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

polserver / polserver / 21108840797

18 Jan 2026 08:35AM UTC coverage: 60.508% (+0.02%) from 60.492%
21108840797

push

github

web-flow
ClangTidy readability-else-after-return (#857)

* trigger tidy

* Automated clang-tidy change: readability-else-after-return

* compile test

* rerun

* Automated clang-tidy change: readability-else-after-return

* trigger..

* Automated clang-tidy change: readability-else-after-return

* manually removed a few

* Automated clang-tidy change: readability-else-after-return

* removed duplicate code

* fix remaining warnings

* fixed scope

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

837 of 1874 new or added lines in 151 files covered. (44.66%)

46 existing lines in 25 files now uncovered.

44448 of 73458 relevant lines covered (60.51%)

525066.38 hits per line

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

55.79
/pol-core/pol/uoscrobj.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/01/24 Shinigami: added ObjMember character.spyonclient2 to get data from packet 0xd9 (Spy
5
 * on Client 2)
6
 * - 2005/03/09 Shinigami: Added Prop Character::Delay_Mod [ms] for WeaponDelay
7
 * - 2005/04/02 Shinigami: UBoat::script_method_id & UBoat::script_method - added optional realm
8
 * param
9
 * - 2005/04/04 Shinigami: Added Prop Character::CreatedAt [PolClock]
10
 * - 2005/08/29 Shinigami: get-/setspyonclient2 renamed to get-/setclientinfo
11
 * - 2005/11/26 Shinigami: changed "strcmp" into "stricmp" to suppress Script Errors
12
 * - 2005/12/09 MuadDib:   Added uclang member for storing UC language from client.
13
 * - 2005/12/09 MuadDib:   Fixed ~ItemGivenEvent not returning items correctly if the script
14
 *                         did nothing with it. Was incorrect str/int comparision for times.
15
 * - 2006/05/16 Shinigami: added Prop Character.Race [RACE_* Constants] to support Elfs
16
 * - 2006/06/15 Austin:    Added mobile.Privs()
17
 * - 2007/07/09 Shinigami: added Prop Character.isUOKR [bool] - UO:KR client used?
18
 * - 2008/07/08 Turley:    Added character.movemode - returns the MoveMode like given in NPCDesc
19
 *                         Added item.stackable - Is item stackable?
20
 * - 2008/12/17 MuadDub:   Added item.tile_layer - returns layer entry from tiledata/tiles.cfg
21
 * - 2009/07/20 MuadDib:   ReAdded on_facing_change() to MBR_FACING: for items.
22
 * - 2009/08/06 MuadDib:   Added gotten_by code for items.
23
 * - 2009/08/31 MuadDib:   Changed layer check on graphic change, excluding mount layer entirely.
24
 * - 2009/09/03 MuadDib:   Relocation of account related cpp/h
25
 *                         Relocation of multi related cpp/h
26
 * - 2009/09/06 Turley:    Removed isUOKR added ClientType
27
 * - 2009/09/22 MuadDib:   Rewrite for Character/NPC to use ar(), ar_mod(), ar_mod(newvalue)
28
 * virtuals.
29
 * - 2009/10/09 Turley:    Added spellbook.spells() & .hasspell() methods
30
 * - 2009/10/10 Turley:    Added spellbook.addspell() & .removespell() methods
31
 * - 2009/10/14 Turley:    Added char.deaf() methods & char.deafened member
32
 * -            MuadDib:   Squelch and Deaf members set to return the gameclock they are in effect
33
 * till.
34
 * - 2009/10/17 Turley:    Moved PrivUpdater to charactr.cpp - Tomi
35
 * - 2009/11/19 Turley:    lightlevel now supports endless duration - Tomi
36
 * - 2009/12/02 Turley:    gargoyle race support
37
 * - 2009/12/03 Turley:    added gargoyle flying movemode
38
 * - 2009/12/21 Turley:    ._method() call fix
39
 *                         multi support of methodscripts
40
 * - 2010/01/15 Turley:    (Tomi) season stuff
41
 * - 2010/02/03 Turley:    MethodScript support for mobiles
42
 * - 2011/12/13 Tomi:      Boat members MBR_COMPONENT, MBR_HULL, MBR_ROPE, MBR_SAILS, MBR_WHEEL,
43
 * MBR_TILLER, MBR_RUDDER, MBR_STORAGE, MBR_WEAPONSLOT
44
 * - 2012/02/02 Tomi:      Added boat member MBR_MULTIID
45
 * - 2012/03/26 Tomi:      Added MBR_LASTCOORD
46
 * - 2012/04/14 Tomi:      Added MBR_FACETID for new map message packet
47
 * - 2012/04/15 Tomi:      Added MBR_EDITABLE for maps
48
 * - 2012/06/02 Tomi:      Added MBR_ACTIVE_SKILL and MBR_CASTING_SPELL for characters
49
 */
50

51

52
#include "uoscrobj.h"
53

54
#include <memory>
55
#include <string>
56

57
#include "../bscript/berror.h"
58
#include "../bscript/dict.h"
59
#include "../bscript/execmodl.h"
60
#include "../bscript/executor.h"
61
#include "../bscript/impstr.h"
62
#include "../bscript/objmembers.h"
63
#include "../bscript/objmethods.h"
64
#include "../clib/clib.h"
65
#include "../clib/stlutil.h"
66
#include "../plib/poltype.h"
67
#include "../plib/uconst.h"
68
#include "accounts/account.h"
69
#include "accounts/acscrobj.h"
70
#include "cmdlevel.h"
71
#include "containr.h"
72
#include "door.h"
73
#include "dynproperties.h"
74
#include "equipdsc.h"
75
#include "exscrobj.h"
76
#include "fnsearch.h"
77
#include "globals/network.h"
78
#include "globals/uvars.h"
79
#include "item/armor.h"
80
#include "item/equipmnt.h"
81
#include "item/item.h"
82
#include "item/itemdesc.h"
83
#include "item/weapon.h"
84
#include "lockable.h"
85
#include "mobile/charactr.h"
86
#include "mobile/corpse.h"
87
#include "mobile/npc.h"
88
#include "mobile/ufacing.h"
89
#include "module/guildmod.h"
90
#include "module/partymod.h"
91
#include "module/uomod.h"
92
#include "multi/boat.h"
93
#include "multi/boatcomp.h"
94
#include "multi/house.h"
95
#include "multi/multi.h"
96
#include "network/cgdata.h"
97
#include "network/client.h"
98
#include "network/packethelper.h"
99
#include "network/packets.h"
100
#include "network/pktdef.h"
101
#include "npctmpl.h"
102
#include "polclass.h"
103
#include "polclock.h"
104
#include "proplist.h"
105
#include "realms/realm.h"
106
#include "realms/realms.h"
107
#include "spelbook.h"
108
#include "statmsg.h"
109
#include "syshookscript.h"
110
#include "tooltips.h"
111
#include "ufunc.h"
112
#include "umap.h"
113
#include "uobject.h"
114
#include "uoclient.h"
115
#include "uoexec.h"
116
#include "uworld.h"
117

118
namespace Pol
119
{
120
namespace Module
121
{
122
using namespace Bscript;
123

124
BApplicObjType euboatrefobjimp_type;
125
BApplicObjType emultirefobjimp_type;
126
BApplicObjType eitemrefobjimp_type;
127
BApplicObjType echaracterrefobjimp_type;
128
BApplicObjType echaracterequipobjimp_type;
129
BApplicObjType storage_area_type;
130
BApplicObjType menu_type;
131
BApplicObjType eclientrefobjimp_type;
132

133
const char* ECharacterRefObjImp::typeOf() const
55✔
134
{
135
  return "MobileRef";
55✔
136
}
137
u8 ECharacterRefObjImp::typeOfInt() const
×
138
{
139
  return OTMobileRef;
×
140
}
141

142
BObjectImp* ECharacterRefObjImp::copy() const
898✔
143
{
144
  return new ECharacterRefObjImp( obj_.get() );
898✔
145
}
146

147
BObjectRef ECharacterRefObjImp::get_member_id( const int id )
725✔
148
{
149
  BObjectImp* result = obj_->get_script_member_id( id );
725✔
150
  if ( result != nullptr )
725✔
151
    return BObjectRef( result );
725✔
152
  return BObjectRef( UninitObject::create() );
×
153
}
154

155
BObjectRef ECharacterRefObjImp::get_member( const char* membername )
×
156
{
157
  ObjMember* objmember = getKnownObjMember( membername );
×
158
  if ( objmember != nullptr )
×
159
    return this->get_member_id( objmember->id );
×
160
  return BObjectRef( UninitObject::create() );
×
161
}
162

163
BObjectRef ECharacterRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
47✔
164
{
165
  BObjectImp* result = nullptr;
47✔
166
  if ( auto* l = impptrIf<BLong>( value ) )
47✔
167
    result = obj_->set_script_member_id( id, l->value() );
34✔
168
  else if ( auto* s = impptrIf<String>( value ) )
13✔
169
    result = obj_->set_script_member_id( id, s->value() );
13✔
170
  else if ( auto* d = impptrIf<Double>( value ) )
×
171
    result = obj_->set_script_member_id_double( id, d->value() );
×
172
  if ( result != nullptr )
47✔
173
    return BObjectRef( result );
41✔
174
  return BObjectRef( UninitObject::create() );
6✔
175
}
176

177
BObjectRef ECharacterRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
×
178
{
179
  ObjMember* objmember = getKnownObjMember( membername );
×
180
  if ( objmember != nullptr )
×
181
    return this->set_member_id( objmember->id, value, copy );
×
182
  return BObjectRef( UninitObject::create() );
×
183
}
184

185
BObjectImp* ECharacterRefObjImp::call_polmethod_id( const int id, Core::UOExecutor& ex,
364✔
186
                                                    bool forcebuiltin )
187
{
188
  // MethodScript for npcs in npc->template_ (npctmpl.h) (aka templatebased)
189
  //             for chars in uoclient_general (uoclient.h) (aka one global definition)
190
  if ( obj_->orphan() )
364✔
191
    return new BError( "That object no longer exists" );
1✔
192
  ObjMethod* mth = getObjMethod( id );
363✔
193
  if ( mth->overridden && !forcebuiltin )
363✔
194
  {
195
    BObjectImp* imp = obj_->custom_script_method( mth->code, ex );
×
196
    if ( imp )
×
197
      return imp;
×
198
  }
199
  BObjectImp* imp = obj_->script_method_id( id, ex );
363✔
200
  if ( imp != nullptr )
363✔
201
    return imp;
363✔
202
  return base::call_polmethod_id( id, ex );
×
203
}
204

205
BObjectImp* ECharacterRefObjImp::call_polmethod( const char* methodname, Core::UOExecutor& ex )
×
206
{
207
  // MethodScript for npcs in npc->template_ (npctmpl.h) (aka templatebased)
208
  //             for chars in uoclient_general (uoclient.h) (aka one global definition)
209
  bool forcebuiltin{ Executor::builtinMethodForced( methodname ) };
×
210
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
211
  if ( objmethod != nullptr )
×
212
    return this->call_polmethod_id( objmethod->id, ex, forcebuiltin );
×
213
  BObjectImp* imp = obj_->custom_script_method( methodname, ex );
×
214
  if ( imp )
×
215
    return imp;
×
216
  return base::call_polmethod( methodname, ex );
×
217
}
218

219
bool ECharacterRefObjImp::isTrue() const
122✔
220
{
221
  return ( !obj_->orphan() && obj_->logged_in() );
122✔
222
}
223

224
bool ECharacterRefObjImp::operator==( const BObjectImp& objimp ) const
32✔
225
{
226
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
32✔
227
  {
228
    const BApplicObjBase* aob =
229
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
32✔
230

231
    if ( aob->object_type() == &echaracterrefobjimp_type )
32✔
232
    {
233
      const ECharacterRefObjImp* chrref_imp =
234
          Clib::explicit_cast<const ECharacterRefObjImp*, const BApplicObjBase*>( aob );
32✔
235

236
      return ( chrref_imp->obj_->serial == obj_->serial );
32✔
237
    }
NEW
238
    return false;
×
239
  }
NEW
240
  if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
×
241
    return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
×
242
  return false;
×
243
}
244

245
bool ECharacterRefObjImp::operator<( const BObjectImp& objimp ) const
×
246
{
247
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
×
248
  {
249
    const BApplicObjBase* aob =
250
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
×
251

252
    if ( aob->object_type() == &echaracterrefobjimp_type )
×
253
    {
254
      const ECharacterRefObjImp* chrref_imp =
255
          Clib::explicit_cast<const ECharacterRefObjImp*, const BApplicObjBase*>( aob );
×
256

257
      return ( chrref_imp->obj_->serial < obj_->serial );
×
258
    }
NEW
259
    if ( aob->object_type() == &eitemrefobjimp_type )
×
260
      return true;
×
261
    return false;
×
262
  }
263
  return base::operator<( objimp );
×
264
}
265

266
const char* EOfflineCharacterRefObjImp::typeOf() const
9✔
267
{
268
  return "OfflineMobileRef";
9✔
269
}
270
u8 EOfflineCharacterRefObjImp::typeOfInt() const
×
271
{
272
  return OTOfflineMobileRef;
×
273
}
274

275
BObjectImp* EOfflineCharacterRefObjImp::copy() const
85✔
276
{
277
  return new EOfflineCharacterRefObjImp( obj_.get() );
85✔
278
}
279

280
bool EOfflineCharacterRefObjImp::isTrue() const
45✔
281
{
282
  return ( !obj_->orphan() );
45✔
283
}
284

285
const char* EItemRefObjImp::typeOf() const
134✔
286
{
287
  return "ItemRef";
134✔
288
}
289
u8 EItemRefObjImp::typeOfInt() const
×
290
{
291
  return OTItemRef;
×
292
}
293

294
BObjectImp* EItemRefObjImp::copy() const
528✔
295
{
296
  return new EItemRefObjImp( obj_.get() );
528✔
297
}
298

299
BObjectRef EItemRefObjImp::get_member_id( const int id )
525✔
300
{
301
  BObjectImp* result = obj_->get_script_member_id( id );
525✔
302
  if ( result != nullptr )
525✔
303
    return BObjectRef( result );
525✔
304
  return BObjectRef( UninitObject::create() );
×
305
}
306

307
BObjectRef EItemRefObjImp::get_member( const char* membername )
×
308
{
309
  ObjMember* objmember = getKnownObjMember( membername );
×
310
  if ( objmember != nullptr )
×
311
    return this->get_member_id( objmember->id );
×
312
  return BObjectRef( UninitObject::create() );
×
313
}
314

315
BObjectRef EItemRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
47✔
316
{
317
  BObjectImp* result = nullptr;
47✔
318
  if ( auto* l = impptrIf<BLong>( value ) )
47✔
319
    result = obj_->set_script_member_id( id, l->value() );
30✔
320
  else if ( auto* s = impptrIf<String>( value ) )
17✔
321
    result = obj_->set_script_member_id( id, s->value() );
9✔
322
  else if ( auto* d = impptrIf<Double>( value ) )
8✔
323
    result = obj_->set_script_member_id_double( id, d->value() );
8✔
324
  if ( result != nullptr )
47✔
325
    return BObjectRef( result );
47✔
326
  return BObjectRef( UninitObject::create() );
×
327
}
328

329
BObjectRef EItemRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
×
330
{
331
  ObjMember* objmember = getKnownObjMember( membername );
×
332
  if ( objmember != nullptr )
×
333
    return this->set_member_id( objmember->id, value, copy );
×
334
  return BObjectRef( UninitObject::create() );
×
335
}
336

337
BObjectImp* EItemRefObjImp::call_polmethod_id( const int id, Core::UOExecutor& ex,
227✔
338
                                               bool forcebuiltin )
339
{
340
  if ( obj_->orphan() )
227✔
341
    return new BError( "That object no longer exists" );
×
342

343
  ObjMethod* mth = getObjMethod( id );
227✔
344
  if ( mth->overridden && !forcebuiltin )
227✔
345
  {
346
    BObjectImp* imp = obj_->custom_script_method( mth->code, ex );
×
347
    if ( imp )
×
348
      return imp;
×
349
  }
350
  BObjectImp* imp = obj_->script_method_id( id, ex );
227✔
351
  if ( imp != nullptr )
227✔
352
    return imp;
227✔
353
  return base::call_polmethod_id( id, ex );
×
354
}
355

356
BObjectImp* EItemRefObjImp::call_polmethod( const char* methodname, Core::UOExecutor& ex )
4✔
357
{
358
  bool forcebuiltin{ Executor::builtinMethodForced( methodname ) };
4✔
359

360
  ObjMethod* objmethod = getKnownObjMethod( methodname );
4✔
361
  if ( objmethod != nullptr )
4✔
362
    return this->call_polmethod_id( objmethod->id, ex, forcebuiltin );
×
363
  Items::Item* item = obj_.get();
4✔
364
  BObjectImp* imp = item->custom_script_method( methodname, ex );
4✔
365
  if ( imp )
4✔
366
    return imp;
4✔
367
  return base::call_polmethod( methodname, ex );
×
368
}
369

370
bool EItemRefObjImp::isTrue() const
226✔
371
{
372
  return ( !obj_->orphan() );
226✔
373
}
374

375
bool EItemRefObjImp::operator==( const BObjectImp& objimp ) const
35✔
376
{
377
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
35✔
378
  {
379
    const BApplicObjBase* aob =
380
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
35✔
381

382
    if ( aob->object_type() == &eitemrefobjimp_type )
35✔
383
    {
384
      const EItemRefObjImp* itemref_imp =
385
          Clib::explicit_cast<const EItemRefObjImp*, const BApplicObjBase*>( aob );
35✔
386

387
      return ( itemref_imp->obj_->serial == obj_->serial );
35✔
388
    }
389
    return false;
×
390
  }
NEW
391
  if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
×
392
    return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
×
393
  return false;
×
394
}
395

396
bool EItemRefObjImp::operator<( const BObjectImp& objimp ) const
×
397
{
398
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
×
399
  {
400
    const BApplicObjBase* aob =
401
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
×
402

403
    if ( aob->object_type() == &eitemrefobjimp_type )
×
404
    {
405
      const EItemRefObjImp* itemref_imp =
406
          Clib::explicit_cast<const EItemRefObjImp*, const BApplicObjBase*>( aob );
×
407

408
      return ( itemref_imp->obj_->serial < obj_->serial );
×
409
    }
410
    return ( &eitemrefobjimp_type < aob->object_type() );
×
411
  }
412

413
  return base::operator<( objimp );
×
414
}
415

416
const char* EUBoatRefObjImp::typeOf() const
×
417
{
418
  return "BoatRef";
×
419
}
420
u8 EUBoatRefObjImp::typeOfInt() const
×
421
{
422
  return OTBoatRef;
×
423
}
424

425
BObjectImp* EUBoatRefObjImp::copy() const
54✔
426
{
427
  return new EUBoatRefObjImp( obj_.get() );
54✔
428
}
429

430
BObjectRef EUBoatRefObjImp::get_member_id( const int id )
6,151✔
431
{
432
  BObjectImp* result = obj_->get_script_member_id( id );
6,151✔
433
  if ( result != nullptr )
6,151✔
434
    return BObjectRef( result );
6,151✔
435
  return BObjectRef( UninitObject::create() );
×
436
}
437

438
BObjectRef EUBoatRefObjImp::get_member( const char* membername )
×
439
{
440
  ObjMember* objmember = getKnownObjMember( membername );
×
441
  if ( objmember != nullptr )
×
442
    return this->get_member_id( objmember->id );
×
443
  return BObjectRef( UninitObject::create() );
×
444
}
445

446
BObjectRef EUBoatRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
2✔
447
{
448
  BObjectImp* result = nullptr;
2✔
449
  if ( auto* l = impptrIf<BLong>( value ) )
2✔
450
    result = obj_->set_script_member_id( id, l->value() );
1✔
451
  else if ( auto* s = impptrIf<String>( value ) )
1✔
452
    result = obj_->set_script_member_id( id, s->value() );
1✔
453
  else if ( auto* d = impptrIf<Double>( value ) )
×
454
    result = obj_->set_script_member_id_double( id, d->value() );
×
455
  if ( result != nullptr )
2✔
456
    return BObjectRef( result );
2✔
457
  return BObjectRef( UninitObject::create() );
×
458
}
459

460
BObjectRef EUBoatRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
×
461
{
462
  ObjMember* objmember = getKnownObjMember( membername );
×
463
  if ( objmember != nullptr )
×
464
    return this->set_member_id( objmember->id, value, copy );
×
465
  return BObjectRef( UninitObject::create() );
×
466
}
467

468
BObjectImp* EUBoatRefObjImp::call_polmethod_id( const int id, Core::UOExecutor& ex,
40✔
469
                                                bool forcebuiltin )
470
{
471
  if ( obj_->orphan() )
40✔
472
    return new BError( "That object no longer exists" );
×
473

474
  ObjMethod* mth = getObjMethod( id );
40✔
475
  if ( mth->overridden && !forcebuiltin )
40✔
476
  {
477
    BObjectImp* imp = obj_->custom_script_method( mth->code, ex );
×
478
    if ( imp )
×
479
      return imp;
×
480
  }
481
  BObjectImp* imp = obj_->script_method_id( id, ex );
40✔
482
  if ( imp != nullptr )
40✔
483
    return imp;
40✔
484
  return base::call_polmethod_id( id, ex );
×
485
}
486

487
BObjectImp* EUBoatRefObjImp::call_polmethod( const char* methodname, Core::UOExecutor& ex )
3✔
488
{
489
  bool forcebuiltin{ Executor::builtinMethodForced( methodname ) };
3✔
490
  ObjMethod* objmethod = getKnownObjMethod( methodname );
3✔
491
  if ( objmethod != nullptr )
3✔
492
    return this->call_polmethod_id( objmethod->id, ex, forcebuiltin );
×
493

494
  Multi::UBoat* boat = obj_.get();
3✔
495
  BObjectImp* imp = boat->custom_script_method( methodname, ex );
3✔
496
  if ( imp )
3✔
497
    return imp;
3✔
498

499
  return base::call_polmethod( methodname, ex );
×
500
}
501

502
bool EUBoatRefObjImp::isTrue() const
99✔
503
{
504
  return ( !obj_->orphan() );
99✔
505
}
506

507
bool EUBoatRefObjImp::operator==( const BObjectImp& objimp ) const
×
508
{
509
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
×
510
  {
511
    const BApplicObjBase* aob =
512
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
×
513

514
    if ( aob->object_type() == &euboatrefobjimp_type )
×
515
    {
516
      const EUBoatRefObjImp* boatref_imp =
517
          Clib::explicit_cast<const EUBoatRefObjImp*, const BApplicObjBase*>( aob );
×
518

519
      return ( boatref_imp->obj_->serial == obj_->serial );
×
520
    }
521
    return false;
×
522
  }
NEW
523
  if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
×
524
    return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
×
525
  return false;
×
526
}
527

528
BObjectImp* EMultiRefObjImp::call_polmethod( const char* methodname, Core::UOExecutor& ex )
×
529
{
530
  bool forcebuiltin{ Executor::builtinMethodForced( methodname ) };
×
531
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
532
  if ( objmethod != nullptr )
×
533
    return this->call_polmethod_id( objmethod->id, ex, forcebuiltin );
×
534
  Multi::UMulti* multi = obj_.get();
×
535
  BObjectImp* imp = multi->custom_script_method( methodname, ex );
×
536
  if ( imp )
×
537
    return imp;
×
538
  return base::call_polmethod( methodname, ex );
×
539
}
540

541
BObjectImp* EMultiRefObjImp::call_polmethod_id( const int id, Core::UOExecutor& ex,
14✔
542
                                                bool forcebuiltin )
543
{
544
  Multi::UMulti* multi = obj_.get();
14✔
545
  if ( multi->orphan() )
14✔
546
    return new BError( "That object no longer exists" );
×
547

548
  ObjMethod* mth = getObjMethod( id );
14✔
549
  if ( mth->overridden && !forcebuiltin )
14✔
550
  {
551
    BObjectImp* imp = multi->custom_script_method( mth->code, ex );
×
552
    if ( imp )
×
553
      return imp;
×
554
  }
555

556
  BObjectImp* imp = multi->script_method_id( id, ex );
14✔
557
  if ( imp != nullptr )
14✔
558
    return imp;
14✔
559
  return base::call_polmethod_id( id, ex, forcebuiltin );
×
560
}
561

562
const char* EMultiRefObjImp::typeOf() const
44✔
563
{
564
  return "MultiRef";
44✔
565
}
566
u8 EMultiRefObjImp::typeOfInt() const
×
567
{
568
  return OTMultiRef;
×
569
}
570

571
BObjectImp* EMultiRefObjImp::copy() const
57✔
572
{
573
  return new EMultiRefObjImp( obj_.get() );
57✔
574
}
575

576
BObjectRef EMultiRefObjImp::get_member_id( const int id )
53✔
577
{
578
  BObjectImp* result = obj_->get_script_member_id( id );
53✔
579
  if ( result != nullptr )
53✔
580
    return BObjectRef( result );
53✔
581
  return BObjectRef( UninitObject::create() );
×
582
}
583

584
BObjectRef EMultiRefObjImp::get_member( const char* membername )
×
585
{
586
  ObjMember* objmember = getKnownObjMember( membername );
×
587
  if ( objmember != nullptr )
×
588
    return this->get_member_id( objmember->id );
×
589
  return BObjectRef( UninitObject::create() );
×
590
}
591

592
BObjectRef EMultiRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
2✔
593
{
594
  BObjectImp* result = nullptr;
2✔
595
  if ( auto* l = impptrIf<BLong>( value ) )
2✔
596
    result = obj_->set_script_member_id( id, l->value() );
×
597
  else if ( auto* s = impptrIf<String>( value ) )
2✔
598
    result = obj_->set_script_member_id( id, s->value() );
2✔
599
  else if ( auto* d = impptrIf<Double>( value ) )
×
600
    result = obj_->set_script_member_id_double( id, d->value() );
×
601
  if ( result != nullptr )
2✔
602
    return BObjectRef( result );
2✔
603
  return BObjectRef( UninitObject::create() );
×
604
}
605
BObjectRef EMultiRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
×
606
{
607
  ObjMember* objmember = getKnownObjMember( membername );
×
608
  if ( objmember != nullptr )
×
609
    return this->set_member_id( objmember->id, value, copy );
×
610
  return BObjectRef( UninitObject::create() );
×
611
}
612

613
bool EMultiRefObjImp::isTrue() const
22✔
614
{
615
  return ( !obj_->orphan() );
22✔
616
}
617

618
bool EMultiRefObjImp::operator==( const BObjectImp& objimp ) const
3✔
619
{
620
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
3✔
621
  {
622
    const BApplicObjBase* aob =
623
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
3✔
624

625
    if ( aob->object_type() == &emultirefobjimp_type )
3✔
626
    {
627
      const EMultiRefObjImp* multiref_imp =
628
          Clib::explicit_cast<const EMultiRefObjImp*, const BApplicObjBase*>( aob );
3✔
629

630
      return ( multiref_imp->obj_->serial == obj_->serial );
3✔
631
    }
632
    return false;
×
633
  }
NEW
634
  if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
×
635
    return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
×
636
  return false;
×
637
}
638
}  // namespace Module
639

640
namespace Core
641
{
642
using namespace Bscript;
643

644
BObjectImp* UObject::get_script_member_id( const int id ) const
7,700✔
645
{
646
  if ( orphan() )
7,700✔
647
    return new UninitObject;
14✔
648
  switch ( id )
7,686✔
649
  {
650
  case MBR_X:
182✔
651
    return new BLong( x() );
182✔
652
    break;
653
  case MBR_Y:
170✔
654
    return new BLong( y() );
170✔
655
    break;
656
  case MBR_Z:
151✔
657
    return new BLong( z() );
151✔
658
    break;
659
  case MBR_NAME:
43✔
660
    return new String( name() );
43✔
661
    break;
662
  case MBR_OBJTYPE:
2✔
663
    return new BLong( objtype_ );
2✔
664
    break;
665
  case MBR_GRAPHIC:
5✔
666
    return new BLong( graphic );
5✔
667
    break;
668
  case MBR_SERIAL:
522✔
669
    return new BLong( serial );
522✔
670
    break;
671
  case MBR_COLOR:
1✔
672
    return new BLong( color );
1✔
673
    break;
674
  case MBR_HEIGHT:
22✔
675
    return new BLong( height );
22✔
676
    break;
677
  case MBR_FACING:
5✔
678
    return new BLong( facing );
5✔
679
    break;
680
  case MBR_DIRTY:
×
681
    return new BLong( dirty() ? 1 : 0 );
×
682
    break;
683
  case MBR_WEIGHT:
42✔
684
    return new BLong( weight() );
42✔
685
    break;
686
  case MBR_MULTI:
7✔
687
    if ( realm() != nullptr )
7✔
688
    {
689
      Multi::UMulti* multi;
690
      if ( nullptr != ( multi = realm()->find_supporting_multi( pos3d() ) ) )
7✔
691
        return multi->make_ref();
3✔
692
      return new BLong( 0 );
4✔
693
    }
694
    else
695
      return new BLong( 0 );
×
696
    break;
697
  case MBR_REALM:
6,056✔
698
    if ( realm() != nullptr )
6,056✔
699
      return new String( realm()->name() );
6,056✔
700
    else
701
      return new BError( "object does not belong to a realm." );
×
702
    break;
703
  case MBR_SPECIFIC_NAME:
×
704
    return new BLong( specific_name() );
×
705
  default:
478✔
706
    return nullptr;
478✔
707
  }
708
}
709

710
BObjectImp* UObject::get_script_member( const char* membername ) const
×
711
{
712
  ObjMember* objmember = getKnownObjMember( membername );
×
713
  if ( objmember != nullptr )
×
714
    return this->get_script_member_id( objmember->id );
×
715
  return nullptr;
×
716
}
717

718
BObjectImp* UObject::set_script_member_id( const int id, const std::string& value )
38✔
719
{
720
  if ( orphan() )
38✔
721
    return new UninitObject;
×
722

723
  set_dirty();
38✔
724
  switch ( id )
38✔
725
  {
726
  case MBR_NAME:
14✔
727
    if ( ismobile() && ( value.empty() || isspace( value[0] ) ) )
14✔
728
      return new BError( "mobile.name must not be empty, and must not begin with a space" );
×
729
    setname( value );
14✔
730
    return new String( name() );
14✔
731
    break;
732
  default:
24✔
733
    return nullptr;
24✔
734
  }
735
}
736

737
BObjectImp* UObject::set_script_member( const char* membername, const std::string& value )
×
738
{
739
  ObjMember* objmember = getKnownObjMember( membername );
×
740
  if ( objmember != nullptr )
×
741
    return this->set_script_member_id( objmember->id, value );
×
742
  return nullptr;
×
743
}
744

745
BObjectImp* UObject::set_script_member_id( const int id, int value )
235✔
746
{
747
  if ( orphan() )
235✔
748
    return new UninitObject;
×
749

750
  set_dirty();
235✔
751
  switch ( id )
235✔
752
  {
753
  case MBR_GRAPHIC:
1✔
754
    setgraphic( Clib::clamp_convert<u16>( value ) );
1✔
755
    return new BLong( graphic );
1✔
756
  case MBR_COLOR:
1✔
757
  {
758
    bool res = setcolor( Clib::clamp_convert<u16>( value ) );
1✔
759
    if ( !res )  // TODO log?
1✔
760
      return new BError( "Invalid color value " + Clib::hexint( value ) );
×
761
    return new BLong( color );
1✔
762
  }
763
  default:
233✔
764
    return nullptr;
233✔
765
  }
766
}
767

768
BObjectImp* UObject::set_script_member( const char* membername, int value )
×
769
{
770
  ObjMember* objmember = getKnownObjMember( membername );
×
771
  if ( objmember != nullptr )
×
772
    return this->set_script_member_id( objmember->id, value );
×
773
  return nullptr;
×
774
}
775

776
BObjectImp* UObject::set_script_member_id_double( const int /*id*/, double /*value*/ )
19✔
777
{
778
  set_dirty();
19✔
779
  return nullptr;
19✔
780
}
781

782
BObjectImp* UObject::set_script_member_double( const char* membername, double value )
4✔
783
{
784
  ObjMember* objmember = getKnownObjMember( membername );
4✔
785
  if ( objmember != nullptr )
4✔
786
    return this->set_script_member_id_double( objmember->id, value );
4✔
787
  return nullptr;
×
788
}
789
}  // namespace Core
790

791
namespace Items
792
{
793
using namespace Bscript;
794

795
BObjectImp* Item::get_script_member_id( const int id ) const
6,832✔
796
{
797
  BObjectImp* imp = base::get_script_member_id( id );
6,832✔
798
  if ( imp != nullptr )
6,832✔
799
    return imp;
6,619✔
800

801
  switch ( id )
213✔
802
  {
803
  case MBR_AMOUNT:
4✔
804
    return new BLong( amount_ );
4✔
805
    break;
806
  case MBR_LAYER:
×
807
    return new BLong( layer );
×
808
    break;
809
  case MBR_TILE_LAYER:
×
810
    return new BLong( tile_layer );
×
811
    break;
812
  case MBR_CONTAINER:
8✔
813
    if ( container != nullptr )
8✔
814
      return container->make_ref();
8✔
815
    return new BLong( 0 );
×
816
    break;
817
  case MBR_USESCRIPT:
1✔
818
    return new String( on_use_script_ );
1✔
819
    break;
820
  case MBR_SNOOPSCRIPT:
1✔
821
    return new String( snoop_script_ );
1✔
822
    break;
823
  case MBR_EQUIPSCRIPT:
1✔
824
    return new String( equip_script_ );
1✔
825
    break;
826
  case MBR_UNEQUIPSCRIPT:
1✔
827
    return new String( unequip_script_ );
1✔
828
    break;
829
  case MBR_DESC:
×
830
    return new String( description() );
×
831
    break;
832
  case MBR_MOVABLE:
1✔
833
    return new BLong( movable() ? 1 : 0 );
1✔
834
    break;
835
  case MBR_INVISIBLE:
1✔
836
    return new BLong( invisible() ? 1 : 0 );
1✔
837
    break;
838
  case MBR_CURSED:
2✔
839
    return new BLong( cursed() ? 1 : 0 );
2✔
840
    break;
841
  case MBR_DECAYAT:
1✔
842
    return new BLong( decayat_gameclock_ );
1✔
843
    break;
844
  case MBR_SELLPRICE:
1✔
845
    return new BLong( sellprice() );
1✔
846
    break;
847
  case MBR_BUYPRICE:
1✔
848
    return new BLong( buyprice() );
1✔
849
    break;
850
  case MBR_NEWBIE:
1✔
851
    return new BLong( newbie() ? 1 : 0 );
1✔
852
    break;
853
  case MBR_INSURED:
1✔
854
    return new BLong( insured() ? 1 : 0 );
1✔
855
    break;
856
  case MBR_ITEM_COUNT:
×
857
    return new BLong( item_count() );
×
858
    break;
859
  case MBR_STACKABLE:
×
860
    return new BLong( stackable() ? 1 : 0 );
×
861
    break;
862
  case MBR_SAVEONEXIT:
×
863
    return new BLong( saveonexit() );
×
864
    break;
865
  case MBR_FIRE_RESIST:
1✔
866
    return new BLong( fire_resist().sum() );
1✔
867
    break;
868
  case MBR_COLD_RESIST:
1✔
869
    return new BLong( cold_resist().sum() );
1✔
870
    break;
871
  case MBR_ENERGY_RESIST:
1✔
872
    return new BLong( energy_resist().sum() );
1✔
873
    break;
874
  case MBR_POISON_RESIST:
1✔
875
    return new BLong( poison_resist().sum() );
1✔
876
    break;
877
  case MBR_PHYSICAL_RESIST:
1✔
878
    return new BLong( physical_resist().sum() );
1✔
879
    break;
880
  case MBR_LOWER_REAG_COST:
1✔
881
    return new BLong( lower_reagent_cost().sum() );
1✔
882
    break;
883
  case MBR_SPELL_DAMAGE_INCREASE:
1✔
884
    return new BLong( spell_damage_increase().sum() );
1✔
885
    break;
886
  case MBR_FASTER_CASTING:
1✔
887
    return new BLong( faster_casting().sum() );
1✔
888
    break;
889
  case MBR_FASTER_CAST_RECOVERY:
1✔
890
    return new BLong( faster_cast_recovery().sum() );
1✔
891
    break;
892
  case MBR_DEFENCE_CHANCE_INCREASE:
1✔
893
    return new BLong( defence_increase().sum() );
1✔
894
    break;
895
  case MBR_DEFENCE_CHANCE_INCREASE_CAP:
1✔
896
    return new BLong( defence_increase_cap().sum() );
1✔
897
    break;
898
  case MBR_LOWER_MANA_COST:
1✔
899
    return new BLong( lower_mana_cost().sum() );
1✔
900
    break;
901
  case MBR_HIT_CHANCE:
1✔
902
    return new BLong( hit_chance().sum() );
1✔
903
    break;
904
  case MBR_FIRE_RESIST_CAP:
1✔
905
    return new BLong( fire_resist_cap().sum() );
1✔
906
    break;
907
  case MBR_COLD_RESIST_CAP:
1✔
908
    return new BLong( cold_resist_cap().sum() );
1✔
909
    break;
910
  case MBR_ENERGY_RESIST_CAP:
1✔
911
    return new BLong( energy_resist_cap().sum() );
1✔
912
    break;
913
  case MBR_POISON_RESIST_CAP:
1✔
914
    return new BLong( poison_resist_cap().sum() );
1✔
915
    break;
916
  case MBR_PHYSICAL_RESIST_CAP:
1✔
917
    return new BLong( physical_resist_cap().sum() );
1✔
918
    break;
919
  case MBR_LUCK:
1✔
920
    return new BLong( luck().sum() );
1✔
921
    break;
922
  case MBR_SWING_SPEED_INCREASE:
1✔
923
    return new BLong( swing_speed_increase().sum() );
1✔
924
    break;
925
  case MBR_MIN_ATTACK_RANGE_INCREASE:
1✔
926
    return new BLong( min_attack_range_increase().sum() );
1✔
927
    break;
928
  case MBR_MAX_ATTACK_RANGE_INCREASE:
1✔
929
    return new BLong( max_attack_range_increase().sum() );
1✔
930
    break;
931
  case MBR_FIRE_RESIST_MOD:
1✔
932
    return new BLong( fire_resist().mod );
1✔
933
    break;
934
  case MBR_COLD_RESIST_MOD:
1✔
935
    return new BLong( cold_resist().mod );
1✔
936
    break;
937
  case MBR_ENERGY_RESIST_MOD:
1✔
938
    return new BLong( energy_resist().mod );
1✔
939
    break;
940
  case MBR_POISON_RESIST_MOD:
1✔
941
    return new BLong( poison_resist().mod );
1✔
942
    break;
943
  case MBR_PHYSICAL_RESIST_MOD:
1✔
944
    return new BLong( physical_resist().mod );
1✔
945
    break;
946
  case MBR_FIRE_DAMAGE:
1✔
947
    return new BLong( fire_damage().sum() );
1✔
948
    break;
949
  case MBR_COLD_DAMAGE:
1✔
950
    return new BLong( cold_damage().sum() );
1✔
951
    break;
952
  case MBR_ENERGY_DAMAGE:
1✔
953
    return new BLong( energy_damage().sum() );
1✔
954
    break;
955
  case MBR_POISON_DAMAGE:
1✔
956
    return new BLong( poison_damage().sum() );
1✔
957
    break;
958
  case MBR_PHYSICAL_DAMAGE:
1✔
959
    return new BLong( physical_damage().sum() );
1✔
960
    break;
961
  case MBR_FIRE_DAMAGE_MOD:
1✔
962
    return new BLong( fire_damage().mod );
1✔
963
    break;
964
  case MBR_COLD_DAMAGE_MOD:
1✔
965
    return new BLong( cold_damage().mod );
1✔
966
    break;
967
  case MBR_ENERGY_DAMAGE_MOD:
1✔
968
    return new BLong( energy_damage().mod );
1✔
969
    break;
970
  case MBR_POISON_DAMAGE_MOD:
1✔
971
    return new BLong( poison_damage().mod );
1✔
972
    break;
973
  case MBR_PHYSICAL_DAMAGE_MOD:
1✔
974
    return new BLong( physical_damage().mod );
1✔
975
    break;
976
  case MBR_LOWER_REAG_COST_MOD:
1✔
977
    return new BLong( lower_reagent_cost().mod );
1✔
978
    break;
979
  case MBR_SPELL_DAMAGE_INCREASE_MOD:
1✔
980
    return new BLong( spell_damage_increase().mod );
1✔
981
    break;
982
  case MBR_FASTER_CASTING_MOD:
1✔
983
    return new BLong( faster_casting().mod );
1✔
984
    break;
985
  case MBR_FASTER_CAST_RECOVERY_MOD:
1✔
986
    return new BLong( faster_cast_recovery().mod );
1✔
987
    break;
988
  case MBR_DEFENCE_CHANCE_INCREASE_MOD:
1✔
989
    return new BLong( defence_increase().mod );
1✔
990
    break;
991
  case MBR_DEFENCE_CHANCE_INCREASE_CAP_MOD:
1✔
992
    return new BLong( defence_increase_cap().mod );
1✔
993
    break;
994
  case MBR_LOWER_MANA_COST_MOD:
1✔
995
    return new BLong( lower_mana_cost().mod );
1✔
996
    break;
997
  case MBR_HIT_CHANCE_MOD:
1✔
998
    return new BLong( hit_chance().mod );
1✔
999
    break;
1000
  case MBR_FIRE_RESIST_CAP_MOD:
1✔
1001
    return new BLong( fire_resist_cap().mod );
1✔
1002
    break;
1003
  case MBR_COLD_RESIST_CAP_MOD:
1✔
1004
    return new BLong( cold_resist_cap().mod );
1✔
1005
    break;
1006
  case MBR_ENERGY_RESIST_CAP_MOD:
1✔
1007
    return new BLong( energy_resist_cap().mod );
1✔
1008
    break;
1009
  case MBR_POISON_RESIST_CAP_MOD:
1✔
1010
    return new BLong( poison_resist_cap().mod );
1✔
1011
    break;
1012
  case MBR_PHYSICAL_RESIST_CAP_MOD:
1✔
1013
    return new BLong( physical_resist_cap().mod );
1✔
1014
    break;
1015
  case MBR_LUCK_MOD:
1✔
1016
    return new BLong( luck().mod );
1✔
1017
    break;
1018
  case MBR_SWING_SPEED_INCREASE_MOD:
1✔
1019
    return new BLong( swing_speed_increase().mod );
1✔
1020
    break;
1021
  case MBR_MIN_ATTACK_RANGE_INCREASE_MOD:
1✔
1022
    return new BLong( min_attack_range_increase().mod );
1✔
1023
    break;
1024
  case MBR_MAX_ATTACK_RANGE_INCREASE_MOD:
1✔
1025
    return new BLong( max_attack_range_increase().mod );
1✔
1026
    break;
1027

1028
  case MBR_GETGOTTENBY:
×
1029
    if ( has_gotten_by() )
×
1030
      return new Module::ECharacterRefObjImp( gotten_by() );
×
1031
    return new BError( "Gotten By nullptr" );
×
1032
    break;
1033
  case MBR_PROCESS:
4✔
1034
  {
1035
    Module::UOExecutorModule* proc = process();
4✔
1036
    if ( proc )
4✔
1037
    {
1038
      Core::UOExecutor* executor = static_cast<Core::UOExecutor*>( &proc->exec );
3✔
1039
      return new Core::ScriptExObjImp( executor );
3✔
1040
    }
1041
    return new BError( "No script running" );
1✔
1042
    break;
1043
  }
1044
  case MBR_DOUBLECLICKRANGE:
×
1045
  {
1046
    const ItemDesc& itemdesc = this->itemdesc();
×
1047
    return new BLong( itemdesc.doubleclick_range );
×
1048
    break;
1049
  }
1050
  case MBR_QUALITY:
1✔
1051
    return new Double( quality() );
1✔
1052
    break;
1053
  case MBR_HP:
5✔
1054
    return new BLong( hp_ );
5✔
1055
    break;
1056
  case MBR_MAXHP_MOD:
1✔
1057
    return new BLong( maxhp_mod() );
1✔
1058
    break;
1059
  case MBR_MAXHP:
×
1060
    return new BLong( Clib::clamp_convert<s32>( maxhp() * quality() ) );
×
1061
    break;
1062
  case MBR_NAME_SUFFIX:
1✔
1063
    return new String( name_suffix() );
1✔
1064
    break;
1065
  case MBR_HOUSE:
×
1066
    if ( house() != nullptr )
×
1067
      return house()->make_ref();
×
1068
    return new BError( "This is a not component of any house" );
×
1069
    break;
1070
  case MBR_NO_DROP:
2✔
1071
    return new BLong( no_drop() );
2✔
1072
  case MBR_CHARACTER_OWNER:
3✔
1073
  {
1074
    Mobile::Character* owner = GetCharacterOwner();
3✔
1075
    if ( owner != nullptr )
3✔
1076
    {
1077
      return new Module::EOfflineCharacterRefObjImp( owner );
3✔
1078
    }
1079
    return new BError( "This item is not owned by any character" );
×
1080
    break;
1081
  }
1082
  case MBR_WEIGHT_MULTIPLIER_MOD:
1✔
1083
    return new Double( weight_multiplier_mod() );
1✔
1084
    break;
1085
  default:
116✔
1086
    return nullptr;
116✔
1087
  }
1088
}
1089

1090
BObjectImp* Item::get_script_member( const char* membername ) const
77✔
1091
{
1092
  ObjMember* objmember = getKnownObjMember( membername );
77✔
1093
  if ( objmember != nullptr )
77✔
1094
    return this->get_script_member_id( objmember->id );
77✔
1095
  return nullptr;
×
1096
}
1097

1098
BObjectImp* Item::set_script_member_id( const int id, const std::string& value )
21✔
1099
{
1100
  BObjectImp* imp = base::set_script_member_id( id, value );
21✔
1101
  if ( imp != nullptr )
21✔
1102
    return imp;
14✔
1103

1104
  switch ( id )
7✔
1105
  {
1106
  case MBR_USESCRIPT:
1✔
1107
    on_use_script_ = value;
1✔
1108
    return new String( value );
1✔
1109
  case MBR_SNOOPSCRIPT:
1✔
1110
    snoop_script_ = value;
1✔
1111
    return new String( value );
1✔
1112
  case MBR_EQUIPSCRIPT:
1✔
1113
    equip_script_ = value;
1✔
1114
    return new String( value );
1✔
1115
  case MBR_UNEQUIPSCRIPT:
1✔
1116
    unequip_script_ = value;
1✔
1117
    return new String( value );
1✔
1118
  case MBR_NAME_SUFFIX:
1✔
1119
    set_dirty();
1✔
1120
    increv();
1✔
1121
    send_object_cache_to_inrange( this );
1✔
1122
    name_suffix( value );
1✔
1123
    return new String( value );
1✔
1124

1125
  default:
2✔
1126
    return nullptr;
2✔
1127
  }
1128
}
1129

1130
BObjectImp* Item::set_script_member( const char* membername, const std::string& value )
7✔
1131
{
1132
  ObjMember* objmember = getKnownObjMember( membername );
7✔
1133
  if ( objmember != nullptr )
7✔
1134
    return this->set_script_member_id( objmember->id, value );
7✔
1135
  return nullptr;
×
1136
}
1137

1138
BObjectImp* Item::set_script_member_id( const int id, int value )
137✔
1139
{
1140
  BObjectImp* imp = base::set_script_member_id( id, value );
137✔
1141
  if ( imp != nullptr )
137✔
1142
    return imp;
2✔
1143

1144
  switch ( id )
135✔
1145
  {
1146
  case MBR_MOVABLE:
15✔
1147
    restart_decay_timer();
15✔
1148
    movable( value ? true : false );
15✔
1149
    increv();
15✔
1150
    return new BLong( movable() );
15✔
1151
  case MBR_INVISIBLE:
2✔
1152
    restart_decay_timer();
2✔
1153
    invisible( value ? true : false );
2✔
1154
    increv();
2✔
1155
    return new BLong( invisible() );
2✔
1156
  case MBR_CURSED:
1✔
1157
    restart_decay_timer();
1✔
1158
    cursed( value ? true : false );
1✔
1159
    increv();
1✔
1160
    return new BLong( cursed() );
1✔
1161
  case MBR_DECAYAT:
1✔
1162
    decayat_gameclock_ = value;
1✔
1163
    return new BLong( decayat_gameclock_ );
1✔
1164
  case MBR_SELLPRICE:
1✔
1165
    sellprice( value );
1✔
1166
    return new BLong( value );
1✔
1167
  case MBR_BUYPRICE:
1✔
1168
    buyprice( value );
1✔
1169
    return new BLong( value );
1✔
1170
  case MBR_NEWBIE:
1✔
1171
    restart_decay_timer();
1✔
1172
    newbie( value ? true : false );
1✔
1173
    increv();
1✔
1174
    return new BLong( newbie() );
1✔
1175
  case MBR_INSURED:
1✔
1176
    restart_decay_timer();
1✔
1177
    insured( value ? true : false );
1✔
1178
    increv();
1✔
1179
    return new BLong( insured() );
1✔
1180
  case MBR_FACING:
1✔
1181
    setfacing( (u8)value );
1✔
1182
    return new BLong( facing );
1✔
1183
  case MBR_SAVEONEXIT:
×
1184
    saveonexit( value ? true : false );
×
1185
    return new BLong( saveonexit() );
×
1186
  case MBR_FIRE_RESIST_MOD:
3✔
1187
    fire_resist( fire_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1188
    if ( container != nullptr )
3✔
1189
    {
1190
      if ( Core::IsCharacter( container->serial ) )
2✔
1191
      {
1192
        Mobile::Character* chr = container->get_chr_owner();
2✔
1193
        if ( chr != nullptr )
2✔
1194
          chr->refresh_ar();
2✔
1195
      }
1196
    }
1197
    return new BLong( fire_resist().mod );
3✔
1198
    break;
1199
  case MBR_COLD_RESIST_MOD:
3✔
1200
    cold_resist( cold_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1201
    if ( container != nullptr )
3✔
1202
    {
1203
      if ( Core::IsCharacter( container->serial ) )
2✔
1204
      {
1205
        Mobile::Character* chr = container->get_chr_owner();
2✔
1206
        if ( chr != nullptr )
2✔
1207
          chr->refresh_ar();
2✔
1208
      }
1209
    }
1210
    return new BLong( cold_resist().mod );
3✔
1211
    break;
1212
  case MBR_ENERGY_RESIST_MOD:
3✔
1213
    energy_resist( energy_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1214
    if ( container != nullptr )
3✔
1215
    {
1216
      if ( Core::IsCharacter( container->serial ) )
2✔
1217
      {
1218
        Mobile::Character* chr = container->get_chr_owner();
2✔
1219
        if ( chr != nullptr )
2✔
1220
          chr->refresh_ar();
2✔
1221
      }
1222
    }
1223
    return new BLong( energy_resist().mod );
3✔
1224
    break;
1225
  case MBR_POISON_RESIST_MOD:
3✔
1226
    poison_resist( poison_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1227
    if ( container != nullptr )
3✔
1228
    {
1229
      if ( Core::IsCharacter( container->serial ) )
2✔
1230
      {
1231
        Mobile::Character* chr = container->get_chr_owner();
2✔
1232
        if ( chr != nullptr )
2✔
1233
          chr->refresh_ar();
2✔
1234
      }
1235
    }
1236
    return new BLong( poison_resist().mod );
3✔
1237
    break;
1238
  case MBR_PHYSICAL_RESIST_MOD:
3✔
1239
    physical_resist( physical_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1240
    if ( container != nullptr )
3✔
1241
    {
1242
      if ( Core::IsCharacter( container->serial ) )
2✔
1243
      {
1244
        Mobile::Character* chr = container->get_chr_owner();
2✔
1245
        if ( chr != nullptr )
2✔
1246
          chr->refresh_ar();
2✔
1247
      }
1248
    }
1249
    return new BLong( physical_resist().mod );
3✔
1250
    break;
1251
  case MBR_FIRE_RESIST_CAP_MOD:
2✔
1252
    fire_resist_cap( fire_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1253
    if ( container != nullptr )
2✔
1254
    {
1255
      if ( Core::IsCharacter( container->serial ) )
1✔
1256
      {
1257
        Mobile::Character* chr = container->get_chr_owner();
1✔
1258
        if ( chr != nullptr )
1✔
1259
          chr->refresh_ar();
1✔
1260
      }
1261
    }
1262
    return new BLong( fire_resist_cap().mod );
2✔
1263
    break;
1264
  case MBR_COLD_RESIST_CAP_MOD:
2✔
1265
    cold_resist_cap( cold_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1266
    if ( container != nullptr )
2✔
1267
    {
1268
      if ( Core::IsCharacter( container->serial ) )
1✔
1269
      {
1270
        Mobile::Character* chr = container->get_chr_owner();
1✔
1271
        if ( chr != nullptr )
1✔
1272
          chr->refresh_ar();
1✔
1273
      }
1274
    }
1275
    return new BLong( cold_resist_cap().mod );
2✔
1276
    break;
1277
  case MBR_ENERGY_RESIST_CAP_MOD:
2✔
1278
    energy_resist_cap( energy_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1279
    if ( container != nullptr )
2✔
1280
    {
1281
      if ( Core::IsCharacter( container->serial ) )
1✔
1282
      {
1283
        Mobile::Character* chr = container->get_chr_owner();
1✔
1284
        if ( chr != nullptr )
1✔
1285
          chr->refresh_ar();
1✔
1286
      }
1287
    }
1288
    return new BLong( energy_resist_cap().mod );
2✔
1289
    break;
1290
  case MBR_POISON_RESIST_CAP_MOD:
2✔
1291
    poison_resist_cap( poison_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1292
    if ( container != nullptr )
2✔
1293
    {
1294
      if ( Core::IsCharacter( container->serial ) )
1✔
1295
      {
1296
        Mobile::Character* chr = container->get_chr_owner();
1✔
1297
        if ( chr != nullptr )
1✔
1298
          chr->refresh_ar();
1✔
1299
      }
1300
    }
1301
    return new BLong( poison_resist_cap().mod );
2✔
1302
    break;
1303
  case MBR_PHYSICAL_RESIST_CAP_MOD:
2✔
1304
    physical_resist_cap( physical_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1305
    if ( container != nullptr )
2✔
1306
    {
1307
      if ( Core::IsCharacter( container->serial ) )
1✔
1308
      {
1309
        Mobile::Character* chr = container->get_chr_owner();
1✔
1310
        if ( chr != nullptr )
1✔
1311
          chr->refresh_ar();
1✔
1312
      }
1313
    }
1314
    return new BLong( physical_resist_cap().mod );
2✔
1315
    break;
1316

1317
  case MBR_FIRE_DAMAGE_MOD:
3✔
1318
    fire_damage( fire_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1319
    if ( container != nullptr )
3✔
1320
    {
1321
      if ( Core::IsCharacter( container->serial ) )
2✔
1322
      {
1323
        Mobile::Character* chr = container->get_chr_owner();
2✔
1324
        if ( chr != nullptr )
2✔
1325
          chr->refresh_ar();
2✔
1326
      }
1327
    }
1328
    return new BLong( fire_damage().mod );
3✔
1329
    break;
1330
  case MBR_COLD_DAMAGE_MOD:
3✔
1331
    cold_damage( cold_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1332
    if ( container != nullptr )
3✔
1333
    {
1334
      if ( Core::IsCharacter( container->serial ) )
2✔
1335
      {
1336
        Mobile::Character* chr = container->get_chr_owner();
2✔
1337
        if ( chr != nullptr )
2✔
1338
          chr->refresh_ar();
2✔
1339
      }
1340
    }
1341
    return new BLong( cold_damage().mod );
3✔
1342
    break;
1343
  case MBR_ENERGY_DAMAGE_MOD:
3✔
1344
    energy_damage( energy_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1345
    if ( container != nullptr )
3✔
1346
    {
1347
      if ( Core::IsCharacter( container->serial ) )
2✔
1348
      {
1349
        Mobile::Character* chr = container->get_chr_owner();
2✔
1350
        if ( chr != nullptr )
2✔
1351
          chr->refresh_ar();
2✔
1352
      }
1353
    }
1354
    return new BLong( energy_damage().mod );
3✔
1355
    break;
1356
  case MBR_POISON_DAMAGE_MOD:
3✔
1357
    poison_damage( poison_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1358
    if ( container != nullptr )
3✔
1359
    {
1360
      if ( Core::IsCharacter( container->serial ) )
2✔
1361
      {
1362
        Mobile::Character* chr = container->get_chr_owner();
2✔
1363
        if ( chr != nullptr )
2✔
1364
          chr->refresh_ar();
2✔
1365
      }
1366
    }
1367
    return new BLong( poison_damage().mod );
3✔
1368
    break;
1369

1370
  case MBR_PHYSICAL_DAMAGE_MOD:
3✔
1371
    physical_damage( physical_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1372
    if ( container != nullptr )
3✔
1373
    {
1374
      if ( Core::IsCharacter( container->serial ) )
2✔
1375
      {
1376
        Mobile::Character* chr = container->get_chr_owner();
2✔
1377
        if ( chr != nullptr )
2✔
1378
          chr->refresh_ar();
2✔
1379
      }
1380
    }
1381
    return new BLong( physical_damage().mod );
3✔
1382
    break;
1383

1384
  case MBR_LOWER_REAG_COST_MOD:
3✔
1385
    lower_reagent_cost( lower_reagent_cost().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1386
    if ( container != nullptr )
3✔
1387
    {
1388
      if ( Core::IsCharacter( container->serial ) )
2✔
1389
      {
1390
        Mobile::Character* chr = container->get_chr_owner();
2✔
1391
        if ( chr != nullptr )
2✔
1392
          chr->refresh_ar();
2✔
1393
      }
1394
    }
1395
    return new BLong( lower_reagent_cost().mod );
3✔
1396
    break;
1397
  case MBR_SPELL_DAMAGE_INCREASE_MOD:
3✔
1398
    spell_damage_increase( spell_damage_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1399
    if ( container != nullptr )
3✔
1400
    {
1401
      if ( Core::IsCharacter( container->serial ) )
2✔
1402
      {
1403
        Mobile::Character* chr = container->get_chr_owner();
2✔
1404
        if ( chr != nullptr )
2✔
1405
          chr->refresh_ar();
2✔
1406
      }
1407
    }
1408
    return new BLong( spell_damage_increase().mod );
3✔
1409
    break;
1410
  case MBR_FASTER_CASTING_MOD:
3✔
1411
    faster_casting( faster_casting().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1412
    if ( container != nullptr )
3✔
1413
    {
1414
      if ( Core::IsCharacter( container->serial ) )
2✔
1415
      {
1416
        Mobile::Character* chr = container->get_chr_owner();
2✔
1417
        if ( chr != nullptr )
2✔
1418
          chr->refresh_ar();
2✔
1419
      }
1420
    }
1421
    return new BLong( faster_casting().mod );
3✔
1422
    break;
1423
  case MBR_FASTER_CAST_RECOVERY_MOD:
3✔
1424
    faster_cast_recovery( faster_cast_recovery().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1425
    if ( container != nullptr )
3✔
1426
    {
1427
      if ( Core::IsCharacter( container->serial ) )
2✔
1428
      {
1429
        Mobile::Character* chr = container->get_chr_owner();
2✔
1430
        if ( chr != nullptr )
2✔
1431
          chr->refresh_ar();
2✔
1432
      }
1433
    }
1434
    return new BLong( faster_cast_recovery().mod );
3✔
1435
    break;
1436
  case MBR_DEFENCE_CHANCE_INCREASE_MOD:
3✔
1437
    defence_increase( defence_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1438
    if ( container != nullptr )
3✔
1439
    {
1440
      if ( Core::IsCharacter( container->serial ) )
2✔
1441
      {
1442
        Mobile::Character* chr = container->get_chr_owner();
2✔
1443
        if ( chr != nullptr )
2✔
1444
          chr->refresh_ar();
2✔
1445
      }
1446
    }
1447
    return new BLong( defence_increase().mod );
3✔
1448
    break;
1449
  case MBR_DEFENCE_CHANCE_INCREASE_CAP_MOD:
2✔
1450
    defence_increase_cap( defence_increase_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
1451
    if ( container != nullptr )
2✔
1452
    {
1453
      if ( Core::IsCharacter( container->serial ) )
1✔
1454
      {
1455
        Mobile::Character* chr = container->get_chr_owner();
1✔
1456
        if ( chr != nullptr )
1✔
1457
          chr->refresh_ar();
1✔
1458
      }
1459
    }
1460
    return new BLong( defence_increase_cap().mod );
2✔
1461
    break;
1462
  case MBR_LOWER_MANA_COST_MOD:
3✔
1463
    lower_mana_cost( lower_mana_cost().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1464
    if ( container != nullptr )
3✔
1465
    {
1466
      if ( Core::IsCharacter( container->serial ) )
2✔
1467
      {
1468
        Mobile::Character* chr = container->get_chr_owner();
2✔
1469
        if ( chr != nullptr )
2✔
1470
          chr->refresh_ar();
2✔
1471
      }
1472
    }
1473
    return new BLong( lower_mana_cost().mod );
3✔
1474
    break;
1475
  case MBR_HITCHANCE_MOD:  // to be made redundant in the future
3✔
1476
  case MBR_HIT_CHANCE_MOD:
1477
    hit_chance( hit_chance().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1478
    if ( container != nullptr )
3✔
1479
    {
1480
      if ( Core::IsCharacter( container->serial ) )
2✔
1481
      {
1482
        Mobile::Character* chr = container->get_chr_owner();
2✔
1483
        if ( chr != nullptr )
2✔
1484
          chr->refresh_ar();
2✔
1485
      }
1486
    }
1487
    return new BLong( hit_chance().mod );
3✔
1488
    break;
1489
  case MBR_LUCK_MOD:
3✔
1490
    luck( luck().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1491
    if ( container != nullptr )
3✔
1492
    {
1493
      if ( Core::IsCharacter( container->serial ) )
2✔
1494
      {
1495
        Mobile::Character* chr = container->get_chr_owner();
2✔
1496
        if ( chr != nullptr )
2✔
1497
          chr->refresh_ar();
2✔
1498
      }
1499
    }
1500
    return new BLong( luck().mod );
3✔
1501
    break;
1502
  case MBR_SWING_SPEED_INCREASE_MOD:
3✔
1503
    swing_speed_increase( swing_speed_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1504
    if ( container != nullptr )
3✔
1505
    {
1506
      if ( Core::IsCharacter( container->serial ) )
2✔
1507
      {
1508
        Mobile::Character* chr = container->get_chr_owner();
2✔
1509
        if ( chr != nullptr )
2✔
1510
          chr->refresh_ar();
2✔
1511
      }
1512
    }
1513
    return new BLong( swing_speed_increase().mod );
3✔
1514
    break;
1515
  case MBR_MIN_ATTACK_RANGE_INCREASE_MOD:
3✔
1516
    min_attack_range_increase(
6✔
1517
        min_attack_range_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1518
    if ( container != nullptr )
3✔
1519
    {
1520
      if ( Core::IsCharacter( container->serial ) )
2✔
1521
      {
1522
        Mobile::Character* chr = container->get_chr_owner();
2✔
1523
        if ( chr != nullptr )
2✔
1524
          chr->refresh_ar();
2✔
1525
      }
1526
    }
1527
    return new BLong( min_attack_range_increase().mod );
3✔
1528
    break;
1529
  case MBR_MAX_ATTACK_RANGE_INCREASE_MOD:
3✔
1530
    max_attack_range_increase(
6✔
1531
        max_attack_range_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
1532
    if ( container != nullptr )
3✔
1533
    {
1534
      if ( Core::IsCharacter( container->serial ) )
2✔
1535
      {
1536
        Mobile::Character* chr = container->get_chr_owner();
2✔
1537
        if ( chr != nullptr )
2✔
1538
          chr->refresh_ar();
2✔
1539
      }
1540
    }
1541
    return new BLong( max_attack_range_increase().mod );
3✔
1542
    break;
1543

1544
  case MBR_QUALITY:
×
1545
    quality( double( value ) );
×
1546
    return new Double( double( value ) );
×
1547
    break;
1548
  case MBR_HP:
5✔
1549
    hp_ = Clib::clamp_convert<u16>( value );
5✔
1550

1551
    if ( this->isa( Core::UOBJ_CLASS::CLASS_ARMOR ) )
5✔
1552
    {
1553
      if ( container != nullptr )
×
1554
      {
1555
        if ( Core::IsCharacter( container->serial ) )
×
1556
        {
1557
          Mobile::Character* chr = container->get_chr_owner();
×
1558
          if ( chr != nullptr )
×
1559
            chr->refresh_ar();
×
1560
        }
1561
      }
1562
    }
1563
    return new BLong( hp_ );
5✔
1564
  case MBR_MAXHP_MOD:
1✔
1565
    this->maxhp_mod( Clib::clamp_convert<s16>( value ) );
1✔
1566
    if ( this->isa( Core::UOBJ_CLASS::CLASS_ARMOR ) )
1✔
1567
    {
1568
      if ( container != nullptr )
×
1569
      {
1570
        if ( Core::IsCharacter( container->serial ) )
×
1571
        {
1572
          Mobile::Character* chr = container->get_chr_owner();
×
1573
          if ( chr != nullptr )
×
1574
            chr->refresh_ar();
×
1575
        }
1576
      }
1577
    }
1578
    return new BLong( value );
1✔
1579
  case MBR_NO_DROP:
3✔
1580
    no_drop( value ? true : false );
3✔
1581
    return new BLong( no_drop() );
3✔
1582
  case MBR_WEIGHT_MULTIPLIER_MOD:
2✔
1583
    return set_script_member_id_double( id, value );
2✔
1584
  default:
25✔
1585
    return nullptr;
25✔
1586
  }
1587
}
1588

1589
BObjectImp* Item::set_script_member( const char* membername, int value )
42✔
1590
{
1591
  ObjMember* objmember = getKnownObjMember( membername );
42✔
1592
  if ( objmember != nullptr )
42✔
1593
    return this->set_script_member_id( objmember->id, value );
42✔
1594
  return nullptr;
×
1595
}
1596

1597
BObjectImp* Item::set_script_member_id_double( const int id, double value )
19✔
1598
{
1599
  BObjectImp* imp = base::set_script_member_id_double( id, value );
19✔
1600
  if ( imp != nullptr )
19✔
1601
    return imp;
×
1602
  switch ( id )
19✔
1603
  {
1604
  case MBR_QUALITY:
1✔
1605
    quality( value );
1✔
1606
    return new Double( value );
1✔
1607
  case MBR_WEIGHT_MULTIPLIER_MOD:
5✔
1608
  {
1609
    if ( value < 0.0 )
5✔
1610
    {
1611
      return new BError( "weight_multiplier_mod cannot be less than 0.0" );
×
1612
    }
1613

1614
    if ( container )
5✔
1615
    {
1616
      int old_weight = weight();
2✔
1617
      weight_multiplier_mod( value );
2✔
1618
      int new_weight = weight();
2✔
1619
      int weight_delta = new_weight - old_weight;
2✔
1620
      container->add_bulk( 0, weight_delta );
2✔
1621
    }
1622
    else
1623
    {
1624
      weight_multiplier_mod( value );
3✔
1625
    }
1626

1627
    increv_send_object_recursive();
5✔
1628

1629
    UpdateCharacterWeight( this );
5✔
1630
    return new Double( weight_multiplier_mod() );
5✔
1631
    break;
1632
  }
1633
  default:
13✔
1634
    return nullptr;
13✔
1635
  }
1636
}
1637

1638
BObjectImp* Item::set_script_member_double( const char* membername, double value )
2✔
1639
{
1640
  ObjMember* objmember = getKnownObjMember( membername );
2✔
1641
  if ( objmember != nullptr )
2✔
1642
    return this->set_script_member_id_double( objmember->id, value );
2✔
1643
  return nullptr;
×
1644
}
1645

1646
BObjectImp* Item::script_method_id( const int id, Core::UOExecutor& ex )
281✔
1647
{
1648
  BObjectImp* imp = base::script_method_id( id, ex );
281✔
1649
  if ( imp != nullptr )
281✔
1650
    return imp;
248✔
1651
  switch ( id )
33✔
1652
  {
1653
  case MTH_SPLITSTACK_AT:
×
1654
  {
1655
    unsigned short amt;
1656
    Core::Pos4d newpos;
×
1657
    Item* new_stack( nullptr );
×
1658
    u16 item_amount = this->getamount();
×
1659

1660
    if ( !ex.hasParams( 5 ) )
×
1661
      return new BError( "Not enough parameters" );
×
NEW
1662
    if ( !ex.getPos4dParam( 0, 1, 2, 3, &newpos ) )
×
1663
      return new BError( "Invalid parameter type" );
×
NEW
1664
    if ( !ex.getParam( 4, amt ) )
×
1665
      return new BError( "No amount specified to pull from existing stack" );
×
NEW
1666
    if ( amt > this->getamount() )
×
1667
      return new BError( "Amount must be less than or equal to the stack amount" );
×
NEW
1668
    if ( amt < 1 )
×
1669
      return new BError( "Amount was less than 1" );
×
NEW
1670
    if ( this->inuse() )
×
1671
      return new BError( "Item is in use" );
×
1672

1673
    // Check first if the item is non-stackable and just force stacked with CreateItemInInventory
1674
    if ( !this->stackable() && amt > 1 )
×
1675
    {
1676
      unsigned short i;
1677

1678
      for ( i = 1; i <= amt; i++ )
×
1679
      {
1680
        if ( this->getamount() == 1 )
×
1681
          new_stack = this->clone();
×
1682
        else
1683
          new_stack = this->remove_part_of_stack( 1 );
×
1684
        new_stack->setposition( newpos );
×
1685
        add_item_to_world( new_stack );
×
1686
        move_item( new_stack, newpos );
×
1687
        update_item_to_inrange( new_stack );
×
1688
      }
1689

1690
      if ( this->getamount() == 1 )
×
1691
        destroy_item( this );
×
1692
      else
1693
        update_item_to_inrange( this );
×
1694
      if ( new_stack != nullptr )
×
1695
        return new Module::EItemRefObjImp( new_stack );
×
1696
      return nullptr;
×
1697
    }
1698

1699

1700
    if ( amt == this->getamount() )
×
1701
      new_stack = this->clone();
×
1702
    else
1703
      new_stack = this->remove_part_of_stack( amt );
×
1704

1705
    new_stack->setposition( newpos );
×
1706
    new_stack->setamount( amt );
×
1707
    add_item_to_world( new_stack );
×
1708
    move_item( new_stack, newpos );
×
1709
    update_item_to_inrange( new_stack );
×
1710

1711
    if ( amt == item_amount )
×
1712
      destroy_item( this );
×
1713
    else
1714
      update_item_to_inrange( this );
×
1715

1716
    return new Module::EItemRefObjImp( new_stack );
×
1717

1718
    break;
1719
  }
1720
  case MTH_SPLITSTACK_INTO:
1✔
1721
  {
1722
    unsigned short amt;
1723
    Item* cont_item;
1724

1725
    if ( !ex.hasParams( 2 ) )
1✔
1726
      return new BError( "Not enough parameters" );
×
1727
    if ( !ex.getItemParam( 0, cont_item ) )
1✔
1728
      return new BError( "No container specified" );
×
1729
    if ( !ex.getParam( 1, amt ) )
1✔
1730
      return new BError( "No amount specified to pull from existing stack" );
×
1731
    if ( amt > this->getamount() )
1✔
1732
      return new BError( "Amount must be less than or equal to stack amount" );
×
1733
    if ( amt < 1 )
1✔
1734
      return new BError( "Amount was less than 1" );
×
1735
    if ( this->inuse() )
1✔
1736
      return new BError( "Item is in use" );
×
1737
    if ( !cont_item->isa( Core::UOBJ_CLASS::CLASS_CONTAINER ) )
1✔
1738
      return new BError( "Non-container selected as target" );
×
1739

1740
    Core::UContainer* newcontainer = static_cast<Core::UContainer*>( cont_item );
1✔
1741

1742
    // Check first if the item is non-stackable and just force stacked with CreateItemInInventory
1743

1744
    Item* new_stack( nullptr );
1✔
1745
    u16 item_amount = this->getamount();
1✔
1746

1747
    if ( !this->stackable() && amt > 1 )
1✔
1748
    {
1749
      for ( unsigned short i = 1; i <= amt; i++ )
×
1750
      {
1751
        if ( this->getamount() == 1 )
×
1752
          new_stack = this->clone();
×
1753
        else
1754
          new_stack = this->remove_part_of_stack( 1 );
×
1755

1756
        bool can_insert = newcontainer->can_insert_add_item(
×
1757
            nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1758
        if ( !can_insert )
×
1759
        {
1760
          // Put new_stack back with the original stack
1761
          if ( new_stack != this )
×
1762
            this->add_to_self( new_stack );
×
1763
          return new BError( "Could not insert new stack into container" );
×
1764
        }
1765

1766
        newcontainer->add_at_random_location( new_stack );
×
1767
        update_item_to_inrange( new_stack );
×
1768
        UpdateCharacterWeight( new_stack );
×
1769
        newcontainer->on_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
×
1770
      }
1771

1772
      if ( this->getamount() == 1 )
×
1773
        destroy_item( this );
×
1774
      else
1775
        update_item_to_inrange( this );
×
1776
      if ( new_stack != nullptr )
×
1777
        return new Module::EItemRefObjImp( new_stack );
×
1778
      return nullptr;
×
1779
    }
1780

1781
    if ( amt == this->getamount() )
1✔
1782
      new_stack = this->clone();
×
1783
    else
1784
      new_stack = this->remove_part_of_stack( amt );
1✔
1785

1786
    auto create_new_stack = [&]() -> BObjectImp*
1✔
1787
    {
1788
      bool can_insert =
1789
          newcontainer->can_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1✔
1790
      if ( !can_insert )
1✔
1791
      {
1792
        // Put newstack back with the original stack
1793
        if ( new_stack != this )
×
1794
          this->add_to_self( new_stack );
×
1795
        return new BError( "Could not insert new stack into container" );
×
1796
      }
1797
      newcontainer->add_at_random_location( new_stack );
1✔
1798
      new_stack->setamount( amt );
1✔
1799
      update_item_to_inrange( new_stack );
1✔
1800
      UpdateCharacterWeight( new_stack );
1✔
1801
      newcontainer->on_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1✔
1802

1803
      if ( amt == item_amount )
1✔
1804
        destroy_item( this );
×
1805
      else
1806
        update_item_to_inrange( this );
1✔
1807

1808
      return new Module::EItemRefObjImp( new_stack );
1✔
1809
    };
1✔
1810

1811
    int add_to_existing_stack;
1812
    if ( !ex.hasParams( 3 ) ||
1✔
1813
         ( ex.getParam( 2, add_to_existing_stack ) && add_to_existing_stack != 0 ) )
×
1814
    {
1815
      Item* existing_stack = newcontainer->find_addable_stack( new_stack );
1✔
1816
      if ( existing_stack != nullptr && new_stack->stackable() )
1✔
1817
      {
1818
        if ( !newcontainer->can_insert_increase_stack( nullptr, Core::UContainer::MT_CORE_MOVED,
×
1819
                                                       existing_stack, new_stack->getamount(),
×
1820
                                                       new_stack ) )
1821
        {
1822
          if ( new_stack != this )
×
1823
            this->add_to_self( new_stack );
×
1824
          return new BError( "Could not add to existing stack" );
×
1825
        }
1826
      }
1827
      else
1828
        return create_new_stack();
1✔
1829

1830
      u16 amount = new_stack->getamount();
×
1831
      existing_stack->add_to_self( new_stack );
×
1832
      update_item_to_inrange( existing_stack );
×
1833

1834
      UpdateCharacterWeight( existing_stack );
×
1835

1836
      newcontainer->on_insert_increase_stack( nullptr, Core::UContainer::MT_CORE_MOVED,
×
1837
                                              existing_stack, amount );
1838

1839
      if ( amt == item_amount )
×
1840
        destroy_item( this );
×
1841
      else
1842
        update_item_to_inrange( this );
×
1843

1844
      return new Module::EItemRefObjImp( existing_stack );
×
1845
    }
NEW
1846
    return create_new_stack();
×
1847

1848
    break;
1849
  }
1850
  case MTH_HAS_EXISTING_STACK:
×
1851
  {
1852
    Item* cont = nullptr;
×
1853

1854
    if ( !ex.hasParams( 1 ) )
×
1855
      return new BError( "Not enough params" );
×
NEW
1856
    if ( !ex.getItemParam( 0, cont ) )
×
1857
      return new BError( "No container specified" );
×
NEW
1858
    if ( this->inuse() )
×
1859
      return new BError( "Item is in use" );
×
NEW
1860
    if ( !cont->isa( Core::UOBJ_CLASS::CLASS_CONTAINER ) )
×
1861
      return new BError( "Non-container selected as target" );
×
1862

1863
    Core::UContainer* stackcontainer = static_cast<Core::UContainer*>( cont );
×
1864

1865
    Item* existing_stack = stackcontainer->find_addable_stack( this );
×
1866

1867
    if ( existing_stack != nullptr )
×
1868
      return new Module::EItemRefObjImp( existing_stack );
×
1869
    return nullptr;
×
1870

1871
    break;
1872
  }
1873
  default:
32✔
1874
    return nullptr;
32✔
1875
  }
1876
}
1877

1878
BObjectImp* Item::script_method( const char* methodname, Core::UOExecutor& ex )
×
1879
{
1880
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
1881
  if ( objmethod != nullptr )
×
1882
    return this->script_method_id( objmethod->id, ex );
×
1883
  return nullptr;
×
1884
}
1885

1886
BObjectImp* Item::custom_script_method( const char* methodname, Core::UOExecutor& ex )
7✔
1887
{
1888
  const ItemDesc& id = itemdesc();
7✔
1889
  if ( id.method_script != nullptr )
7✔
1890
  {
1891
    unsigned PC;
1892
    if ( id.method_script->FindExportedFunction(
6✔
1893
             methodname, static_cast<unsigned int>( ex.numParams() + 1 ), PC ) )
6✔
1894
      return id.method_script->call( PC, make_ref(), ex.fparams );
6✔
1895
  }
1896
  return Core::gamestate.system_hooks.call_script_method( methodname, &ex, this );
1✔
1897
}
1898

1899
BObject Item::call_custom_method( const char* methodname )
×
1900
{
1901
  // no systemhook needed used for openbook uo module function
1902
  BObjectImpRefVec noparams;
×
1903
  return call_custom_method( methodname, noparams );
×
1904
}
×
1905

1906
BObject Item::call_custom_method( const char* methodname, BObjectImpRefVec& pmore )
×
1907
{
1908
  // no systemhook needed used for openbook uo module function
1909
  const ItemDesc& id = itemdesc();
×
1910
  if ( id.method_script != nullptr )
×
1911
  {
1912
    unsigned PC;
1913
    if ( id.method_script->FindExportedFunction(
×
1914
             methodname, static_cast<unsigned int>( pmore.size() + 1 ), PC ) )
×
1915
      return id.method_script->call( PC, new Module::EItemRefObjImp( this ), pmore );
×
1916

NEW
1917
    std::string message;
×
NEW
1918
    message = "Method script for objtype " + id.objtype_description() +
×
NEW
1919
              " does not export function " + std::string( methodname ) + " taking " +
×
NEW
1920
              Clib::tostring( pmore.size() + 1 ) + " parameters";
×
NEW
1921
    BError* err = new BError( message );
×
NEW
1922
    return BObject( err );
×
1923
  }
×
1924
  return BObject( new BError( "No method script defined for " + id.objtype_description() ) );
×
1925
}
1926

1927
BObjectImp* Item::make_ref()
160✔
1928
{
1929
  return new Module::EItemRefObjImp( this );
160✔
1930
}
1931
}  // namespace Items
1932
namespace Mobile
1933
{
1934
using namespace Bscript;
1935

1936
class ARUpdater
1937
{
1938
public:
1939
  static void on_change( Character* chr )
×
1940
  {
1941
    chr->refresh_ar();  // FIXME inefficient
×
1942
    // if (chr->client != nullptr) // already send in refresh_ar()
1943
    //{
1944
    //  send_full_statmsg( chr->client, chr );
1945
    //}
1946
  }
×
1947
};
1948

1949
BObjectImp* Character::make_ref()
11✔
1950
{
1951
  return new Module::ECharacterRefObjImp( this );
11✔
1952
}
1953
BObjectImp* Character::make_offline_ref()
×
1954
{
1955
  return new Module::EOfflineCharacterRefObjImp( this );
×
1956
}
1957

1958
BObjectImp* Character::get_script_member_id( const int id ) const
868✔
1959
{
1960
  BObjectImp* imp = base::get_script_member_id( id );
868✔
1961
  if ( imp != nullptr )
868✔
1962
    return imp;
603✔
1963

1964

1965
  auto EnforceCaps = []( s16 baseValue, const s16 capValue ) -> s16
30✔
1966
  {
1967
    const bool ignore_caps = Core::settingsManager.ssopt.core_ignores_defence_caps;
30✔
1968

1969

1970
    if ( !ignore_caps )
30✔
1971
      baseValue = std::min( baseValue, capValue );
30✔
1972

1973
    return baseValue;
30✔
1974
  };
1975

1976
  switch ( id )
265✔
1977
  {
1978
  case MBR_WARMODE:
×
1979
    return new BLong( warmode() );
×
1980
    break;
1981
  case MBR_GENDER:
1✔
1982
    return new BLong( gender );
1✔
1983
    break;
1984
  case MBR_RACE:
1✔
1985
    return new BLong( race );
1✔
1986
    break;
1987
  case MBR_TRUEOBJTYPE:
1✔
1988
    return new BLong( trueobjtype );
1✔
1989
    break;
1990
  case MBR_TRUECOLOR:
1✔
1991
    return new BLong( truecolor );
1✔
1992
    break;
1993
  case MBR_POSITION_CHANGED_AT:
2✔
1994
    return new Double( static_cast<double>( Core::polclock_t_to_ms( position_changed_at_ ) ) );
2✔
1995
    break;
1996
  case MBR_MOVED_AT:
2✔
1997
    return new Double( static_cast<double>( Core::polclock_t_to_ms( moved_at_ ) ) );
2✔
1998
    break;
1999
  case MBR_AR_MOD:
×
2000
    return new BLong( ar_mod() );
×
2001
    break;
2002
  case MBR_DELAY_MOD:
×
2003
    return new BLong( delay_mod() );
×
2004
    break;
2005
  case MBR_HIDDEN:
1✔
2006
    return new BLong( hidden() ? 1 : 0 );
1✔
2007
    break;
2008
  case MBR_CONCEALED:
1✔
2009
    return new BLong( concealed() );
1✔
2010
    break;
2011
  case MBR_FROZEN:
1✔
2012
    return new BLong( frozen() ? 1 : 0 );
1✔
2013
    break;
2014
  case MBR_PARALYZED:
×
2015
    return new BLong( paralyzed() ? 1 : 0 );
×
2016
    break;
2017
  case MBR_POISONED:
×
2018
    return new BLong( poisoned() ? 1 : 0 );
×
2019
    break;
2020
  case MBR_STEALTHSTEPS:
×
2021
    return new BLong( stealthsteps_ );
×
2022
    break;
2023
  case MBR_MOUNTEDSTEPS:
1✔
2024
    return new BLong( mountedsteps_ );
1✔
2025
    break;
2026
  case MBR_SQUELCHED:
1✔
2027
    return new BLong( squelched() ? 1 : 0 );
1✔
2028
    break;
2029
  case MBR_DEAD:
1✔
2030
    return new BLong( dead() );
1✔
2031
    break;
2032
  case MBR_AR:
1✔
2033
    return new BLong( ar() );
1✔
2034
    break;
2035
  case MBR_BACKPACK:
30✔
2036
  {
2037
    Items::Item* bp = backpack();
30✔
2038
    if ( bp != nullptr )
30✔
2039
      return bp->make_ref();
27✔
2040
    return new BError( "That has no backpack" );
3✔
2041
    break;
2042
  }
2043
  case MBR_TRADEWINDOW:
×
2044
  {
2045
    Core::UContainer* tw = trading_cont.get();
×
2046
    if ( trading_with != nullptr )
×
2047
      return tw->make_ref();
×
2048
    return new BError( "That has no active tradewindow" );
×
2049
    break;
2050
  }
2051
  case MBR_WEAPON:
1✔
2052
    if ( weapon != nullptr )
1✔
2053
      return weapon->make_ref();
1✔
2054
    return new BLong( 0 );
×
2055
    break;
2056
  case MBR_SHIELD:
1✔
2057
    if ( shield != nullptr )
1✔
2058
      return shield->make_ref();
1✔
2059
    return new BLong( 0 );
×
2060
    break;
2061
  case MBR_ACCTNAME:
×
2062
    if ( acct != nullptr )
×
2063
      return new String( acct->name() );
×
2064
    return new BError( "Not attached to an account" );
×
2065
    break;
2066

2067
  case MBR_ACCT:
×
2068
    if ( acct != nullptr )
×
2069
      return new Accounts::AccountObjImp( Accounts::AccountPtrHolder( acct ) );
×
2070
    return new BError( "Not attached to an account" );
×
2071
    break;
2072
  case MBR_CMDLEVEL:
1✔
2073
    return new BLong( cmdlevel() );
1✔
2074
    break;
2075
  case MBR_CMDLEVELSTR:
×
2076
    return new String( Core::gamestate.cmdlevels[cmdlevel()].name );
×
2077
    break;
2078
  case MBR_CRIMINAL:
×
2079
    return new BLong( is_criminal() ? 1 : 0 );
×
2080
    break;
2081
  case MBR_TEMPORALLY_CRIMINAL:
×
2082
    return new BLong( is_temporally_criminal() ? 1 : 0 );
×
2083
    break;
2084
  case MBR_IP:
×
2085
    if ( client != nullptr )
×
2086
      return new String( client->ipaddrAsString() );
×
2087
    return new String( "" );
×
2088
    break;
2089
  case MBR_GOLD:
×
2090
    return new BLong( gold_carried() );
×
2091
    break;
2092

2093
  case MBR_TITLE_PREFIX:
1✔
2094
    return new String( title_prefix() );
1✔
2095
    break;
2096
  case MBR_TITLE_SUFFIX:
1✔
2097
    return new String( title_suffix() );
1✔
2098
    break;
2099
  case MBR_TITLE_GUILD:
1✔
2100
    return new String( title_guild() );
1✔
2101
    break;
2102
  case MBR_TITLE_RACE:
1✔
2103
    return new String( title_race() );
1✔
2104
    break;
2105
  case MBR_UCLANG:
×
2106
    return new String( uclang );
×
2107
    break;
2108
  case MBR_GUILDID:
×
2109
    return new BLong( guildid() );
×
2110
    break;
2111
  case MBR_GUILD:
×
2112
    if ( has_guild() )
×
2113
      return Module::GuildExecutorModule::CreateGuildRefObjImp( guild() );
×
2114
    return new BError( "Not a member of a guild" );
×
2115
    break;
2116

2117
  case MBR_MURDERER:
1✔
2118
    return new BLong( is_murderer() ? 1 : 0 );
1✔
2119
    break;
2120
  case MBR_ATTACHED:
×
2121
    if ( script_ex == nullptr )
×
2122
      return new BError( "No script attached." );
×
2123
    return new Core::ScriptExObjImp( script_ex );
×
2124
    break;
2125
  case MBR_CLIENTVERSION:
×
2126
    if ( client != nullptr )
×
2127
      return new String( client->getversion() );
×
2128
    return new String( "" );
×
2129
    break;
2130
  case MBR_CLIENTVERSIONDETAIL:
×
2131
    if ( client != nullptr )
×
2132
    {
2133
      std::unique_ptr<BStruct> info( new BStruct );
×
2134
      Network::VersionDetailStruct version = client->getversiondetail();
×
2135
      info->addMember( "major", new BLong( version.major ) );
×
2136
      info->addMember( "minor", new BLong( version.minor ) );
×
2137
      info->addMember( "rev", new BLong( version.rev ) );
×
2138
      info->addMember( "patch", new BLong( version.patch ) );
×
2139
      return info.release();
×
2140
    }
×
2141
    else
2142
    {
2143
      std::unique_ptr<BStruct> info( new BStruct );
×
2144
      info->addMember( "major", new BLong( 0 ) );
×
2145
      info->addMember( "minor", new BLong( 0 ) );
×
2146
      info->addMember( "rev", new BLong( 0 ) );
×
2147
      info->addMember( "patch", new BLong( 0 ) );
×
2148
      return info.release();
×
2149
    }
×
2150
    break;
2151

2152
  case MBR_CLIENTINFO:
×
2153
    if ( client != nullptr )
×
2154
      return client->getclientinfo();
×
2155
    return new BLong( 0 );
×
2156
    break;
2157

2158
  case MBR_CREATEDAT:
×
2159
    return new BLong( created_at );
×
2160
    break;
2161

2162
  case MBR_REPORTABLES:
2✔
2163
    return GetReportables();
2✔
2164
    break;
2165

2166
  case MBR_OPPONENT:
×
2167
    if ( opponent_ != nullptr )
×
2168
      return opponent_->make_ref();
×
2169
    return new BError( "Mobile does not have any opponent selected." );
×
2170
    break;
2171
  case MBR_CONNECTED:
×
2172
    return new BLong( connected() ? 1 : 0 );
×
2173
    break;
2174
  case MBR_TRADING_WITH:
×
2175
    if ( trading_with != nullptr )
×
2176
      return trading_with->make_ref();
×
2177
    return new BError( "Mobile is not currently trading with anyone." );
×
2178
    break;
2179
  case MBR_CLIENTTYPE:
×
2180
    return new BLong( client != nullptr ? client->ClientType : 0 );
×
2181
    break;
2182
  case MBR_CURSOR:
×
2183
    if ( client != nullptr )
×
2184
      return new BLong( target_cursor_busy() ? 1 : 0 );
×
2185
    return new BLong( 0 );
×
2186
    break;
2187
  case MBR_GUMP:
×
2188
    if ( client != nullptr )
×
2189
      return new BLong( has_active_gump() ? 1 : 0 );
×
2190
    return new BLong( 0 );
×
2191
    break;
2192
  case MBR_PROMPT:
×
2193
    if ( client != nullptr )
×
2194
      return new BLong( has_active_prompt() ? 1 : 0 );
×
2195
    return new BLong( 0 );
×
2196
    break;
2197
  case MBR_MOVEMODE:
1✔
2198
  {
2199
    std::string mode = "";
1✔
2200
    if ( movemode & Plib::MOVEMODE_LAND )
1✔
2201
      mode = "L";
×
2202
    if ( movemode & Plib::MOVEMODE_SEA )
1✔
2203
      mode += "S";
×
2204
    if ( movemode & Plib::MOVEMODE_AIR )
1✔
2205
      mode += "A";
1✔
2206
    if ( movemode & Plib::MOVEMODE_FLY )
1✔
2207
      mode += "F";
×
2208
    return new String( mode );
1✔
2209
    break;
2210
  }
1✔
2211
  case MBR_HITCHANCE_MOD:
×
2212
    return new BLong( hitchance_mod() );
×
2213
    break;
2214
  case MBR_EVASIONCHANCE_MOD:
×
2215
    return new BLong( evasionchance_mod() );
×
2216
    break;
2217
  case MBR_PARRYCHANCE_MOD:
×
2218
    return new BLong( parrychance_mod() );
×
2219
    break;
2220
  case MBR_CARRYINGCAPACITY_MOD:
1✔
2221
    return new BLong( carrying_capacity_mod() );
1✔
2222
    break;
2223
  case MBR_CARRYINGCAPACITY:
×
2224
    return new BLong( carrying_capacity() );
×
2225
    break;
2226
  case MBR_FIRE_RESIST:
5✔
2227
    return new BLong( EnforceCaps( fire_resist().sum(), fire_resist_cap().sum() ) );
5✔
2228
  case MBR_COLD_RESIST:
5✔
2229
    return new BLong( EnforceCaps( cold_resist().sum(), cold_resist_cap().sum() ) );
5✔
2230
  case MBR_ENERGY_RESIST:
5✔
2231
    return new BLong( EnforceCaps( energy_resist().sum(), energy_resist_cap().sum() ) );
5✔
2232
  case MBR_POISON_RESIST:
5✔
2233
    return new BLong( EnforceCaps( poison_resist().sum(), poison_resist_cap().sum() ) );
5✔
2234
  case MBR_PHYSICAL_RESIST:
5✔
2235
    return new BLong( EnforceCaps( physical_resist().sum(), physical_resist_cap().sum() ) );
5✔
2236
  case MBR_FIRE_RESIST_MOD:
×
2237
    return new BLong( fire_resist().mod );
×
2238
    break;
2239
  case MBR_COLD_RESIST_MOD:
×
2240
    return new BLong( cold_resist().mod );
×
2241
    break;
2242
  case MBR_ENERGY_RESIST_MOD:
×
2243
    return new BLong( energy_resist().mod );
×
2244
    break;
2245
  case MBR_POISON_RESIST_MOD:
×
2246
    return new BLong( poison_resist().mod );
×
2247
    break;
2248
  case MBR_PHYSICAL_RESIST_MOD:
×
2249
    return new BLong( physical_resist().mod );
×
2250
    break;
2251
  case MBR_FIRE_RESIST_CAP:
1✔
2252
    return new BLong( fire_resist_cap().sum() );
1✔
2253
    break;
2254
  case MBR_COLD_RESIST_CAP:
1✔
2255
    return new BLong( cold_resist_cap().sum() );
1✔
2256
    break;
2257
  case MBR_ENERGY_RESIST_CAP:
1✔
2258
    return new BLong( energy_resist_cap().sum() );
1✔
2259
    break;
2260
  case MBR_POISON_RESIST_CAP:
1✔
2261
    return new BLong( poison_resist_cap().sum() );
1✔
2262
    break;
2263
  case MBR_PHYSICAL_RESIST_CAP:
1✔
2264
    return new BLong( physical_resist_cap().sum() );
1✔
2265
    break;
2266
  case MBR_FIRE_RESIST_CAP_MOD:
×
2267
    return new BLong( fire_resist_cap().mod );
×
2268
    break;
2269
  case MBR_COLD_RESIST_CAP_MOD:
×
2270
    return new BLong( cold_resist_cap().mod );
×
2271
    break;
2272
  case MBR_ENERGY_RESIST_CAP_MOD:
×
2273
    return new BLong( energy_resist_cap().mod );
×
2274
    break;
2275
  case MBR_POISON_RESIST_CAP_MOD:
×
2276
    return new BLong( poison_resist_cap().mod );
×
2277
    break;
2278
  case MBR_PHYSICAL_RESIST_CAP_MOD:
×
2279
    return new BLong( physical_resist_cap().mod );
×
2280
    break;
2281
  case MBR_LOWER_REAG_COST:
5✔
2282
    return new BLong( lower_reagent_cost().sum() );
5✔
2283
    break;
2284
  case MBR_SPELL_DAMAGE_INCREASE:
5✔
2285
    return new BLong( spell_damage_increase().sum() );
5✔
2286
    break;
2287
  case MBR_FASTER_CASTING:
5✔
2288
    return new BLong( faster_casting().sum() );
5✔
2289
    break;
2290
  case MBR_FASTER_CAST_RECOVERY:
5✔
2291
    return new BLong( faster_cast_recovery().sum() );
5✔
2292
    break;
2293
  case MBR_LOWER_REAG_COST_MOD:
×
2294
    return new BLong( lower_reagent_cost().mod );
×
2295
    break;
2296
  case MBR_SPELL_DAMAGE_INCREASE_MOD:
×
2297
    return new BLong( spell_damage_increase().mod );
×
2298
    break;
2299
  case MBR_FASTER_CASTING_MOD:
×
2300
    return new BLong( faster_casting().mod );
×
2301
    break;
2302
  case MBR_FASTER_CAST_RECOVERY_MOD:
×
2303
    return new BLong( faster_cast_recovery().mod );
×
2304
    break;
2305
  case MBR_DEFENCE_CHANCE_INCREASE_MOD:
×
2306
    return new BLong( defence_increase().mod );
×
2307
    break;
2308
  case MBR_DEFENCE_CHANCE_INCREASE_CAP_MOD:
×
2309
    return new BLong( defence_increase_cap().mod );
×
2310
    break;
2311
  case MBR_LOWER_MANA_COST_MOD:
×
2312
    return new BLong( lower_mana_cost().mod );
×
2313
    break;
2314
  case MBR_HIT_CHANCE_MOD:
×
2315
    return new BLong( hit_chance().mod );
×
2316
    break;
2317
  case MBR_DEFENCE_CHANCE_INCREASE:
5✔
2318
    return new BLong( EnforceCaps( defence_increase().sum(), defence_increase_cap().sum() ) );
5✔
2319
    break;
2320
  case MBR_DEFENCE_CHANCE_INCREASE_CAP:
1✔
2321
    return new BLong( defence_increase_cap().sum() );
1✔
2322
    break;
2323
  case MBR_LOWER_MANA_COST:
5✔
2324
    return new BLong( lower_mana_cost().sum() );
5✔
2325
    break;
2326
  case MBR_HIT_CHANCE:
5✔
2327
    return new BLong( hit_chance().sum() );
5✔
2328
    break;
2329
  case MBR_STATCAP:
1✔
2330
    return new BLong( skillstatcap().statcap );
1✔
2331
    break;
2332
  case MBR_SKILLCAP:
1✔
2333
    return new BLong( skillstatcap().skillcap );
1✔
2334
    break;
2335
  case MBR_LUCK:
5✔
2336
    return new BLong( luck().sum() );
5✔
2337
    break;
2338
  case MBR_LUCK_MOD:
×
2339
    return new BLong( luck().mod );
×
2340
    break;
2341
  case MBR_SWING_SPEED_INCREASE:
5✔
2342
    return new BLong( swing_speed_increase().sum() );
5✔
2343
    break;
2344
  case MBR_SWING_SPEED_INCREASE_MOD:
×
2345
    return new BLong( swing_speed_increase().mod );
×
2346
    break;
2347
  case MBR_MIN_ATTACK_RANGE_INCREASE:
5✔
2348
    return new BLong( min_attack_range_increase().sum() );
5✔
2349
    break;
2350
  case MBR_MIN_ATTACK_RANGE_INCREASE_MOD:
×
2351
    return new BLong( min_attack_range_increase().mod );
×
2352
    break;
2353
  case MBR_MAX_ATTACK_RANGE_INCREASE:
5✔
2354
    return new BLong( max_attack_range_increase().sum() );
5✔
2355
    break;
2356
  case MBR_MAX_ATTACK_RANGE_INCREASE_MOD:
×
2357
    return new BLong( max_attack_range_increase().mod );
×
2358
    break;
2359
  case MBR_FOLLOWERSMAX:
1✔
2360
    return new BLong( followers().followers_max );
1✔
2361
    break;
2362
  case MBR_TITHING:
1✔
2363
    return new BLong( tithing() );
1✔
2364
    break;
2365
  case MBR_FOLLOWERS:
1✔
2366
    return new BLong( followers().followers );
1✔
2367
    break;
2368
  case MBR_FIRE_DAMAGE:
5✔
2369
    return new BLong( fire_damage().sum() );
5✔
2370
    break;
2371
  case MBR_COLD_DAMAGE:
5✔
2372
    return new BLong( cold_damage().sum() );
5✔
2373
    break;
2374
  case MBR_ENERGY_DAMAGE:
5✔
2375
    return new BLong( energy_damage().sum() );
5✔
2376
    break;
2377
  case MBR_POISON_DAMAGE:
5✔
2378
    return new BLong( poison_damage().sum() );
5✔
2379
    break;
2380
  case MBR_PHYSICAL_DAMAGE:
5✔
2381
    return new BLong( physical_damage().sum() );
5✔
2382
    break;
2383
  case MBR_FIRE_DAMAGE_MOD:
×
2384
    return new BLong( fire_damage().mod );
×
2385
    break;
2386
  case MBR_COLD_DAMAGE_MOD:
×
2387
    return new BLong( cold_damage().mod );
×
2388
    break;
2389
  case MBR_ENERGY_DAMAGE_MOD:
×
2390
    return new BLong( energy_damage().mod );
×
2391
    break;
2392
  case MBR_POISON_DAMAGE_MOD:
×
2393
    return new BLong( poison_damage().mod );
×
2394
    break;
2395
  case MBR_PHYSICAL_DAMAGE_MOD:
×
2396
    return new BLong( physical_damage().mod );
×
2397
    break;
2398
  case MBR_PARTY:
6✔
2399
    if ( has_party() )
6✔
2400
      return Module::CreatePartyRefObjImp( party() );
6✔
2401
    return new BError( "Not a member of a party" );
×
2402
    break;
2403
  case MBR_PARTYLOOT:
×
2404
    return new BLong( party_can_loot() );
×
2405
  case MBR_CANDIDATE_OF_PARTY:
×
2406
    if ( has_candidate_of() )
×
2407
      return Module::CreatePartyRefObjImp( candidate_of() );
×
2408
    return new BError( "Not a candidate of a party" );
×
2409
    break;
2410
  case MBR_MOVECOST_WALK:
1✔
2411
    return new Double( movement_cost().walk );
1✔
2412
    break;
2413
  case MBR_MOVECOST_RUN:
1✔
2414
    return new Double( movement_cost().run );
1✔
2415
    break;
2416
  case MBR_MOVECOST_WALK_MOUNTED:
1✔
2417
    return new Double( movement_cost().walk_mounted );
1✔
2418
    break;
2419
  case MBR_MOVECOST_RUN_MOUNTED:
1✔
2420
    return new Double( movement_cost().run_mounted );
1✔
2421
    break;
2422

2423
  case MBR_AGGRESSORTO:
×
2424
    return GetAggressorTo();
×
2425
    break;
2426
  case MBR_LAWFULLYDAMAGED:
×
2427
    return GetLawFullyDamaged();
×
2428
    break;
2429

2430
  case MBR_UO_EXPANSION_CLIENT:
×
2431
    return new BLong( client != nullptr ? client->UOExpansionFlagClient : 0 );
×
2432
    break;
2433

2434
  case MBR_DEAFENED:
1✔
2435
    return new BLong( deafened() ? 1 : 0 );
1✔
2436
    break;
2437

2438
  case MBR_CLIENT:
12✔
2439
    if ( ( client != nullptr ) && ( client->isConnected() ) )
12✔
2440
      return client->make_ref();
11✔
2441
    return new BError( "No client attached." );
1✔
2442
    break;
2443
  case MBR_EDITING:
×
2444
    return new BLong( is_house_editing() ? 1 : 0 );
×
2445
    break;
2446
  case MBR_LASTCOORD:
×
2447
    if ( client != nullptr )
×
2448
    {
2449
      std::unique_ptr<BStruct> lastcoord( new BStruct );
×
2450
      lastcoord->addMember( "lastx", new BLong( lastpos.x() ) );
×
2451
      lastcoord->addMember( "lasty", new BLong( lastpos.y() ) );
×
2452
      lastcoord->addMember( "lastz", new BLong( lastpos.z() ) );
×
2453
      return lastcoord.release();
×
2454
    }
×
2455
    return new BError( "No client attached." );
×
2456
  case MBR_ACTIVE_SKILL:
×
2457
    return new BLong( skill_ex_active() );
×
2458
  case MBR_CASTING_SPELL:
×
2459
    return new BLong( casting_spell() );
×
2460
  case MBR_LAST_TEXTCOLOR:
×
2461
    return new BLong( last_textcolor() );
×
2462
  case MBR_BUFFS:
3✔
2463
  {
2464
    auto buffs = std::make_unique<BDictionary>();
3✔
2465
    for ( const auto& [icon, buf] : buffs_ )
5✔
2466
    {
2467
      auto info = std::make_unique<BStruct>();
2✔
2468
      info->addMember( "name_cliloc", new BLong( buf.cl_name ) );
2✔
2469
      info->addMember( "desc_cliloc", new BLong( buf.cl_descr ) );
2✔
2470
      info->addMember( "end_time", new BLong( buf.end ) );
2✔
2471
      info->addMember( "name_args", new String( buf.name_arguments ) );
2✔
2472
      info->addMember( "desc_args", new String( buf.desc_arguments ) );
2✔
2473
      buffs->addMember( new BLong( icon ), info.release() );
2✔
2474
    }
2✔
2475
    return buffs.release();
3✔
2476
  }
3✔
2477
  case MBR_LOGGED_IN:
6✔
2478
    return new BLong( logged_in() ? 1 : 0 );
6✔
2479
    break;
2480
  }
2481
  // if all else fails, returns nullptr
2482
  return nullptr;
60✔
2483
}
2484

2485
BObjectImp* Character::get_script_member( const char* membername ) const
108✔
2486
{
2487
  ObjMember* objmember = getKnownObjMember( membername );
108✔
2488
  if ( objmember != nullptr )
108✔
2489
    return this->get_script_member_id( objmember->id );
108✔
2490
  return nullptr;
×
2491
}
2492

2493
BObjectImp* Character::set_script_member_id( const int id, const std::string& value )
17✔
2494
{
2495
  BObjectImp* imp = base::set_script_member_id( id, value );
17✔
2496
  if ( imp != nullptr )
17✔
2497
    return imp;
×
2498

2499
  String* ret;
2500
  switch ( id )
17✔
2501
  {
2502
  case MBR_TITLE_PREFIX:
4✔
2503
    title_prefix( value );
4✔
2504
    ret = new String( value );
4✔
2505
    break;
4✔
2506
  case MBR_TITLE_SUFFIX:
4✔
2507
    title_suffix( value );
4✔
2508
    ret = new String( value );
4✔
2509
    break;
4✔
2510
  case MBR_TITLE_GUILD:
5✔
2511
    title_guild( value );
5✔
2512
    ret = new String( value );
5✔
2513
    break;
5✔
2514
  case MBR_TITLE_RACE:
4✔
2515
    title_race( value );
4✔
2516
    ret = new String( value );
4✔
2517
    break;
4✔
2518
  default:
×
2519
    return nullptr;
×
2520
  }
2521
  set_dirty();
17✔
2522
  increv();
17✔
2523
  if ( this->has_active_client() )
17✔
2524
    send_object_cache_to_inrange( this );
13✔
2525
  return ret;
17✔
2526
}
2527

2528
BObjectImp* Character::set_script_member( const char* membername, const std::string& value )
4✔
2529
{
2530
  ObjMember* objmember = getKnownObjMember( membername );
4✔
2531
  if ( objmember != nullptr )
4✔
2532
    return this->set_script_member_id( objmember->id, value );
4✔
2533
  return nullptr;
×
2534
}
2535

2536
BObjectImp* Character::set_script_member_id( const int id, int value )
98✔
2537
{
2538
  BObjectImp* imp = base::set_script_member_id( id, value );
98✔
2539
  if ( imp != nullptr )
98✔
2540
    return imp;
×
2541

2542
  switch ( id )
98✔
2543
  {
2544
  case MBR_GENDER:
1✔
2545
    if ( value )
1✔
2546
      gender = Plib::GENDER_FEMALE;
1✔
2547
    else
2548
      gender = Plib::GENDER_MALE;
×
2549
    return new BLong( gender );
1✔
2550
  case MBR_RACE:
1✔
2551
    if ( value == Plib::RACE_HUMAN )
1✔
2552
      race = Plib::RACE_HUMAN;
×
2553
    else if ( value == Plib::RACE_ELF )
1✔
2554
      race = Plib::RACE_ELF;
×
2555
    else if ( value == Plib::RACE_GARGOYLE )
1✔
2556
      race = Plib::RACE_GARGOYLE;
1✔
2557
    if ( ( race != Plib::RACE_GARGOYLE ) &&
1✔
NEW
2558
         ( movemode & Plib::MOVEMODE_FLY ) )                         // FIXME graphic based maybe?
×
NEW
2559
      movemode = (Plib::MOVEMODE)( movemode ^ Plib::MOVEMODE_FLY );  // remove flying
×
2560
    return new BLong( race );
1✔
2561
  case MBR_TRUEOBJTYPE:
1✔
2562
    return new BLong( trueobjtype = Clib::clamp_convert<u32>( value ) );
1✔
2563
  case MBR_TRUECOLOR:
1✔
2564
    return new BLong( truecolor = Clib::clamp_convert<u16>( value ) );
1✔
2565
  case MBR_AR_MOD:
×
2566
    ar_mod( Clib::clamp_convert<s16>( value ) );
×
2567
    refresh_ar();
×
2568
    return new BLong( ar_mod() );
×
2569
  case MBR_DELAY_MOD:
×
2570
    delay_mod( Clib::clamp_convert<s16>( value ) );
×
2571
    return new BLong( delay_mod() );
×
2572
  case MBR_HIDDEN:
12✔
2573
  {
2574
    // FIXME: don't call on_change unless the value actually changed?
2575
    hidden( value ? true : false );
12✔
2576
    return new BLong( hidden() );
12✔
2577
  }
2578
  case MBR_CONCEALED:
1✔
2579
    concealed( Clib::clamp_convert<u8>( value ) );
1✔
2580
    return new BLong( concealed() );
1✔
2581
  case MBR_FROZEN:
1✔
2582
    mob_flags_.change( MOB_FLAGS::FROZEN, value ? true : false );
1✔
2583
    return new BLong( frozen() );
1✔
2584
  case MBR_PARALYZED:
×
2585
    mob_flags_.change( MOB_FLAGS::PARALYZED, value ? true : false );
×
2586
    return new BLong( paralyzed() );
×
2587
  case MBR_POISONED:
×
2588
    poisoned( value ? true : false );
×
2589
    return new BLong( poisoned() );
×
2590
  case MBR_STEALTHSTEPS:
×
2591
    return new BLong( stealthsteps_ = Clib::clamp_convert<u16>( value ) );
×
2592
  case MBR_MOUNTEDSTEPS:
1✔
2593
    return new BLong( mountedsteps_ = Clib::clamp_convert<u32>( value ) );
1✔
2594
  case MBR_CMDLEVEL:
1✔
2595
    if ( value >= static_cast<int>( Core::gamestate.cmdlevels.size() ) )
1✔
2596
      cmdlevel( static_cast<unsigned char>( Core::gamestate.cmdlevels.size() ) - 1, true );
×
2597
    else
2598
      cmdlevel( static_cast<unsigned char>( value ), true );
1✔
2599
    return new BLong( cmdlevel() );
1✔
2600
  case MBR_MURDERER:
1✔
2601
    // make_murderer handles the updating
2602
    make_murderer( value ? true : false );
1✔
2603
    return new BLong( is_murderer() );
1✔
2604
  case MBR_HITCHANCE_MOD:
2✔
2605
    hitchance_mod( Clib::clamp_convert<s16>( value ) );
2✔
2606
    return new BLong( hitchance_mod() );
2✔
2607
  case MBR_EVASIONCHANCE_MOD:
×
2608
    evasionchance_mod( Clib::clamp_convert<s16>( value ) );
×
2609
    return new BLong( evasionchance_mod() );
×
2610
  case MBR_PARRYCHANCE_MOD:
×
2611
    parrychance_mod( Clib::clamp_convert<s16>( value ) );
×
2612
    return new BLong( parrychance_mod() );
×
2613
  case MBR_CARRYINGCAPACITY_MOD:
1✔
2614
    carrying_capacity_mod( Clib::clamp_convert<s16>( value ) );
1✔
2615
    if ( client != nullptr )
1✔
2616
    {  // CHECKME consider sending less frequently
2617
      send_full_statmsg( client, this );
×
2618
    }
2619
    return new BLong( carrying_capacity_mod() );
1✔
2620
  case MBR_FACING:
5✔
2621
    if ( !face( static_cast<Core::UFACING>( value & PKTIN_02_FACING_MASK ), 0 ) )
5✔
2622
      return new BLong( 0 );
×
2623
    on_facing_changed();
5✔
2624
    return new BLong( 1 );
5✔
2625
  case MBR_FIRE_RESIST_MOD:
2✔
2626
    fire_resist( fire_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2627
    refresh_ar();
2✔
2628
    return new BLong( fire_resist().mod );
2✔
2629
    break;
2630
  case MBR_COLD_RESIST_MOD:
2✔
2631
    cold_resist( cold_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2632
    refresh_ar();
2✔
2633
    return new BLong( cold_resist().mod );
2✔
2634
    break;
2635
  case MBR_ENERGY_RESIST_MOD:
2✔
2636
    energy_resist( energy_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2637
    refresh_ar();
2✔
2638
    return new BLong( energy_resist().mod );
2✔
2639
    break;
2640
  case MBR_POISON_RESIST_MOD:
2✔
2641
    poison_resist( poison_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2642
    refresh_ar();
2✔
2643
    return new BLong( poison_resist().mod );
2✔
2644
    break;
2645
  case MBR_PHYSICAL_RESIST_MOD:
2✔
2646
    physical_resist( physical_resist().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2647
    refresh_ar();
2✔
2648
    return new BLong( physical_resist().mod );
2✔
2649
    break;
2650
  case MBR_LOWER_REAG_COST_MOD:
2✔
2651
    lower_reagent_cost( lower_reagent_cost().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2652
    refresh_ar();
2✔
2653
    return new BLong( lower_reagent_cost().mod );
2✔
2654
    break;
2655
  case MBR_SPELL_DAMAGE_INCREASE_MOD:
2✔
2656
    spell_damage_increase( spell_damage_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2657
    refresh_ar();
2✔
2658
    return new BLong( spell_damage_increase().mod );
2✔
2659
    break;
2660
  case MBR_FASTER_CASTING_MOD:
2✔
2661
    faster_casting( faster_casting().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2662
    refresh_ar();
2✔
2663
    return new BLong( faster_casting().mod );
2✔
2664
    break;
2665
  case MBR_FASTER_CAST_RECOVERY_MOD:
2✔
2666
    faster_cast_recovery( faster_cast_recovery().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2667
    refresh_ar();
2✔
2668
    return new BLong( faster_cast_recovery().mod );
2✔
2669
    break;
2670
  case MBR_DEFENCE_CHANCE_INCREASE_MOD:
2✔
2671
    defence_increase( defence_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2672
    refresh_ar();
2✔
2673
    return new BLong( defence_increase().mod );
2✔
2674
    break;
2675
  case MBR_DEFENCE_CHANCE_INCREASE_CAP_MOD:
1✔
2676
    defence_increase_cap( defence_increase_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2677
    refresh_ar();
1✔
2678
    return new BLong( defence_increase_cap().mod );
1✔
2679
    break;
2680
  case MBR_LOWER_MANA_COST_MOD:
2✔
2681
    lower_mana_cost( lower_mana_cost().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2682
    refresh_ar();
2✔
2683
    return new BLong( lower_mana_cost().mod );
2✔
2684
    break;
2685
  case MBR_HIT_CHANCE_MOD:
2✔
2686
    hit_chance( hit_chance().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2687
    refresh_ar();
2✔
2688
    return new BLong( hit_chance().mod );
2✔
2689
    break;
2690
  case MBR_FIRE_RESIST_CAP_MOD:
1✔
2691
    fire_resist_cap( fire_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2692
    refresh_ar();
1✔
2693
    return new BLong( fire_resist_cap().mod );
1✔
2694
    break;
2695
  case MBR_COLD_RESIST_CAP_MOD:
1✔
2696
    cold_resist_cap( cold_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2697
    refresh_ar();
1✔
2698
    return new BLong( cold_resist_cap().mod );
1✔
2699
    break;
2700
  case MBR_ENERGY_RESIST_CAP_MOD:
1✔
2701
    energy_resist_cap( energy_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2702
    refresh_ar();
1✔
2703
    return new BLong( energy_resist_cap().mod );
1✔
2704
    break;
2705
  case MBR_PHYSICAL_RESIST_CAP_MOD:
1✔
2706
    physical_resist_cap( physical_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2707
    refresh_ar();
1✔
2708
    return new BLong( physical_resist_cap().mod );
1✔
2709
    break;
2710
  case MBR_POISON_RESIST_CAP_MOD:
1✔
2711
    poison_resist_cap( poison_resist_cap().setAsMod( Clib::clamp_convert<s16>( value ) ) );
1✔
2712
    refresh_ar();
1✔
2713
    return new BLong( poison_resist_cap().mod );
1✔
2714
    break;
2715
  case MBR_LUCK_MOD:
2✔
2716
    luck( luck().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2717
    refresh_ar();
2✔
2718
    return new BLong( luck().mod );
2✔
2719
    break;
2720
  case MBR_SWING_SPEED_INCREASE_MOD:
10✔
2721
    swing_speed_increase( swing_speed_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
10✔
2722
    refresh_ar();
10✔
2723
    return new BLong( swing_speed_increase().mod );
10✔
2724
    break;
2725
  case MBR_MIN_ATTACK_RANGE_INCREASE_MOD:
2✔
2726
    min_attack_range_increase(
4✔
2727
        min_attack_range_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2728
    refresh_ar();
2✔
2729
    return new BLong( min_attack_range_increase().mod );
2✔
2730
    break;
2731
  case MBR_MAX_ATTACK_RANGE_INCREASE_MOD:
3✔
2732
    max_attack_range_increase(
6✔
2733
        max_attack_range_increase().setAsMod( Clib::clamp_convert<s16>( value ) ) );
3✔
2734
    refresh_ar();
3✔
2735
    return new BLong( max_attack_range_increase().mod );
3✔
2736
    break;
2737
  case MBR_STATCAP:
1✔
2738
  {
2739
    auto val = skillstatcap();
1✔
2740
    val.statcap = Clib::clamp_convert<s16>( value );
1✔
2741
    skillstatcap( val );
1✔
2742
    if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
1✔
2743
      on_aos_ext_stat_changed();
1✔
2744
    return new BLong( skillstatcap().statcap );
1✔
2745
  }
2746
  case MBR_SKILLCAP:
1✔
2747
  {
2748
    auto val = skillstatcap();
1✔
2749
    val.skillcap = Clib::clamp_convert<u16>( value );
1✔
2750
    skillstatcap( val );
1✔
2751
    return new BLong( skillstatcap().skillcap );
1✔
2752
  }
2753
  case MBR_FOLLOWERSMAX:
1✔
2754
  {
2755
    auto val = followers();
1✔
2756
    val.followers_max = Clib::clamp_convert<u8>( value );
1✔
2757
    followers( val );
1✔
2758
    if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
1✔
2759
      on_aos_ext_stat_changed();
1✔
2760
    return new BLong( followers().followers_max );
1✔
2761
  }
2762
  case MBR_TITHING:
1✔
2763
    tithing( value );
1✔
2764
    if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
1✔
2765
      on_aos_ext_stat_changed();
1✔
2766
    return new BLong( tithing() );
1✔
2767
    break;
2768
  case MBR_FOLLOWERS:
1✔
2769
  {
2770
    auto val = followers();
1✔
2771
    val.followers = Clib::clamp_convert<u8>( value );
1✔
2772
    followers( val );
1✔
2773
    if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
1✔
2774
      on_aos_ext_stat_changed();
1✔
2775
    return new BLong( followers().followers );
1✔
2776
  }
2777
  case MBR_FIRE_DAMAGE_MOD:
2✔
2778
    fire_damage( fire_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2779
    refresh_ar();
2✔
2780
    return new BLong( fire_damage().mod );
2✔
2781
    break;
2782
  case MBR_COLD_DAMAGE_MOD:
2✔
2783
    cold_damage( cold_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2784
    refresh_ar();
2✔
2785
    return new BLong( cold_damage().mod );
2✔
2786
    break;
2787
  case MBR_ENERGY_DAMAGE_MOD:
2✔
2788
    energy_damage( energy_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2789
    refresh_ar();
2✔
2790
    return new BLong( energy_damage().mod );
2✔
2791
    break;
2792
  case MBR_POISON_DAMAGE_MOD:
2✔
2793
    poison_damage( poison_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2794
    refresh_ar();
2✔
2795
    return new BLong( poison_damage().mod );
2✔
2796
    break;
2797
  case MBR_PHYSICAL_DAMAGE_MOD:
2✔
2798
    physical_damage( physical_damage().setAsMod( Clib::clamp_convert<s16>( value ) ) );
2✔
2799
    refresh_ar();
2✔
2800
    return new BLong( physical_damage().mod );
2✔
2801
    break;
2802
  case MBR_MOVECOST_WALK:
×
2803
  {
2804
    auto val = movement_cost();
×
2805
    val.walk = static_cast<double>( value );
×
2806
    movement_cost( val );
×
2807
    return new Double( movement_cost().walk );
×
2808
  }
2809
  case MBR_MOVECOST_RUN:
×
2810
  {
2811
    auto val = movement_cost();
×
2812
    val.run = static_cast<double>( value );
×
2813
    movement_cost( val );
×
2814
    return new Double( movement_cost().run );
×
2815
  }
2816
  case MBR_MOVECOST_WALK_MOUNTED:
×
2817
  {
2818
    auto val = movement_cost();
×
2819
    val.walk_mounted = static_cast<double>( value );
×
2820
    movement_cost( val );
×
2821
    return new Double( movement_cost().walk_mounted );
×
2822
  }
2823
  case MBR_MOVECOST_RUN_MOUNTED:
×
2824
  {
2825
    auto val = movement_cost();
×
2826
    val.run_mounted = static_cast<double>( value );
×
2827
    movement_cost( val );
×
2828
    return new Double( movement_cost().run_mounted );
×
2829
  }
2830
  default:
7✔
2831
    return nullptr;
7✔
2832
  }
2833
}
2834

2835
BObjectImp* Character::set_script_member_id_double( const int id, double value )
4✔
2836
{
2837
  switch ( id )
4✔
2838
  {
2839
  case MBR_MOVECOST_WALK:
1✔
2840
  {
2841
    auto val = movement_cost();
1✔
2842
    val.walk = value;
1✔
2843
    movement_cost( val );
1✔
2844
    return new Double( movement_cost().walk );
1✔
2845
  }
2846
  case MBR_MOVECOST_RUN:
1✔
2847
  {
2848
    auto val = movement_cost();
1✔
2849
    val.run = value;
1✔
2850
    movement_cost( val );
1✔
2851
    return new Double( movement_cost().run );
1✔
2852
  }
2853
  case MBR_MOVECOST_WALK_MOUNTED:
1✔
2854
  {
2855
    auto val = movement_cost();
1✔
2856
    val.walk_mounted = value;
1✔
2857
    movement_cost( val );
1✔
2858
    return new Double( movement_cost().walk_mounted );
1✔
2859
  }
2860
  case MBR_MOVECOST_RUN_MOUNTED:
1✔
2861
  {
2862
    auto val = movement_cost();
1✔
2863
    val.run_mounted = value;
1✔
2864
    movement_cost( val );
1✔
2865
    return new Double( movement_cost().run_mounted );
1✔
2866
  }
2867
  default:
×
2868
    return nullptr;
×
2869
  }
2870
}
2871

2872
BObjectImp* Character::set_script_member( const char* membername, int value )
64✔
2873
{
2874
  ObjMember* objmember = getKnownObjMember( membername );
64✔
2875
  if ( objmember != nullptr )
64✔
2876
    return this->set_script_member_id( objmember->id, value );
64✔
2877
  return nullptr;
×
2878
}
2879

2880
BObjectImp* Character::script_method_id( const int id, Core::UOExecutor& ex )
363✔
2881
{
2882
  BObjectImp* imp = base::script_method_id( id, ex );
363✔
2883
  if ( imp != nullptr )
363✔
2884
    return imp;
256✔
2885

2886
  switch ( id )
107✔
2887
  {
2888
  /*
2889
  mobile.SetPoisoned( ispoisoned := 1 )
2890
  If the poisoned flag was changed, and the script has a controller
2891
  If poisoned was SET,
2892
  apply RepSystem rules (Mobile damages Mobile)
2893
  else poisoned was CLEARED, so
2894
  apply RepSystem rules (Mobile helps Mobile)
2895
  */
2896
  case MTH_SETPOISONED:
×
2897
  {
2898
    bool newval = true;
×
2899
    if ( ex.hasParams( 1 ) )
×
2900
    {
2901
      int lval;
2902
      if ( !ex.getParam( 0, lval ) )
×
2903
        return new BError( "Invalid parameter type" );
×
2904
      if ( !lval )
×
2905
        newval = false;
×
2906
    }
2907

2908
    if ( newval != poisoned() )
×
2909
    {
2910
      set_dirty();
×
2911
      poisoned( newval );
×
2912
      check_undamaged();
×
2913
      Module::UOExecutorModule* uoexec =
2914
          static_cast<Module::UOExecutorModule*>( ex.findModule( "UO" ) );
×
2915
      if ( uoexec != nullptr && uoexec->controller_.get() )
×
2916
      {
2917
        Character* attacker = uoexec->controller_.get();
×
2918
        if ( !attacker->orphan() )
×
2919
        {
2920
          if ( poisoned() )
×
2921
            attacker->repsys_on_damage( this );
×
2922
          else
2923
            attacker->repsys_on_help( this );
×
2924
        }
2925
      }
2926
    }
2927
    return new BLong( 1 );
×
2928
  }
2929

2930
  /*
2931
   mobile.SetParalyzed( isparalyzed := 1 )
2932
   If the paralyzed flag was changed, and the script has a controller
2933
   if paralyzed was SET,
2934
   apply RepSystem rules (Mobile damages Mobile)
2935
   else paralyzed was CLEARED, so
2936
   apply RepSystem rules (Mobile heals Mobile)
2937
   */
2938
  case MTH_SETPARALYZED:
×
2939
  {
2940
    bool newval = true;
×
2941
    if ( ex.hasParams( 1 ) )
×
2942
    {
2943
      int lval;
2944
      if ( !ex.getParam( 0, lval ) )
×
2945
        return new BError( "Invalid parameter type" );
×
2946
      if ( !lval )
×
2947
        newval = false;
×
2948
    }
2949

2950
    if ( newval != paralyzed() )
×
2951
    {
2952
      set_dirty();
×
2953
      mob_flags_.change( MOB_FLAGS::PARALYZED, newval );
×
2954
      check_undamaged();
×
2955
      Module::UOExecutorModule* uoexec =
2956
          static_cast<Module::UOExecutorModule*>( ex.findModule( "UO" ) );
×
2957
      if ( uoexec != nullptr && uoexec->controller_.get() )
×
2958
      {
2959
        Character* attacker = uoexec->controller_.get();
×
2960
        if ( !attacker->orphan() )
×
2961
        {
2962
          if ( paralyzed() )
×
2963
            attacker->repsys_on_damage( this );
×
2964
          else
2965
            attacker->repsys_on_help( this );
×
2966
        }
2967
      }
2968
    }
2969
    return new BLong( 1 );
×
2970
  }
2971

2972
  /*
2973
   mobile.SetCriminal( level := 1 )
2974
   if level is 0, clears the CriminalTimer
2975
   */
2976
  case MTH_SETCRIMINAL:
×
2977
  {
2978
    int level = 1;
×
2979
    if ( ex.hasParams( 1 ) )
×
2980
    {
2981
      if ( !ex.getParam( 0, level ) )
×
2982
        return new BError( "Invalid parameter type" );
×
2983
      if ( level < 0 )
×
2984
        return new BError( "Level must be >= 0" );
×
2985
    }
2986
    set_dirty();
×
2987
    // make_criminal handles the updating
2988
    make_criminal( level );
×
2989
    return new BLong( 1 );
×
2990
  }
2991

2992
  case MTH_SETLIGHTLEVEL:
×
2993
  {
2994
    int level, duration;
2995
    if ( !ex.hasParams( 2 ) )
×
2996
      return new BError( "Not enough parameters" );
×
2997
    if ( ex.getParam( 0, level ) && ex.getParam( 1, duration ) )
×
2998
    {
2999
      lightoverride( level );
×
3000

3001
      if ( duration == -1 )
×
3002
        lightoverride_until( ~0u );
×
3003
      else if ( duration == 0 )
×
3004
        lightoverride_until( 0 );
×
3005
      else
3006
        lightoverride_until( Core::read_gameclock() + duration );
×
3007

3008
      check_region_changes();
×
3009
      if ( duration == -1 )
×
3010
        return new BLong( duration );
×
3011
      return new BLong( lightoverride_until() );
×
3012
    }
3013
    break;
×
3014
  }
3015

3016
  case MTH_SETSEASON:
×
3017
  {
3018
    int season_id, playsound;
3019

3020
    if ( !ex.hasParams( 2 ) )
×
3021
      return new BError( "Not enough parameters" );
×
3022
    if ( ex.getParam( 0, season_id ) && ex.getParam( 1, playsound ) )
×
3023
    {
3024
      if ( season_id < 0 || season_id > 4 )
×
3025
        return new BError( "Invalid season id" );
×
3026

3027
      if ( client && client->getversiondetail().major >= 1 )
×
3028
      {
3029
        Network::PktHelper::PacketOut<Network::PktOut_BC> msg;
×
3030
        msg->Write<u8>( Clib::clamp_convert<u8>( season_id ) );
×
3031
        msg->Write<u8>( Clib::clamp_convert<u8>( playsound ) );
×
3032
        msg.Send( client );
×
3033
        return new BLong( 1 );
×
3034
      }
×
3035
    }
3036
    break;
×
3037
  }
3038
  case MTH_SQUELCH:
1✔
3039
  {
3040
    int duration;
3041
    if ( !ex.hasParams( 1 ) )
1✔
3042
      return new BError( "Not enough parameters" );
1✔
3043
    if ( ex.getParam( 0, duration ) )
1✔
3044
    {
3045
      set_dirty();
1✔
3046
      if ( duration == -1 )
1✔
3047
      {
3048
        squelched_until( ~0u );
×
3049
        return new BLong( -1 );
×
3050
      }
3051
      if ( duration == 0 )
1✔
3052
        squelched_until( 0 );
×
3053
      else
3054
        squelched_until( Core::read_gameclock() + duration );
1✔
3055
      return new BLong( squelched_until() );
1✔
3056
    }
3057
    break;
×
3058
  }
3059
  case MTH_ENABLE:
3✔
3060
  {
3061
    if ( !ex.hasParams( 1 ) )
3✔
3062
      return new BError( "Not enough parameters" );
3✔
3063
    const String* pstr;
3064
    if ( ex.getStringParam( 0, pstr ) )
3✔
3065
    {
3066
      if ( has_privilege( pstr->data() ) )
3✔
3067
      {
3068
        set_dirty();
3✔
3069
        set_setting( pstr->data(), true );
3✔
3070
        return new BLong( 1 );
3✔
3071
      }
3072
      return new BError( "Mobile doesn't have that privilege" );
×
3073
    }
3074
    break;
×
3075
  }
3076

3077
  case MTH_DISABLE:
2✔
3078
  {
3079
    if ( !ex.hasParams( 1 ) )
2✔
3080
      return new BError( "Not enough parameters" );
2✔
3081
    const String* pstr;
3082
    if ( ex.getStringParam( 0, pstr ) )
2✔
3083
    {
3084
      set_dirty();
2✔
3085
      set_setting( pstr->data(), false );
2✔
3086
      return new BLong( 1 );
2✔
3087
    }
3088
    break;
×
3089
  }
3090

3091
  case MTH_ENABLED:
2✔
3092
  {
3093
    if ( !ex.hasParams( 1 ) )
2✔
3094
      return new BError( "Not enough parameters" );
2✔
3095
    const String* pstr;
3096
    if ( ex.getStringParam( 0, pstr ) )
2✔
3097
      return new BLong( setting_enabled( pstr->data() ) ? 1 : 0 );
2✔
3098
    break;
×
3099
  }
3100

3101
  case MTH_PRIVILEGES:
1✔
3102
  {
3103
    std::unique_ptr<BDictionary> dict( new BDictionary );
1✔
3104
    ISTRINGSTREAM istrm( all_privs() );
1✔
3105
    std::string tmp;
1✔
3106
    while ( istrm >> tmp )
3✔
3107
    {
3108
      dict->addMember( new String( tmp ), new BLong( setting_enabled( tmp.c_str() ) ) );
2✔
3109
    }
3110
    return dict.release();
1✔
3111
    break;
3112
  }
1✔
3113

3114
  case MTH_SETCMDLEVEL:
×
3115
  {
3116
    if ( !ex.hasParams( 1 ) )
×
3117
      return new BError( "Not enough parameters" );
×
3118
    const String* pstr;
3119
    if ( ex.getStringParam( 0, pstr ) )
×
3120
    {
3121
      Core::CmdLevel* pcmdlevel = Core::find_cmdlevel( pstr->data() );
×
3122
      if ( pcmdlevel )
×
3123
      {
3124
        set_dirty();
×
3125
        cmdlevel( pcmdlevel->cmdlevel, true );
×
3126
        return new BLong( 1 );
×
3127
      }
3128
      return new BError( "No such command level" );
×
3129
    }
3130
    break;
×
3131
  }
3132
  case MTH_SPENDGOLD:
×
3133
  {
3134
    u32 amt;
3135
    if ( ex.numParams() != 1 || !ex.getParam( 0, amt ) )
×
3136
      return new BError( "Invalid parameter type" );
×
3137

3138
    if ( gold_carried() < amt )
×
3139
      return new BError( "Insufficient funds" );
×
3140

3141
    spend_gold( amt );
×
3142
    return new BLong( 1 );
×
3143
  }
3144

3145
  case MTH_SETMURDERER:
×
3146
  {
3147
    int lnewval = 1;
×
3148
    if ( ex.hasParams( 1 ) )
×
3149
    {
3150
      if ( !ex.getParam( 0, lnewval ) )
×
3151
        return new BError( "Invalid parameter type" );
×
3152
    }
3153
    set_dirty();
×
3154
    // make_murderer handles the updating
3155
    make_murderer( lnewval ? true : false );
×
3156
    return new BLong( 1 );
×
3157
  }
3158
  case MTH_REMOVEREPORTABLE:
×
3159
  {
3160
    if ( !ex.hasParams( 2 ) )
×
3161
      return new BError( "Not enough parameters" );
×
3162
    int repserial, gameclock;
3163
    if ( ex.getParam( 0, repserial ) && ex.getParam( 1, gameclock ) )
×
3164
    {
3165
      set_dirty();
×
3166
      clear_reportable( repserial, gameclock );
×
3167
      return new BLong( 1 );
×
3168
    }
3169
    break;
×
3170
  }
3171
  case MTH_GETGOTTENITEM:
3✔
3172
    if ( has_gotten_item() )
3✔
3173
      return new Module::EItemRefObjImp( gotten_item().item() );
3✔
3174
    return new BError( "Gotten Item nullptr" );
×
3175
    break;
3176
  case MTH_CLEARGOTTENITEM:
×
3177
    if ( has_gotten_item() )
×
3178
    {
3179
      clear_gotten_item();
×
3180
      return new BLong( 1 );
×
3181
    }
3182
    return new BError( "No Gotten Item" );
×
3183
    break;
3184
  case MTH_SETWARMODE:
3✔
3185
  {
3186
    int newmode;
3187
    if ( !ex.hasParams( 1 ) )
3✔
3188
      return new BError( "Not enough parameters" );
3✔
3189
    if ( ex.getParam( 0, newmode, 0, 1 ) )
3✔
3190
    {
3191
      set_warmode( ( newmode == 0 ) ? false : true );
3✔
3192
      // FIXME: Additional checks needed?
3193
      if ( client )
3✔
3194
        send_warmode();
2✔
3195
      return new BLong( warmode() );
3✔
3196
    }
3197
    break;
×
3198
  }
3199
  case MTH_GETCORPSE:
2✔
3200
  {
3201
    Core::UCorpse* corpse_obj =
3202
        static_cast<Core::UCorpse*>( Core::system_find_item( last_corpse ) );
2✔
3203
    if ( corpse_obj != nullptr && !corpse_obj->orphan() )
2✔
3204
      return new Module::EItemRefObjImp( corpse_obj );
2✔
3205
    return new BError( "No corpse was found." );
×
3206
    break;
3207
  }
3208
  case MTH_SET_SWINGTIMER:
×
3209
  {
3210
    int time;
3211
    if ( !ex.hasParams( 1 ) )
×
3212
      return new BError( "Not enough parameters" );
×
3213
    if ( ex.getParam( 0, time ) )
×
3214
    {
3215
      if ( time < 0 )
×
3216
        return new BError( "Time must be >= 0" );
×
3217
      Core::polclock_t clocks;
3218
      clocks = ( time * Core::POLCLOCKS_PER_SEC ) / 1000;
×
3219
      return new BLong( manual_set_swing_timer( clocks ) ? 1 : 0 );
×
3220
    }
3221
    break;
×
3222
  }
3223
  case MTH_ATTACK_ONCE:
×
3224
  {
3225
    Character* chr;
3226
    if ( ex.hasParams( 1 ) )
×
3227
    {
3228
      if ( ex.getCharacterParam( 0, chr ) )
×
3229
      {
3230
        if ( dead() )
×
3231
          return new BError( "Character is dead" );
×
3232
        if ( is_attackable( chr ) )
×
3233
          attack( chr );
×
3234
        else
3235
          return new BError( "Opponent is not attackable" );
×
3236
      }
3237
      else
3238
        return new BError( "Invalid parameter type" );
×
3239
    }
3240
    else
3241
    {
3242
      chr = get_attackable_opponent();
×
3243
      if ( chr != nullptr )
×
3244
      {
3245
        if ( !dead() )
×
3246
          attack( chr );
×
3247
        else
3248
          return new BError( "Character is dead" );
×
3249
      }
3250
      else
3251
        return new BError( "No opponent" );
×
3252
    }
3253
    return new BLong( 1 );
×
3254
    break;
3255
  }
3256
  case MTH_KILL:
72✔
3257
    if ( ex.hasParams( 1 ) )
72✔
3258
    {
3259
      Character* chr;
3260
      if ( ex.getCharacterParam( 0, chr ) )
1✔
3261
        chr->repsys_on_damage( this );
1✔
3262
    }
3263
    if ( dead() )
72✔
3264
      return new BError( "That is already dead!" );
×
3265

3266
    die();
72✔
3267
    return new BLong( 1 );
72✔
3268
    break;
3269
  case MTH_SETFACING:
×
3270
  {
3271
    int flags = 0;
×
3272
    Core::UFACING i_facing;
3273

3274
    if ( ex.hasParams( 2 ) && !ex.getParam( 1, flags, 0, 1 ) )
×
3275
      return new BError( "Invalid flags for parameter 1" );
×
3276

3277
    BObjectImp* param0 = ex.getParamImp( 0 );
×
3278
    if ( auto* s = impptrIf<String>( param0 ) )
×
3279
    {
3280
      if ( DecodeFacing( s->data(), i_facing ) == false )
×
3281
        return new BError( "Invalid string for parameter 0" );
×
3282
    }
3283
    else if ( auto* l = impptrIf<BLong>( param0 ) )
×
3284
    {
3285
      i_facing = static_cast<Core::UFACING>( l->value() & PKTIN_02_FACING_MASK );
×
3286
    }
3287
    else
3288
      return new BError( "Invalid type for parameter 0" );
×
3289

3290
    if ( !face( i_facing, flags ) )
×
3291
      return new BLong( 0 );
×
3292

3293
    on_facing_changed();
×
3294
    return new BLong( 1 );
×
3295
    break;
3296
  }
3297
  case MTH_COMPAREVERSION:
×
3298
    if ( client != nullptr )
×
3299
    {
3300
      if ( !ex.hasParams( 1 ) )
×
3301
        return new BError( "Not enough parameters" );
×
3302
      const String* pstr;
3303
      if ( ex.getStringParam( 0, pstr ) )
×
3304
        return new BLong( client->compareVersion( pstr->getStringRep() ) ? 1 : 0 );
×
3305
      return new BError( "Invalid parameter type" );
×
3306
    }
3307
    return new BError( "No client attached" );
×
3308
    break;
3309
  case MTH_SETAGGRESSORTO:
×
3310
    if ( ex.hasParams( 1 ) )
×
3311
    {
3312
      Character* chr;
3313
      if ( ex.getCharacterParam( 0, chr ) )
×
3314
      {
3315
        // make_aggressor_to handles the updating
3316
        this->make_aggressor_to( chr );
×
3317
        return new BLong( 1 );
×
3318
      }
3319
      return new BError( "Invalid parameter type" );
×
3320
    }
3321
    return new BError( "Not enough parameters" );
×
3322
    break;
3323
  case MTH_SETLAWFULLYDAMAGEDTO:
×
3324
    if ( ex.hasParams( 1 ) )
×
3325
    {
3326
      Character* chr;
3327
      if ( ex.getCharacterParam( 0, chr ) )
×
3328
      {
3329
        // make_lawfullydamaged_to handled the updating
3330
        this->make_lawfullydamaged_to( chr );
×
3331
        return new BLong( 1 );
×
3332
      }
3333
      return new BError( "Invalid parameter type" );
×
3334
    }
3335
    return new BError( "Not enough parameters" );
×
3336
    break;
3337
  case MTH_CLEARAGGRESSORTO:
×
3338
    if ( ex.hasParams( 1 ) )
×
3339
    {
3340
      Character* chr;
3341
      if ( ex.getCharacterParam( 0, chr ) )
×
3342
      {
3343
        this->remove_as_aggressor_to( chr );
×
3344
        return new BLong( 1 );
×
3345
      }
3346
      return new BError( "Invalid parameter type" );
×
3347
    }
3348
    return new BError( "Not enough parameters" );
×
3349
    break;
3350
  case MTH_CLEARLAWFULLYDAMAGEDTO:
×
3351
    if ( ex.hasParams( 1 ) )
×
3352
    {
3353
      Character* chr;
3354
      if ( ex.getCharacterParam( 0, chr ) )
×
3355
      {
3356
        this->remove_as_lawful_damager( chr );
×
3357
        return new BLong( 1 );
×
3358
      }
3359
      return new BError( "Invalid parameter type" );
×
3360
    }
3361
    return new BError( "Not enough parameters" );
×
3362
    break;
3363
  case MTH_DEAF:
1✔
3364
  {
3365
    int duration;
3366
    if ( !ex.hasParams( 1 ) )
1✔
3367
      return new BError( "Not enough parameters" );
1✔
3368
    if ( ex.getParam( 0, duration ) )
1✔
3369
    {
3370
      set_dirty();
1✔
3371
      if ( duration == -1 )
1✔
3372
      {
3373
        deafened_until( ~0u );
×
3374
        return new BLong( -1 );
×
3375
      }
3376
      if ( duration == 0 )
1✔
3377
        deafened_until( 0 );
×
3378
      else
3379
        deafened_until( Core::read_gameclock() + duration );
1✔
3380
      return new BLong( deafened_until() );
1✔
3381
    }
3382
    break;
×
3383
  }
3384
  case MTH_DISABLE_SKILLS_FOR:
×
3385
  {
3386
    int duration;
3387
    if ( !ex.hasParams( 1 ) )
×
3388
      return new BError( "Not enough parameters" );
×
3389
    if ( ex.getParam( 0, duration ) )
×
3390
    {
3391
      if ( duration < 0 )
×
3392
        return new BError( "Duration must be >= 0" );
×
3393
      disable_skills_until( Core::poltime() + duration );
×
3394
      return new BLong( static_cast<int>( disable_skills_until() ) );
×
3395
    }
3396
    break;
×
3397
  }
3398
  case MTH_ADD_BUFF:
2✔
3399
  {
3400
    u16 icon;
3401
    u16 duration;
3402
    u32 cl_name;
3403
    u32 cl_descr;
3404
    const String* desc_text;
3405
    std::string name_args;
2✔
3406

3407
    if ( !ex.hasParams( 5 ) )
2✔
3408
      return new BError( "Not enough parameters" );
×
3409
    if ( ex.getParam( 0, icon ) && ex.getParam( 1, duration ) && ex.getParam( 2, cl_name ) &&
4✔
3410
         ex.getParam( 3, cl_descr ) && ex.getUnicodeStringParam( 4, desc_text ) )
4✔
3411
    {
3412
      if ( ex.hasParams( 6 ) )
2✔
3413
      {
3414
        const String* name_text;
3415
        if ( !ex.getUnicodeStringParam( 5, name_text ) )
×
3416
          break;
×
3417
        if ( name_text->length() > SPEECH_MAX_LEN )
×
3418
          return new BError( "Title text exceeds maximum size." );
×
3419
        name_args = name_text->value();
×
3420
      }
3421

3422
      if ( !( icon && cl_name && cl_descr ) )
2✔
3423
        return new BError( "Invalid parameters" );
×
3424

3425
      if ( desc_text->length() > SPEECH_MAX_LEN )
2✔
3426
        return new BError( "Text exceeds maximum size." );
×
3427

3428
      addBuff( icon, duration, cl_name, name_args, cl_descr, desc_text->value() );
2✔
3429
      return new BLong( 1 );
2✔
3430
    }
3431
    break;
×
3432
  }
2✔
3433
  case MTH_CLEAR_BUFFS:
2✔
3434
  {
3435
    clearBuffs();
2✔
3436

3437
    return new BLong( 1 );
2✔
3438
    break;
3439
  }
3440
  case MTH_DEL_BUFF:
2✔
3441
  {
3442
    u16 icon;
3443

3444
    if ( !ex.hasParams( 1 ) )
2✔
3445
      return new BError( "Not enough parameters" );
2✔
3446
    if ( ex.getParam( 0, icon ) )
2✔
3447
    {
3448
      if ( !icon )
2✔
3449
        return new BError( "Invalid parameter" );
×
3450

3451
      if ( !delBuff( icon ) )
2✔
3452
        return new BError( "Buff not found" );
1✔
3453

3454
      return new BLong( 1 );
1✔
3455
    }
3456
    break;
×
3457
  }
3458
  default:
11✔
3459
    return nullptr;
11✔
3460
  }
3461
  return new BError( "Invalid parameter type" );
×
3462
}
3463

3464

3465
BObjectImp* Character::script_method( const char* methodname, Core::UOExecutor& ex )
×
3466
{
3467
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
3468
  if ( objmethod != nullptr )
×
3469
    return this->script_method_id( objmethod->id, ex );
×
3470
  return nullptr;
×
3471
}
3472

3473
BObjectImp* Character::custom_script_method( const char* methodname, Core::UOExecutor& ex )
×
3474
{
3475
  // TODO uoclient entry deprecated
3476
  if ( Core::networkManager.uoclient_general.method_script != nullptr )
×
3477
  {
3478
    unsigned PC;
3479
    if ( Core::networkManager.uoclient_general.method_script->FindExportedFunction(
×
3480
             methodname, static_cast<unsigned int>( ex.numParams() + 1 ), PC ) )
×
3481
      return Core::networkManager.uoclient_general.method_script->call( PC, make_ref(),
×
3482
                                                                        ex.fparams );
×
3483
  }
3484
  return Core::gamestate.system_hooks.call_script_method( methodname, &ex, this );
×
3485
}
3486

3487
ObjArray* Character::GetReportables() const
2✔
3488
{
3489
  std::unique_ptr<ObjArray> arr( new ObjArray );
2✔
3490

3491
  for ( ReportableList::const_iterator itr = reportable_.begin(), end = reportable_.end();
2✔
3492
        itr != end; ++itr )
4✔
3493
  {
3494
    const reportable_t& rt = ( *itr );
2✔
3495

3496
    std::unique_ptr<BObjectImp> kmember( nullptr );
2✔
3497
    Character* killer = Core::system_find_mobile( rt.serial );
2✔
3498
    if ( killer )
2✔
3499
      kmember = std::make_unique<Module::EOfflineCharacterRefObjImp>( killer );
2✔
3500
    else
3501
      kmember = std::make_unique<BError>( "Mobile not found" );
×
3502

3503
    std::unique_ptr<BStruct> elem( new BStruct );
2✔
3504
    elem->addMember( "serial", new BLong( rt.serial ) );
2✔
3505
    elem->addMember( "killer", kmember.release() );
2✔
3506
    elem->addMember( "gameclock", new BLong( static_cast<s32>( rt.polclock ) ) );
2✔
3507

3508
    arr->addElement( elem.release() );
2✔
3509
  }
2✔
3510
  return arr.release();
4✔
3511
}
2✔
3512

3513
ObjArray* Character::GetAggressorTo() const
×
3514
{
3515
  std::unique_ptr<ObjArray> arr( new ObjArray );
×
3516

3517
  for ( Character::MobileCont::const_iterator itr = aggressor_to_.begin(),
×
3518
                                              end = aggressor_to_.end();
×
3519
        itr != end; ++itr )
×
3520
  {
3521
    std::unique_ptr<BObjectImp> member( nullptr );
×
3522
    Character* chr = Core::system_find_mobile( ( *itr ).first->serial );
×
3523
    if ( chr )
×
3524
      member = std::make_unique<Module::EOfflineCharacterRefObjImp>( chr );
×
3525
    else
3526
      member = std::make_unique<BError>( "Mobile not found" );
×
3527

3528
    std::unique_ptr<BStruct> elem( new BStruct );
×
3529
    elem->addMember( "serial", new BLong( ( *itr ).first->serial ) );
×
3530
    elem->addMember( "ref", member.release() );
×
3531
    elem->addMember( "seconds",
×
3532
                     new BLong( static_cast<s32>( ( ( *itr ).second - Core::polclock() ) /
×
3533
                                                  Core::POLCLOCKS_PER_SEC ) ) );
×
3534

3535
    arr->addElement( elem.release() );
×
3536
  }
×
3537
  return arr.release();
×
3538
}
×
3539

3540
ObjArray* Character::GetLawFullyDamaged() const
×
3541
{
3542
  std::unique_ptr<ObjArray> arr( new ObjArray );
×
3543

3544
  for ( Character::MobileCont::const_iterator itr = lawfully_damaged_.begin(),
×
3545
                                              end = lawfully_damaged_.end();
×
3546
        itr != end; ++itr )
×
3547
  {
3548
    std::unique_ptr<BObjectImp> member( nullptr );
×
3549
    Character* chr = Core::system_find_mobile( ( *itr ).first->serial );
×
3550
    if ( chr )
×
3551
      member = std::make_unique<Module::EOfflineCharacterRefObjImp>( chr );
×
3552
    else
3553
      member = std::make_unique<BError>( "Mobile not found" );
×
3554

3555
    std::unique_ptr<BStruct> elem( new BStruct );
×
3556
    elem->addMember( "serial", new BLong( ( *itr ).first->serial ) );
×
3557
    elem->addMember( "ref", member.release() );
×
3558
    elem->addMember( "seconds",
×
3559
                     new BLong( static_cast<s32>( ( ( *itr ).second - Core::polclock() ) /
×
3560
                                                  Core::POLCLOCKS_PER_SEC ) ) );
×
3561

3562
    arr->addElement( elem.release() );
×
3563
  }
×
3564
  return arr.release();
×
3565
}
×
3566

3567
BObjectImp* NPC::get_script_member_id( const int id ) const
447✔
3568
{
3569
  BObjectImp* imp = base::get_script_member_id( id );
447✔
3570
  if ( imp != nullptr )
447✔
3571
    return imp;
387✔
3572

3573
  switch ( id )
60✔
3574
  {
3575
  case MBR_SCRIPT:
1✔
3576
    return new String( script );
1✔
3577
    break;
3578
  case MBR_NPCTEMPLATE:
×
3579
    return new String( template_name );
×
3580
    break;
3581
  case MBR_MASTER:
1✔
3582
  {
3583
    Character* master = master_.get();
1✔
3584
    if ( master != nullptr && !master->orphan() )
1✔
3585
      return new Module::EOfflineCharacterRefObjImp( master );
1✔
3586
    return new BLong( 0 );
×
3587
    break;
3588
  }
3589

3590
  case MBR_PROCESS:
52✔
3591
    if ( ex )
52✔
3592
      return new Core::ScriptExObjImp( ex );
52✔
3593
    return new BError( "No script running" );
×
3594
    break;
3595

3596
  case MBR_EVENTMASK:
×
3597
    if ( ex )
×
3598
      return new BLong( ex->eventmask );
×
3599
    return new BError( "No script running" );
×
3600
    break;
3601

3602
  case MBR_SPEECH_COLOR:
1✔
3603
    return new BLong( speech_color() );
1✔
3604
    break;
3605
  case MBR_SPEECH_FONT:
1✔
3606
    return new BLong( speech_font() );
1✔
3607
    break;
3608
  case MBR_USE_ADJUSTMENTS:
1✔
3609
    return new BLong( use_adjustments() ? 1 : 0 );
1✔
3610
    break;
3611
  case MBR_RUN_SPEED:
1✔
3612
    return new BLong( run_speed );
1✔
3613
    break;
3614
  case MBR_ALIGNMENT:
×
3615
    return new BLong( template_->alignment );
×
3616
    break;
3617
  case MBR_SAVEONEXIT:
×
3618
    return new BLong( saveonexit() );
×
3619
    break;
3620
  case MBR_NO_DROP_EXCEPTION:
2✔
3621
    return new BLong( no_drop_exception() );
2✔
3622
  default:
×
3623
    return nullptr;
×
3624
  }
3625
}
3626

3627
BObjectImp* NPC::get_script_member( const char* membername ) const
35✔
3628
{
3629
  ObjMember* objmember = getKnownObjMember( membername );
35✔
3630
  if ( objmember != nullptr )
35✔
3631
    return this->get_script_member_id( objmember->id );
35✔
3632
  return nullptr;
×
3633
}
3634

3635
BObjectImp* NPC::set_script_member_id( const int id, const std::string& value )
×
3636
{
3637
  BObjectImp* imp = base::set_script_member_id( id, value );
×
3638
  if ( imp != nullptr )
×
3639
    return imp;
×
3640
  switch ( id )
×
3641
  {
3642
  case MBR_SCRIPT:
×
3643
    return new String( script = value );
×
3644
  default:
×
3645
    return nullptr;
×
3646
  }
3647
}
3648

3649
BObjectImp* NPC::set_script_member( const char* membername, const std::string& value )
×
3650
{
3651
  ObjMember* objmember = getKnownObjMember( membername );
×
3652
  if ( objmember != nullptr )
×
3653
    return this->set_script_member_id( objmember->id, value );
×
3654
  return nullptr;
×
3655
}
3656

3657
BObjectImp* NPC::set_script_member_id( const int id, int value )
29✔
3658
{
3659
  BObjectImp* imp = base::set_script_member_id( id, value );
29✔
3660
  if ( imp != nullptr )
29✔
3661
    return imp;
22✔
3662
  switch ( id )
7✔
3663
  {
3664
  case MBR_SPEECH_COLOR:
×
3665
    speech_color( Clib::clamp_convert<u16>( value ) );
×
3666
    return new BLong( speech_color() );
×
3667
  case MBR_SPEECH_FONT:
×
3668
    speech_font( Clib::clamp_convert<u16>( value ) );
×
3669
    return new BLong( speech_font() );
×
3670
  case MBR_USE_ADJUSTMENTS:
×
3671
    use_adjustments( value ? true : false );
×
3672
    return new BLong( use_adjustments() );
×
3673
  case MBR_RUN_SPEED:
×
3674
    return new BLong( run_speed = Clib::clamp_convert<u16>( value ) );
×
3675
  case MBR_SAVEONEXIT:
1✔
3676
    saveonexit( value ? true : false );
1✔
3677
    return new BLong( saveonexit() );
1✔
3678
  case MBR_NO_DROP_EXCEPTION:
×
3679
    no_drop_exception( value ? true : false );
×
3680
    return new BLong( no_drop_exception() );
×
3681
  default:
6✔
3682
    return nullptr;
6✔
3683
  }
3684
}
3685
BObjectImp* NPC::set_script_member( const char* membername, int value )
×
3686
{
3687
  ObjMember* objmember = getKnownObjMember( membername );
×
3688
  if ( objmember != nullptr )
×
3689
    return this->set_script_member_id( objmember->id, value );
×
3690
  return nullptr;
×
3691
}
3692

3693
BObjectImp* NPC::script_method_id( const int id, Core::UOExecutor& executor )
157✔
3694
{
3695
  BObjectImp* imp = base::script_method_id( id, executor );
157✔
3696
  if ( imp != nullptr )
157✔
3697
    return imp;
146✔
3698

3699
  switch ( id )
11✔
3700
  {
3701
  case MTH_SETMASTER:
11✔
3702
  {
3703
    if ( executor.numParams() != 1 )
11✔
3704
      return new BError( "Not enough parameters" );
×
3705
    Character* chr;
3706
    set_dirty();
11✔
3707
    if ( executor.getCharacterParam( 0, chr ) )
11✔
3708
    {
3709
      master_.set( chr );
11✔
3710
      return new BLong( 1 );
11✔
3711
    }
3712

NEW
3713
    master_.clear();
×
NEW
3714
    return new BLong( 0 );
×
3715

3716
    break;
3717
  }
3718
  default:
×
3719
    return nullptr;
×
3720
  }
3721
}
3722

3723
BObjectImp* NPC::script_method( const char* methodname, Core::UOExecutor& executor )
×
3724
{
3725
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
3726
  if ( objmethod != nullptr )
×
3727
    return this->script_method_id( objmethod->id, executor );
×
3728
  return nullptr;
×
3729
}
3730

3731
BObjectImp* NPC::custom_script_method( const char* methodname, Core::UOExecutor& executor )
×
3732
{
3733
  if ( template_->method_script != nullptr )
×
3734
  {
3735
    unsigned PC;
3736
    if ( template_->method_script->FindExportedFunction(
×
3737
             methodname, static_cast<unsigned int>( executor.numParams() + 1 ), PC ) )
×
3738
      return template_->method_script->call( PC, make_ref(), executor.fparams );
×
3739
  }
3740
  return Core::gamestate.system_hooks.call_script_method( methodname, &executor, this );
×
3741
}
3742
}  // namespace Mobile
3743
namespace Core
3744
{
3745
using namespace Bscript;
3746

3747
BObjectImp* ULockable::get_script_member_id( const int id ) const
238✔
3748
{
3749
  BObjectImp* imp = Item::get_script_member_id( id );
238✔
3750
  if ( imp != nullptr )
238✔
3751
    return imp;
192✔
3752

3753
  switch ( id )
46✔
3754
  {
3755
  case MBR_LOCKED:
1✔
3756
    return new BLong( locked() ? 1 : 0 );
1✔
3757
    break;
3758
  default:
45✔
3759
    return nullptr;
45✔
3760
  }
3761
}
3762

3763
BObjectImp* ULockable::get_script_member( const char* membername ) const
×
3764
{
3765
  ObjMember* objmember = getKnownObjMember( membername );
×
3766
  if ( objmember != nullptr )
×
3767
    return this->get_script_member_id( objmember->id );
×
3768
  return nullptr;
×
3769
}
3770

3771
BObjectImp* ULockable::set_script_member_id( const int id, int value )
61✔
3772
{
3773
  BObjectImp* imp = Item::set_script_member_id( id, value );
61✔
3774
  if ( imp != nullptr )
61✔
3775
    return imp;
48✔
3776
  switch ( id )
13✔
3777
  {
3778
  case MBR_LOCKED:
1✔
3779
    locked( value ? true : false );
1✔
3780
    return new BLong( locked() );
1✔
3781
  default:
12✔
3782
    return nullptr;
12✔
3783
  }
3784
}
3785

3786
BObjectImp* ULockable::set_script_member( const char* membername, int value )
×
3787
{
3788
  ObjMember* objmember = getKnownObjMember( membername );
×
3789
  if ( objmember != nullptr )
×
3790
    return this->set_script_member_id( objmember->id, value );
×
3791
  return nullptr;
×
3792
}
3793

3794
BObjectImp* UContainer::get_script_member_id( const int id ) const
218✔
3795
{
3796
  BObjectImp* imp = base::get_script_member_id( id );
218✔
3797
  if ( imp != nullptr )
218✔
3798
    return imp;
173✔
3799

3800
  switch ( id )
45✔
3801
  {
3802
  case MBR_MAX_ITEMS_MOD:
1✔
3803
    return new BLong( max_items_mod() );
1✔
3804
    break;
3805
  case MBR_MAX_WEIGHT_MOD:
1✔
3806
    return new BLong( max_weight_mod() );
1✔
3807
    break;
3808
  case MBR_MAX_SLOTS_MOD:
1✔
3809
    return new BLong( max_slots_mod() );
1✔
3810
    break;
3811
  case MBR_NO_DROP_EXCEPTION:
2✔
3812
    return new BLong( no_drop_exception() );
2✔
3813
  case MBR_HELD_WEIGHT_MULTIPLIER:
8✔
3814
    return new Double( held_weight_multiplier() );
8✔
3815
  default:
32✔
3816
    return nullptr;
32✔
3817
  }
3818
}
3819

3820
BObjectImp* UContainer::get_script_member( const char* membername ) const
6✔
3821
{
3822
  ObjMember* objmember = getKnownObjMember( membername );
6✔
3823
  if ( objmember != nullptr )
6✔
3824
    return this->get_script_member_id( objmember->id );
6✔
3825
  return nullptr;
×
3826
}
3827

3828
BObjectImp* UContainer::set_script_member_id( const int id, int value )
61✔
3829
{
3830
  BObjectImp* imp = base::set_script_member_id( id, value );
61✔
3831
  if ( imp != nullptr )
61✔
3832
    return imp;
49✔
3833
  switch ( id )
12✔
3834
  {
3835
  case MBR_MAX_ITEMS_MOD:
1✔
3836
    max_items_mod( Clib::clamp_convert<s16>( value ) );
1✔
3837
    break;
1✔
3838
  case MBR_MAX_WEIGHT_MOD:
1✔
3839
    max_weight_mod( Clib::clamp_convert<s16>( value ) );
1✔
3840
    break;
1✔
3841
  case MBR_MAX_SLOTS_MOD:
1✔
3842
    max_slots_mod( Clib::clamp_convert<s8>( value ) );
1✔
3843
    break;
1✔
3844
  case MBR_NO_DROP_EXCEPTION:
2✔
3845
    no_drop_exception( value ? true : false );
2✔
3846
    return new BLong( no_drop_exception() );
2✔
3847
  case MBR_WEIGHT_MULTIPLIER_MOD:
×
3848
    return set_script_member_id_double( id, value );
×
3849
  case MBR_HELD_WEIGHT_MULTIPLIER:
7✔
3850
    return set_script_member_id_double( id, value );
7✔
3851
  default:
×
3852
    return nullptr;
×
3853
  }
3854
  return new BLong( value );
3✔
3855
}
3856

3857
Bscript::BObjectImp* UContainer::set_script_member_id_double( const int id, double value )
13✔
3858
{
3859
  BObjectImp* imp = base::set_script_member_id_double( id, value );
13✔
3860
  if ( imp != nullptr )
13✔
3861
    return imp;
×
3862

3863
  switch ( id )
13✔
3864
  {
3865
  case MBR_HELD_WEIGHT_MULTIPLIER:
13✔
3866
  {
3867
    if ( container )
13✔
3868
    {
3869
      int oldweight = weight();
8✔
3870
      held_weight_multiplier( value );
8✔
3871
      container->add_bulk( 0, weight() - oldweight );
8✔
3872
    }
3873
    else
3874
    {
3875
      held_weight_multiplier( value );
5✔
3876
    }
3877

3878
    increv_send_object_recursive();
13✔
3879

3880
    UpdateCharacterWeight( this );
13✔
3881

3882
    return new Double( held_weight_multiplier() );
13✔
3883
  }
3884
  default:
×
3885
    break;
×
3886
  }
3887
  return nullptr;
×
3888
}
3889

3890
BObjectImp* UContainer::set_script_member( const char* membername, int value )
53✔
3891
{
3892
  ObjMember* objmember = getKnownObjMember( membername );
53✔
3893
  if ( objmember != nullptr )
53✔
3894
    return this->set_script_member_id( objmember->id, value );
53✔
3895
  return nullptr;
×
3896
}
3897

3898
BObjectImp* UCorpse::get_script_member_id( const int id ) const
39✔
3899
{
3900
  BObjectImp* imp = base::get_script_member_id( id );
39✔
3901
  if ( imp != nullptr )
39✔
3902
    return imp;
7✔
3903

3904
  switch ( id )
32✔
3905
  {
3906
  case MBR_CORPSETYPE:
1✔
3907
    return new BLong( corpsetype );
1✔
3908
    break;
3909
  case MBR_OWNERSERIAL:
31✔
3910
    return new BLong( ownerserial );
31✔
3911
    break;
3912
  default:
×
3913
    return nullptr;
×
3914
  }
3915
}
3916

3917
BObjectImp* UCorpse::get_script_member( const char* membername ) const
2✔
3918
{
3919
  ObjMember* objmember = getKnownObjMember( membername );
2✔
3920
  if ( objmember != nullptr )
2✔
3921
    return this->get_script_member_id( objmember->id );
2✔
3922
  return nullptr;
×
3923
}
3924

3925
BObjectImp* Spellbook::script_method_id( const int id, Core::UOExecutor& ex )
4✔
3926
{
3927
  BObjectImp* imp = base::script_method_id( id, ex );
4✔
3928
  if ( imp != nullptr )
4✔
3929
    return imp;
×
3930

3931
  switch ( id )
4✔
3932
  {
3933
  case MTH_HASSPELL:
2✔
3934
  {
3935
    u32 sid;
3936
    if ( !ex.hasParams( 1 ) )
2✔
3937
      return new BError( "Not enough parameters" );
2✔
3938
    if ( ex.getParam( 0, sid ) )
2✔
3939
    {
3940
      if ( sid == 0 )
2✔
3941
        return new BError( "SpellID must be >= 1" );
×
3942
      if ( this->has_spellid( sid ) )
2✔
3943
        return new BLong( 1 );
2✔
NEW
3944
      return new BLong( 0 );
×
3945
    }
3946
    break;
×
3947
  }
3948
  case MTH_SPELLS:
×
3949
  {
3950
    std::unique_ptr<ObjArray> arr( new ObjArray );
×
3951
    for ( u16 i = 0; i < 64; ++i )
×
3952
    {
3953
      unsigned int sid;
3954

3955
      // Check for Mysticism spells here
3956
      if ( this->spell_school == 3 )
×
3957
        sid = 678 + i;
×
3958
      else
3959
        sid = this->spell_school * 100 + i + 1;
×
3960

3961
      if ( this->has_spellid( sid ) )
×
3962
        arr->addElement( new BLong( sid ) );
×
3963
    }
3964
    return arr.release();
×
3965
    break;
3966
  }
×
3967
  case MTH_REMOVESPELL:
×
3968
  {
3969
    u32 sid;
3970
    if ( !ex.hasParams( 1 ) )
×
3971
      return new BError( "Not enough parameters" );
×
3972
    if ( ex.getParam( 0, sid ) )
×
3973
    {
3974
      if ( sid == 0 )
×
3975
        return new BError( "SpellID must be >= 1" );
×
3976
      if ( this->remove_spellid( sid ) )
×
3977
        return new BLong( 1 );
×
NEW
3978
      return new BLong( 0 );
×
3979
    }
3980
    break;
×
3981
  }
3982
  case MTH_ADDSPELL:
2✔
3983
  {
3984
    u32 sid;
3985
    if ( !ex.hasParams( 1 ) )
2✔
3986
      return new BError( "Not enough parameters" );
2✔
3987
    if ( ex.getParam( 0, sid ) )
2✔
3988
    {
3989
      if ( sid == 0 )
2✔
3990
        return new BError( "SpellID must be >= 1" );
×
3991
      if ( this->add_spellid( sid ) )
2✔
3992
        return new BLong( 1 );
2✔
NEW
3993
      return new BLong( 0 );
×
3994
    }
3995
    break;
×
3996
  }
3997

3998
  default:
×
3999
    return nullptr;
×
4000
  }
4001
  return new BError( "Invalid parameter type" );
×
4002
}
4003

4004
BObjectImp* Spellbook::script_method( const char* methodname, Core::UOExecutor& ex )
×
4005
{
4006
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4007
  if ( objmethod != nullptr )
×
4008
    return this->script_method_id( objmethod->id, ex );
×
4009
  return nullptr;
×
4010
}
4011
}  // namespace Core
4012
namespace Multi
4013
{
4014
using namespace Bscript;
4015

4016
BObjectImp* UBoat::make_ref()
5✔
4017
{
4018
  return new Module::EUBoatRefObjImp( this );
5✔
4019
}
4020

4021
BObjectImp* UMulti::make_ref()
23✔
4022
{
4023
  return new Module::EMultiRefObjImp( this );
23✔
4024
}
4025

4026
BObjectImp* UBoat::get_script_member_id( const int id ) const
6,153✔
4027
{
4028
  BObjectImp* imp = base::get_script_member_id( id );
6,153✔
4029
  if ( imp != nullptr )
6,153✔
4030
    return imp;
6,116✔
4031

4032
  switch ( id )
37✔
4033
  {
4034
  case MBR_TILLERMAN:
×
4035
  {
4036
    Item* cp = tillerman;
×
4037
    if ( cp != nullptr )
×
4038
      return new Module::EItemRefObjImp( cp );
×
4039
    return new BError( std::string( "This ship doesn't have that component" ) );
×
4040
    break;
4041
  }
4042
  case MBR_PORTPLANK:
20✔
4043
  {
4044
    Item* cp = portplank;
20✔
4045
    if ( cp != nullptr )
20✔
4046
      return new Module::EItemRefObjImp( cp );
20✔
4047
    return new BError( std::string( "This ship doesn't have that component" ) );
×
4048
    break;
4049
  }
4050
  case MBR_STARBOARDPLANK:
×
4051
  {
4052
    Item* cp = starboardplank;
×
4053
    if ( cp != nullptr )
×
4054
      return new Module::EItemRefObjImp( cp );
×
4055
    return new BError( std::string( "This ship doesn't have that component" ) );
×
4056
    break;
4057
  }
4058
  case MBR_HOLD:
×
4059
  {
4060
    Item* cp = hold;
×
4061
    if ( cp != nullptr )
×
4062
      return new Module::EItemRefObjImp( cp );
×
4063
    return new BError( std::string( "This ship doesn't have that component" ) );
×
4064
    break;
4065
  }
4066
  case MBR_ROPE:
×
4067
    return component_list( COMPONENT_ROPE );
×
4068
    break;
4069
  case MBR_WHEEL:
×
4070
    return component_list( COMPONENT_WHEEL );
×
4071
    break;
4072
  case MBR_HULL:
×
4073
    return component_list( COMPONENT_HULL );
×
4074
    break;
4075
  case MBR_TILLER:
×
4076
    return component_list( COMPONENT_TILLER );
×
4077
    break;
4078
  case MBR_RUDDER:
×
4079
    return component_list( COMPONENT_RUDDER );
×
4080
    break;
4081
  case MBR_SAILS:
×
4082
    return component_list( COMPONENT_SAILS );
×
4083
    break;
4084
  case MBR_STORAGE:
×
4085
    return component_list( COMPONENT_STORAGE );
×
4086
    break;
4087
  case MBR_WEAPONSLOT:
×
4088
    return component_list( COMPONENT_WEAPONSLOT );
×
4089
    break;
4090
  case MBR_COMPONENTS:
1✔
4091
    return component_list( COMPONENT_ALL );
1✔
4092
    break;
4093
  case MBR_ITEMS:
3✔
4094
    return items_list();
3✔
4095
    break;
4096
  case MBR_MOBILES:
4✔
4097
    return mobiles_list();
4✔
4098
    break;
4099
  case MBR_HAS_OFFLINE_MOBILES:
×
4100
    return new BLong( has_offline_mobiles() ? 1 : 0 );
×
4101
    break;
4102
  case MBR_MULTIID:
6✔
4103
    return new BLong( multiid_ );
6✔
4104
    break;
4105
  case MBR_PILOT:
3✔
4106
  {
4107
    Mobile::Character* owner = pilot();
3✔
4108
    if ( owner != nullptr )
3✔
4109
    {
4110
      return new Module::ECharacterRefObjImp( owner );
2✔
4111
    }
4112
  }
4113
    return new BLong( 0 );
1✔
4114
  default:
×
4115
    return nullptr;
×
4116
  }
4117
}
4118

4119
BObjectImp* UBoat::get_script_member( const char* membername ) const
2✔
4120
{
4121
  ObjMember* objmember = getKnownObjMember( membername );
2✔
4122
  if ( objmember != nullptr )
2✔
4123
    return this->get_script_member_id( objmember->id );
2✔
4124
  return nullptr;
×
4125
}
4126

4127
BObjectImp* UBoat::script_method_id( const int id, Core::UOExecutor& ex )
40✔
4128
{
4129
  BObjectImp* imp = base::script_method_id( id, ex );
40✔
4130
  if ( imp != nullptr )
40✔
4131
    return imp;
26✔
4132

4133
  switch ( id )
14✔
4134
  {
4135
  case MTH_MOVE_OFFLINE_MOBILES:
×
4136
  {
4137
    if ( ex.numParams() == 3 )
×
4138
    {
4139
      Core::Pos3d pos;
×
4140
      if ( !ex.getPos3dParam( 0, 1, 2, &pos, realm() ) )
×
4141
        return new BError( "Invalid parameter type" );
×
4142
      set_dirty();
×
4143
      move_offline_mobiles( Core::Pos4d( pos, realm() ) );
×
4144
      return new BLong( 1 );
×
4145
    }
NEW
4146
    if ( ex.numParams() == 4 )
×
4147
    {
4148
      Core::Pos4d pos;
×
4149
      if ( !ex.getPos4dParam( 0, 1, 2, 3, &pos ) )
×
4150
        return new BError( "Invalid parameter type" );
×
4151
      set_dirty();
×
4152
      move_offline_mobiles( pos );
×
4153
      return new BLong( 1 );
×
4154
    }
4155
    return new BError( "Not enough parameters" );
×
4156
  }
4157
  case MTH_SET_PILOT:
10✔
4158
  {
4159
    if ( !ex.hasParams( 1 ) )
10✔
4160
    {
4161
      return new BError( "Not enough parameters" );
×
4162
    }
4163

4164
    BObjectImp* impMaybeZero = ex.getParamImp( 0 );
10✔
4165

4166
    if ( auto* value = impptrIf<BLong>( impMaybeZero ) )
10✔
4167
    {
4168
      if ( value->value() != 0 )
6✔
4169
        return new BError( "Invalid parameters" );
×
4170
      return set_pilot( nullptr );
6✔
4171
    }
4172

4173
    Mobile::Character* chr;
4174

4175
    if ( !ex.getCharacterParam( 0, chr ) )
4✔
NEW
4176
      return new BError( "Invalid parameters" );
×
4177

4178
    return set_pilot( chr );
4✔
4179
  }
4180
  case MTH_SET_ALTERNATE_MULTIID:
4✔
4181
  {
4182
    if ( ex.numParams() != 1 )
4✔
4183
      return new BError( "Not enough parameters" );
×
4184
    u32 index;
4185
    if ( !ex.getParam( 0, index ) )
4✔
4186
      return new BError( "Invalid parameter type" );
×
4187
    const auto& desc = static_cast<const Items::BoatDesc&>( itemdesc() );
4✔
4188
    if ( index >= desc.alternates.size() )
4✔
4189
      return new BError( "Index out of range" );
1✔
4190

4191
    {
4192
      UBoat::BoatMoveGuard guard( this );
3✔
4193
      u16 new_multiid = desc.alternates[index];
3✔
4194
      u16 base_multi = multiid_ & ~3u;
3✔
4195
      u16 multioffset = multiid_ - base_multi;
3✔
4196
      multiid_ = new_multiid + multioffset;
3✔
4197
    }
3✔
4198
    transform_components( boatshape() );
3✔
4199
    send_display_boat_to_inrange( {} );
3✔
4200
    return new BLong( 1 );
3✔
4201
  }
4202
  default:
×
4203
    return nullptr;
×
4204
  }
4205
}
4206

4207
BObjectImp* UBoat::script_method( const char* methodname, Core::UOExecutor& ex )
×
4208
{
4209
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4210
  if ( objmethod != nullptr )
×
4211
    return this->script_method_id( objmethod->id, ex );
×
4212
  return nullptr;
×
4213
}
4214

4215
BObjectImp* UPlank::get_script_member_id( const int id ) const
20✔
4216
{
4217
  switch ( id )
20✔
4218
  {
4219
  case MBR_MULTI:
×
4220
    if ( boat_.get() )
×
4221
      return new Module::EUBoatRefObjImp( boat_.get() );
×
4222
    return new BError( "No boat attached" );
×
4223
    break;
4224
  }
4225
  return base::get_script_member_id( id );
20✔
4226
}
4227

4228
/* UObject defines a 'multi' also, so we have to trap that here first */
4229
BObjectImp* UPlank::get_script_member( const char* membername ) const
×
4230
{
4231
  ObjMember* objmember = getKnownObjMember( membername );
×
4232
  if ( objmember != nullptr )
×
4233
    return this->get_script_member_id( objmember->id );
×
4234
  return base::get_script_member( membername );
×
4235
}
4236
}  // namespace Multi
4237
namespace Core
4238
{
4239
using namespace Bscript;
4240

4241
BObjectImp* Map::get_script_member_id( const int id ) const
9✔
4242
{
4243
  BObjectImp* imp = base::get_script_member_id( id );
9✔
4244
  if ( imp != nullptr )
9✔
4245
    return imp;
1✔
4246

4247
  switch ( id )
8✔
4248
  {
4249
  case MBR_XEAST:
1✔
4250
    return new BLong( xeast );
1✔
4251
  case MBR_XWEST:
1✔
4252
    return new BLong( xwest );
1✔
4253
  case MBR_YNORTH:
1✔
4254
    return new BLong( ynorth );
1✔
4255
  case MBR_YSOUTH:
1✔
4256
    return new BLong( ysouth );
1✔
4257
  case MBR_GUMPWIDTH:
1✔
4258
    return new BLong( gumpsize.x() );
1✔
4259
  case MBR_GUMPHEIGHT:
1✔
4260
    return new BLong( gumpsize.y() );
1✔
4261
  case MBR_FACETID:
1✔
4262
    return new BLong( facetid );
1✔
4263
  case MBR_EDITABLE:
1✔
4264
    return new BLong( editable ? 1 : 0 );
1✔
4265
  default:
×
4266
    return nullptr;
×
4267
  }
4268
}
4269

4270
BObjectImp* Map::get_script_member( const char* membername ) const
8✔
4271
{
4272
  ObjMember* objmember = getKnownObjMember( membername );
8✔
4273
  if ( objmember != nullptr )
8✔
4274
    return this->get_script_member_id( objmember->id );
8✔
4275
  return nullptr;
×
4276
}
4277

4278
BObjectImp* Map::set_script_member_id( const int id, int value )
8✔
4279
{
4280
  BObjectImp* imp = base::set_script_member_id( id, value );
8✔
4281
  if ( imp != nullptr )
8✔
4282
    return imp;
×
4283
  switch ( id )
8✔
4284
  {
4285
  case MBR_XEAST:
1✔
4286
    return new BLong( xeast = Clib::clamp_convert<u16>( value ) );
1✔
4287
  case MBR_XWEST:
1✔
4288
    return new BLong( xwest = Clib::clamp_convert<u16>( value ) );
1✔
4289
  case MBR_YNORTH:
1✔
4290
    return new BLong( ynorth = Clib::clamp_convert<u16>( value ) );
1✔
4291
  case MBR_YSOUTH:
1✔
4292
    return new BLong( ysouth = Clib::clamp_convert<u16>( value ) );
1✔
4293
  case MBR_GUMPWIDTH:
1✔
4294
    gumpsize.x( Clib::clamp_convert<u16>( value ) );
1✔
4295
    return new BLong( gumpsize.x() );
1✔
4296
  case MBR_GUMPHEIGHT:
1✔
4297
    gumpsize.y( Clib::clamp_convert<u16>( value ) );
1✔
4298
    return new BLong( gumpsize.y() );
1✔
4299
  case MBR_FACETID:
1✔
4300
    return new BLong( facetid = Clib::clamp_convert<u16>( value ) );
1✔
4301
  case MBR_EDITABLE:
1✔
4302
    return new BLong( editable = value ? true : false );
1✔
4303
  default:
×
4304
    return nullptr;
×
4305
  }
4306
}
4307
BObjectImp* Map::set_script_member( const char* membername, int value )
8✔
4308
{
4309
  ObjMember* objmember = getKnownObjMember( membername );
8✔
4310
  if ( objmember != nullptr )
8✔
4311
    return this->set_script_member_id( objmember->id, value );
8✔
4312
  return nullptr;
×
4313
}
4314

4315
BObjectImp* UObject::script_method_id( const int id, Core::UOExecutor& ex )
644✔
4316
{
4317
  switch ( id )
644✔
4318
  {
4319
  case MTH_ISA:
×
4320
  {
4321
    if ( !ex.hasParams( 1 ) )
×
4322
      return new BError( "Not enough parameters" );
×
4323
    u32 isatype;
4324
    if ( ex.getParam( 0, isatype ) )
×
4325
      return new BLong( script_isa( isatype ) );
×
4326
    break;
×
4327
  }
4328
  case MTH_SET_MEMBER:
189✔
4329
  {
4330
    if ( !ex.hasParams( 2 ) )
189✔
4331
      return new BError( "Not enough parameters" );
189✔
4332
    BObjectImp* objimp;
4333
    const String* mname;
4334
    if ( ex.getStringParam( 0, mname ) && ( objimp = ex.getParamImp( 1 ) ) != nullptr )
189✔
4335
    {
4336
      BObjectImp* ret;
4337
      if ( auto* l = impptrIf<BLong>( objimp ) )
189✔
4338
        ret = set_script_member( mname->value().c_str(), l->value() );
170✔
4339
      else if ( auto* d = impptrIf<Double>( objimp ) )
19✔
4340
        ret = set_script_member_double( mname->value().c_str(), d->value() );
6✔
4341
      else if ( auto* s = impptrIf<String>( objimp ) )
13✔
4342
        ret = set_script_member( mname->value().c_str(), s->value() );
13✔
4343
      else
4344
        return new BError( "Invalid value type" );
×
4345

4346
      if ( ret != nullptr )
189✔
4347
        return ret;
189✔
4348

NEW
4349
      std::string message = std::string( "Member " ) + std::string( mname->value() ) +
×
NEW
4350
                            std::string( " not found on that object" );
×
NEW
4351
      return new BError( message );
×
4352
    }
×
4353
    break;
×
4354
  }
4355
  case MTH_GET_MEMBER:
246✔
4356
  {
4357
    if ( !ex.hasParams( 1 ) )
246✔
4358
      return new BError( "Not enough parameters" );
246✔
4359

4360
    const String* mname;
4361
    if ( ex.getStringParam( 0, mname ) )
246✔
4362
    {
4363
      BObjectImp* ret = get_script_member( mname->value().c_str() );
246✔
4364
      if ( ret != nullptr )
246✔
4365
        return ret;
246✔
4366

NEW
4367
      std::string message = std::string( "Member " ) + std::string( mname->value() ) +
×
NEW
4368
                            std::string( " not found on that object" );
×
NEW
4369
      return new BError( message );
×
4370
    }
×
4371
    break;
×
4372
  }
4373
  default:
209✔
4374
  {
4375
    bool changed = false;
209✔
4376
    BObjectImp* imp = CallPropertyListMethod_id( proplist_, id, ex, changed );
209✔
4377
    if ( changed )
209✔
4378
      set_dirty();
43✔
4379
    return imp;
209✔
4380
  }
4381
  }
4382
  return new BError( "Invalid parameter type" );
×
4383
}
4384

4385

4386
BObjectImp* UObject::script_method( const char* methodname, Core::UOExecutor& ex )
×
4387
{
4388
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4389
  if ( objmethod != nullptr )
×
4390
    return this->script_method_id( objmethod->id, ex );
×
4391

NEW
4392
  bool changed = false;
×
NEW
4393
  BObjectImp* imp = CallPropertyListMethod( proplist_, methodname, ex, changed );
×
NEW
4394
  if ( changed )
×
NEW
4395
    set_dirty();
×
4396

NEW
4397
  return imp;
×
4398
}
4399

4400
BObjectImp* UObject::custom_script_method( const char* methodname, Core::UOExecutor& ex )
×
4401
{
4402
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4403
  if ( objmethod != nullptr )
×
4404
    return this->script_method_id( objmethod->id, ex );
×
4405
  return Core::gamestate.system_hooks.call_script_method( methodname, &ex, this );
×
4406
}
4407

4408
BObjectImp* UDoor::get_script_member_id( const int id ) const
×
4409
{
4410
  BObjectImp* imp = ULockable::get_script_member_id( id );
×
4411
  if ( imp != nullptr )
×
4412
    return imp;
×
4413

4414
  switch ( id )
×
4415
  {
4416
  case MBR_ISOPEN:
×
4417
    return new BLong( is_open() ? 1 : 0 );
×
4418
    break;
4419
  default:
×
4420
    return nullptr;
×
4421
  }
4422
}
4423

4424
BObjectImp* UDoor::get_script_member( const char* membername ) const
×
4425
{
4426
  ObjMember* objmember = getKnownObjMember( membername );
×
4427
  if ( objmember != nullptr )
×
4428
    return this->get_script_member_id( objmember->id );
×
4429
  return nullptr;
×
4430
}
4431

4432
BObjectImp* UDoor::script_method_id( const int id, Core::UOExecutor& ex )
×
4433
{
4434
  BObjectImp* imp = base::script_method_id( id, ex );
×
4435
  if ( imp != nullptr )
×
4436
    return imp;
×
4437

4438
  switch ( id )
×
4439
  {
4440
  case MTH_OPEN:
×
4441
    open();
×
4442
    break;
×
4443
  case MTH_CLOSE:
×
4444
    close();
×
4445
    break;
×
4446
  case MTH_TOGGLE:
×
4447
    toggle();
×
4448
    break;
×
4449
  default:
×
4450
    return nullptr;
×
4451
  }
4452
  return new BLong( 1 );
×
4453
}
4454

4455
BObjectImp* UDoor::script_method( const char* methodname, Core::UOExecutor& ex )
×
4456
{
4457
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4458
  if ( objmethod != nullptr )
×
4459
    return this->script_method_id( objmethod->id, ex );
×
4460
  return nullptr;
×
4461
}
4462
}  // namespace Core
4463
namespace Items
4464
{
4465
using namespace Bscript;
4466

4467
BObjectImp* Equipment::get_script_member_id( const int id ) const
7✔
4468
{
4469
  BObjectImp* imp = Item::get_script_member_id( id );
7✔
4470
  if ( imp != nullptr )
7✔
4471
    return imp;
2✔
4472

4473
  switch ( id )
5✔
4474
  {
4475
  case MBR_INTRINSIC:
×
4476
    return new BLong( is_intrinsic() );
×
4477
    break;
4478
  default:
5✔
4479
    return nullptr;
5✔
4480
  }
4481
}
4482
BObjectImp* Equipment::get_script_member( const char* membername ) const
×
4483
{
4484
  ObjMember* objmember = getKnownObjMember( membername );
×
4485
  if ( objmember != nullptr )
×
4486
    return this->get_script_member_id( objmember->id );
×
4487
  return nullptr;
×
4488
}
4489

4490
BObjectImp* Equipment::set_script_member_id( const int id, int value )
3✔
4491
{
4492
  BObjectImp* imp = Item::set_script_member_id( id, value );
3✔
4493
  if ( imp != nullptr )
3✔
4494
    return imp;
×
4495

4496
  return nullptr;
3✔
4497
  /*
4498
  switch(id)
4499
  {
4500
  default: return nullptr;
4501
  }
4502
  */
4503
}
4504
BObjectImp* Equipment::set_script_member( const char* membername, int value )
×
4505
{
4506
  ObjMember* objmember = getKnownObjMember( membername );
×
4507
  if ( objmember != nullptr )
×
4508
    return this->set_script_member_id( objmember->id, value );
×
4509
  return nullptr;
×
4510
}
4511

4512
BObjectImp* Equipment::set_script_member_id_double( const int id, double value )
×
4513
{
4514
  BObjectImp* imp = Item::set_script_member_id_double( id, value );
×
4515
  if ( imp != nullptr )
×
4516
    return imp;
×
4517

4518
  return nullptr;
×
4519
  /*
4520
  switch(id)
4521
  {
4522
  default: return nullptr;
4523
  }
4524
  */
4525
}
4526
BObjectImp* Equipment::set_script_member_double( const char* membername, double value )
×
4527
{
4528
  ObjMember* objmember = getKnownObjMember( membername );
×
4529
  if ( objmember != nullptr )
×
4530
    return this->set_script_member_id_double( objmember->id, value );
×
4531
  return nullptr;
×
4532
}
4533

4534

4535
BObjectImp* UWeapon::get_script_member_id( const int id ) const
4✔
4536
{
4537
  BObjectImp* imp = Equipment::get_script_member_id( id );
4✔
4538
  if ( imp != nullptr )
4✔
4539
    return imp;
1✔
4540

4541
  switch ( id )
3✔
4542
  {
4543
  case MBR_DMG_MOD:
1✔
4544
    return new BLong( damage_mod() );
1✔
4545
    break;
4546
  case MBR_SPEED_MOD:
1✔
4547
    return new BLong( speed_mod() );
1✔
4548
    break;
4549
  case MBR_ATTRIBUTE:
×
4550
    return new String( attribute().name );
×
4551
    break;
4552
  case MBR_HITSCRIPT:
1✔
4553
    return new String( hit_script_.qualifiedname() );
1✔
4554
    break;
4555
  default:
×
4556
    return nullptr;
×
4557
  }
4558
}
4559
BObjectImp* UWeapon::get_script_member( const char* membername ) const
3✔
4560
{
4561
  ObjMember* objmember = getKnownObjMember( membername );
3✔
4562
  if ( objmember != nullptr )
3✔
4563
    return this->get_script_member_id( objmember->id );
3✔
4564
  return nullptr;
×
4565
}
4566

4567
BObjectImp* UWeapon::set_script_member_id( const int id, const std::string& value )
2✔
4568
{
4569
  BObjectImp* imp = Item::set_script_member_id( id, value );
2✔
4570
  if ( imp != nullptr )
2✔
4571
    return imp;
1✔
4572

4573
  switch ( id )
1✔
4574
  {
4575
  case MBR_HITSCRIPT:
1✔
4576
    set_hit_script( value );
1✔
4577
    return new BLong( 1 );
1✔
4578
  default:
×
4579
    return nullptr;
×
4580
  }
4581
}
4582
BObjectImp* UWeapon::set_script_member( const char* membername, const std::string& value )
1✔
4583
{
4584
  ObjMember* objmember = getKnownObjMember( membername );
1✔
4585
  if ( objmember != nullptr )
1✔
4586
    return this->set_script_member_id( objmember->id, value );
1✔
4587
  return nullptr;
×
4588
}
4589

4590
BObjectImp* UWeapon::set_script_member_id( const int id, int value )
2✔
4591
{
4592
  if ( is_intrinsic() )
2✔
4593
    return new BError( "Cannot alter an instrinsic NPC weapon member values" );  // executor won't
×
4594
                                                                                 // return this to
4595
                                                                                 // the script
4596
                                                                                 // currently.
4597

4598
  BObjectImp* imp = Equipment::set_script_member_id( id, value );
2✔
4599
  if ( imp != nullptr )
2✔
4600
    return imp;
×
4601

4602
  switch ( id )
2✔
4603
  {
4604
  case MBR_DMG_MOD:
1✔
4605
    damage_mod( Clib::clamp_convert<s16>( value ) );
1✔
4606
    break;
1✔
4607
  case MBR_SPEED_MOD:
1✔
4608
    speed_mod( Clib::clamp_convert<s16>( value ) );
1✔
4609
    break;
1✔
4610
  default:
×
4611
    return nullptr;
×
4612
  }
4613
  return new BLong( value );
2✔
4614
}
4615

4616
BObjectImp* UWeapon::set_script_member( const char* membername, int value )
2✔
4617
{
4618
  ObjMember* objmember = getKnownObjMember( membername );
2✔
4619
  if ( objmember != nullptr )
2✔
4620
    return this->set_script_member_id( objmember->id, value );
2✔
4621
  return nullptr;
×
4622
}
4623

4624
BObjectImp* UWeapon::set_script_member_id_double( const int id, double value )
×
4625
{
4626
  if ( is_intrinsic() )
×
4627
    return new BError( "Cannot alter an instrinsic NPC weapon member values" );  // executor won't
×
4628
                                                                                 // return this to
4629
                                                                                 // the script
4630
                                                                                 // currently.
4631
  return base::set_script_member_id_double( id, value );
×
4632
}
4633

4634
BObjectImp* UWeapon::set_script_member_double( const char* membername, double value )
×
4635
{
4636
  ObjMember* objmember = getKnownObjMember( membername );
×
4637
  if ( objmember != nullptr )
×
4638
    return this->set_script_member_id_double( objmember->id, value );
×
4639
  return base::set_script_member_double( membername, value );
×
4640
}
4641

4642
BObjectImp* UArmor::get_script_member_id( const int id ) const
3✔
4643
{
4644
  BObjectImp* imp = Equipment::get_script_member_id( id );
3✔
4645
  if ( imp != nullptr )
3✔
4646
    return imp;
1✔
4647

4648
  switch ( id )
2✔
4649
  {
4650
  case MBR_AR_MOD:
1✔
4651
    return new BLong( ar_mod() );
1✔
4652
    break;
4653
  case MBR_AR:
×
4654
    return new BLong( ar() );
×
4655
    break;
4656
  case MBR_AR_BASE:
×
4657
    return new BLong( ar_base() );
×
4658
    break;
4659
  case MBR_ONHIT_SCRIPT:
1✔
4660
    // bad method name? nullptr makes it return the fullpath
4661
    return new String( onhitscript_.qualifiedname() );
1✔
4662
    break;
4663
  default:
×
4664
    return nullptr;
×
4665
  }
4666
}
4667

4668
BObjectImp* UArmor::get_script_member( const char* membername ) const
2✔
4669
{
4670
  ObjMember* objmember = getKnownObjMember( membername );
2✔
4671
  if ( objmember != nullptr )
2✔
4672
    return this->get_script_member_id( objmember->id );
2✔
4673
  return nullptr;
×
4674
}
4675

4676
BObjectImp* UArmor::set_script_member_id( const int id, const std::string& value )
2✔
4677
{
4678
  BObjectImp* imp = Item::set_script_member_id( id, value );
2✔
4679
  if ( imp != nullptr )
2✔
4680
    return imp;
1✔
4681
  switch ( id )
1✔
4682
  {
4683
  case MBR_ONHIT_SCRIPT:
1✔
4684
    set_onhitscript( value );
1✔
4685
    return new BLong( 1 );
1✔
4686
  default:
×
4687
    return nullptr;
×
4688
  }
4689
}
4690

4691
BObjectImp* UArmor::set_script_member( const char* membername, const std::string& value )
1✔
4692
{
4693
  ObjMember* objmember = getKnownObjMember( membername );
1✔
4694
  if ( objmember != nullptr )
1✔
4695
    return this->set_script_member_id( objmember->id, value );
1✔
4696
  return nullptr;
×
4697
}
4698

4699
BObjectImp* UArmor::set_script_member_id( const int id, int value )
1✔
4700
{
4701
  BObjectImp* imp = Equipment::set_script_member_id( id, value );
1✔
4702
  if ( imp != nullptr )
1✔
4703
    return imp;
×
4704

4705
  switch ( id )
1✔
4706
  {
4707
  case MBR_AR_MOD:
1✔
4708
    this->ar_mod( Clib::clamp_convert<s16>( value ) );
1✔
4709
    if ( container != nullptr )
1✔
4710
    {
4711
      if ( Core::IsCharacter( container->serial ) )
×
4712
      {
4713
        Mobile::Character* chr = container->get_chr_owner();
×
4714
        if ( chr != nullptr )
×
4715
          Mobile::ARUpdater::on_change( chr );
×
4716
      }
4717
    }
4718
    return new BLong( value );
1✔
4719
  default:
×
4720
    return nullptr;
×
4721
  }
4722
}
4723

4724
BObjectImp* UArmor::set_script_member( const char* membername, int value )
1✔
4725
{
4726
  ObjMember* objmember = getKnownObjMember( membername );
1✔
4727
  if ( objmember != nullptr )
1✔
4728
    return this->set_script_member_id( objmember->id, value );
1✔
4729
  return nullptr;
×
4730
}
4731
}  // namespace Items
4732
namespace Module
4733
{
4734
using namespace Bscript;
4735

4736
const char* EClientRefObjImp::typeOf() const
×
4737
{
4738
  return "ClientRef";
×
4739
}
4740

4741
u8 EClientRefObjImp::typeOfInt() const
×
4742
{
4743
  return OTClientRef;
×
4744
}
4745

4746
BObjectImp* EClientRefObjImp::copy() const
×
4747
{
4748
  if ( value().exists() )
×
4749
    return value()->make_ref();
×
4750
  return new BError( "Client is disconnected" );
×
4751
}
4752

4753
bool EClientRefObjImp::isTrue() const
2✔
4754
{
4755
  return ( value().exists() && value()->isConnected() );
2✔
4756
}
4757

4758
bool EClientRefObjImp::operator==( const BObjectImp& objimp ) const
×
4759
{
4760
  if ( objimp.isa( BObjectImp::OTApplicObj ) )
×
4761
  {
4762
    const BApplicObjBase* aob =
4763
        Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
×
4764

4765
    if ( aob->object_type() == &eclientrefobjimp_type )
×
4766
    {
4767
      const EClientRefObjImp* clientref_imp =
4768
          Clib::explicit_cast<const EClientRefObjImp*, const BApplicObjBase*>( aob );
×
4769

4770
      if ( clientref_imp->value().exists() && value().exists() &&
×
4771
           ( clientref_imp->value()->chr != nullptr ) && ( value()->chr != nullptr ) )
×
4772
        return ( clientref_imp->value()->chr->serial == value()->chr->serial );
×
4773
      return false;
×
4774
    }
4775
    return false;
×
4776
  }
NEW
4777
  if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
×
4778
    return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
×
4779
  return false;
×
4780
}
4781

4782
BObjectRef EClientRefObjImp::get_member_id( const int id )
5✔
4783
{
4784
  if ( ( !obj_.exists() ) || ( !obj_->isConnected() ) )
5✔
4785
    return BObjectRef( new BError( "Client not ready or disconnected" ) );
×
4786

4787
  BObjectImp* result = obj_->get_script_member_id( id );
5✔
4788
  if ( result != nullptr )
5✔
4789
    return BObjectRef( result );
4✔
4790
  return BObjectRef( UninitObject::create() );
1✔
4791
}
4792

4793
BObjectRef EClientRefObjImp::get_member( const char* membername )
1✔
4794
{
4795
  if ( ( !obj_.exists() ) || ( !obj_->isConnected() ) )
1✔
4796
    return BObjectRef( new BError( "Client not ready or disconnected" ) );
×
4797
  ObjMember* objmember = getKnownObjMember( membername );
1✔
4798
  if ( objmember != nullptr )
1✔
4799
    return this->get_member_id( objmember->id );
×
4800
  return BObjectRef( UninitObject::create() );
1✔
4801
}
4802

4803
BObjectRef EClientRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
×
4804
{
4805
  if ( !obj_.exists() || !obj_->isConnected() )
×
4806
    return BObjectRef( new BError( "Client not ready or disconnected" ) );
×
4807
  ObjMember* objmember = getKnownObjMember( membername );
×
4808
  if ( objmember != nullptr )
×
4809
    return this->set_member_id( objmember->id, value, copy );
×
4810
  return BObjectRef( UninitObject::create() );
×
4811
}
4812

4813
BObjectRef EClientRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
2✔
4814
{
4815
  if ( !obj_.exists() || !obj_->isConnected() )
2✔
4816
    return BObjectRef( new BError( "Client not ready or disconnected" ) );
×
4817

4818
  BObjectImp* result = nullptr;
2✔
4819
  if ( auto* v = impptrIf<BLong>( value ) )
2✔
4820
    result = obj_->set_script_member_id( id, v->value() );
2✔
4821

4822
  if ( result != nullptr )
2✔
4823
    return BObjectRef( result );
2✔
4824

4825
  return BObjectRef( UninitObject::create() );
×
4826
}
4827

4828

4829
BObjectImp* EClientRefObjImp::call_polmethod( const char* methodname, Core::UOExecutor& ex )
×
4830
{
4831
  if ( !obj_.exists() || !obj_->isConnected() )
×
4832
    return new BError( "Client not ready or disconnected" );
×
4833
  bool forcebuiltin{ Executor::builtinMethodForced( methodname ) };
×
4834
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
4835
  if ( objmethod != nullptr )
×
4836
    return this->call_polmethod_id( objmethod->id, ex, forcebuiltin );
×
4837
  return Core::gamestate.system_hooks.call_script_method( methodname, &ex, this );
×
4838
}
4839

4840
BObjectImp* EClientRefObjImp::call_polmethod_id( const int id, Core::UOExecutor& ex,
×
4841
                                                 bool forcebuiltin )
4842
{
4843
  if ( !obj_.exists() || !obj_->isConnected() )
×
4844
    return new BError( "Client not ready or disconnected" );
×
4845

4846
  ObjMethod* mth = getObjMethod( id );
×
4847
  if ( mth->overridden && !forcebuiltin )
×
4848
  {
4849
    auto* imp = Core::gamestate.system_hooks.call_script_method( mth->code, &ex, this );
×
4850
    if ( imp )
×
4851
      return imp;
×
4852
  }
4853
  switch ( id )
×
4854
  {
4855
  case MTH_COMPAREVERSION:
×
4856
  {
4857
    if ( !ex.hasParams( 1 ) )
×
4858
      return new BError( "Not enough parameters" );
×
4859
    const String* pstr;
4860
    if ( ex.getStringParam( 0, pstr ) )
×
4861
      return new BLong( obj_->compareVersion( pstr->getStringRep() ) ? 1 : 0 );
×
4862
    return new BError( "Invalid parameter type" );
×
4863
  }
4864
  }
4865

4866
  return base::call_polmethod_id( id, ex );
×
4867
}
4868

4869
BoatMovementEvent::BoatMovementEvent( Mobile::Character* source, const u8 speed, const u8 direction,
3✔
4870
                                      const u8 relative_direction )
3✔
4871
{
4872
  addMember( "type", new BLong( Core::EVID_BOAT_MOVEMENT ) );
3✔
4873
  addMember( "source", new Module::EOfflineCharacterRefObjImp( source ) );
3✔
4874
  addMember( "speed", new BLong( static_cast<int>( speed ) ) );
3✔
4875
  addMember( "direction", new BLong( static_cast<int>( direction ) ) );
3✔
4876
  addMember( "relative_direction", new BLong( static_cast<int>( relative_direction ) ) );
3✔
4877
}
3✔
4878

4879
SourcedEvent::SourcedEvent( Core::EVENTID type, Mobile::Character* source )
20✔
4880
{
4881
  addMember( "type", new BLong( type ) );
20✔
4882
  addMember( "source", new Module::EOfflineCharacterRefObjImp( source ) );
20✔
4883
}
20✔
4884

4885
SpeechEvent::SpeechEvent( Mobile::Character* speaker, const std::string& speech,
3✔
4886
                          const std::string& texttype, std::string lang,
4887
                          Bscript::ObjArray* speechtokens )
3✔
4888
{
4889
  addMember( "type", new BLong( Core::EVID_SPOKE ) );
3✔
4890
  addMember( "source", new Module::EOfflineCharacterRefObjImp( speaker ) );
3✔
4891
  addMember( "text", new String( speech ) );
3✔
4892
  addMember( "texttype", new String( texttype ) );
3✔
4893
  if ( !lang.empty() )
3✔
4894
    addMember( "langcode", new String( lang ) );
3✔
4895
  if ( speechtokens != nullptr )
3✔
4896
    addMember( "tokens", new Bscript::ObjArray( *speechtokens ) );
3✔
4897
}
3✔
4898

4899
DamageEvent::DamageEvent( Mobile::Character* source, unsigned short damage )
×
4900
{
4901
  addMember( "type", new BLong( Core::EVID_DAMAGED ) );
×
4902

4903
  if ( source != nullptr )
×
4904
    addMember( "source", new Module::EOfflineCharacterRefObjImp( source ) );
×
4905
  else
4906
    addMember( "source", new BLong( 0 ) );
×
4907

4908
  addMember( "damage", new BLong( damage ) );
×
4909
}
×
4910

4911
ItemGivenEvent::ItemGivenEvent( Mobile::Character* chr_givenby, Items::Item* item_given,
×
4912
                                Mobile::NPC* chr_givento )
×
4913
    : SourcedEvent( Core::EVID_ITEM_GIVEN, chr_givenby ), given_by_( nullptr )
×
4914
{
4915
  addMember( "item", new EItemRefObjImp( item_given ) );
×
4916

4917
  given_time_ = Core::read_gameclock();
×
4918
  item_.set( item_given );
×
4919
  cont_.set( item_given->container );
×
4920
  given_by_.set( chr_givenby );
×
4921

4922
  item_given->setprop( "GivenBy", BLong::pack( chr_givenby->serial ) );
×
4923
  item_given->setprop( "GivenTo", BLong::pack( chr_givento->serial ) );
×
4924
  item_given->setprop( "GivenTime", BLong::pack( given_time_ ) );
×
4925
}
×
4926

4927
ItemGivenEvent::~ItemGivenEvent()
×
4928
{
4929
  /* See if the item is still in the container it was in
4930
       This means the AI script didn't do anything with it.
4931
       */
4932
  Items::Item* item = item_.get();
×
4933
  Core::UContainer* cont = cont_.get();
×
4934
  Mobile::Character* chr = given_by_.get();
×
4935

4936
  std::string given_time_str;
×
4937
  if ( !item->getprop( "GivenTime", given_time_str ) )
×
4938
    given_time_str = "";
×
4939

4940
  item->eraseprop( "GivenBy" );
×
4941
  item->eraseprop( "GivenTo" );
×
4942
  item->eraseprop( "GivenTime" );
×
4943

4944
  Bscript::BObject given_value( BObjectImp::unpack( given_time_str.c_str() ) );
×
4945
  int gts = given_value.impptr<BLong>()->value();
×
4946

4947
  if ( item->orphan() || cont->orphan() || chr->orphan() )
×
4948
    return;
×
4949

4950
  if ( item->container == cont && Clib::tostring( given_time_ ) == Clib::tostring( gts ) )
×
4951
  {
4952
    Core::UContainer* backpack = chr->backpack();
×
4953
    if ( backpack != nullptr && !chr->dead() )
×
4954
    {
4955
      if ( backpack->can_add( *item ) )
×
4956
      {
4957
        cont->remove( item );
×
4958
        u8 newSlot = 1;
×
4959
        if ( !backpack->can_add_to_slot( newSlot ) || !item->slot_index( newSlot ) )
×
4960
        {
4961
          item->setposition( chr->pos() );
×
4962
          add_item_to_world( item );
×
4963
          register_with_supporting_multi( item );
×
4964
          move_item( item, item->pos() );
×
4965
          return;
×
4966
        }
4967
        backpack->add( item, item->pos2d() );
×
4968
        update_item_to_inrange( item );
×
4969
        return;
×
4970
      }
4971
    }
4972
    cont->remove( item );
×
4973
    item->setposition( chr->pos() );
×
4974
    add_item_to_world( item );
×
4975
    register_with_supporting_multi( item );
×
4976
    move_item( item, item->pos() );
×
4977
  }
4978
}
×
4979
}  // namespace Module
4980

4981
namespace Network
4982
{
4983
using namespace Bscript;
4984
BObjectImp* Client::set_script_member_id( const int id, int value )
2✔
4985
{
4986
  switch ( id )
2✔
4987
  {
4988
  case MBR_DISABLE_INACTIVITY_TIMEOUT:
×
4989
    disable_inactivity_timeout( value );
×
4990
    return new BLong( disable_inactivity_timeout() );
×
4991
  case MBR_VISUAL_RANGE:
2✔
4992
    set_update_range_by_script( Clib::clamp_convert<u8>( value ) );
2✔
4993
    return new BLong( update_range() );
2✔
4994
  default:
×
4995
    return nullptr;
×
4996
  }
4997
}
4998

4999
BObjectImp* Client::get_script_member_id( const int id )
5✔
5000
{
5001
  switch ( id )
5✔
5002
  {
5003
  case MBR_ACCTNAME:
2✔
5004
    if ( acct != nullptr )
2✔
5005
      return new String( acct->name() );
2✔
5006
    return new BError( "Not attached to an account" );
×
5007
    break;
5008
  case MBR_ACCT:
2✔
5009
    if ( acct != nullptr )
2✔
5010
      return new Accounts::AccountObjImp( Accounts::AccountPtrHolder( Core::AccountRef( acct ) ) );
2✔
5011
    return new BError( "Not attached to an account" );
×
5012
    break;
5013
  case MBR_IP:
×
5014
    return new String( ipaddrAsString() );
×
5015
    break;
5016
  case MBR_CLIENTVERSION:
×
5017
    return new String( getversion() );
×
5018
    break;
5019
  case MBR_CLIENTVERSIONDETAIL:
×
5020
  {
5021
    std::unique_ptr<BStruct> info( new BStruct );
×
5022
    Network::VersionDetailStruct version = getversiondetail();
×
5023
    info->addMember( "major", new BLong( version.major ) );
×
5024
    info->addMember( "minor", new BLong( version.minor ) );
×
5025
    info->addMember( "rev", new BLong( version.rev ) );
×
5026
    info->addMember( "patch", new BLong( version.patch ) );
×
5027
    return info.release();
×
5028
  }
×
5029
  break;
5030
  case MBR_CLIENTINFO:
×
5031
    return getclientinfo();
×
5032
    break;
5033
  case MBR_CLIENTTYPE:
×
5034
    return new BLong( ClientType );
×
5035
    break;
5036
  case MBR_UO_EXPANSION_CLIENT:
×
5037
    return new BLong( UOExpansionFlagClient );
×
5038
    break;
5039
  case MBR_LAST_ACTIVITY_AT:
×
5040
    return new BLong( static_cast<s32>( last_activity_at() ) );
×
5041
    break;
5042
  case MBR_LAST_PACKET_AT:
×
5043
    return new BLong( static_cast<s32>( last_packet_at() ) );
×
5044
    break;
5045
  case MBR_PORT:
×
5046
    return new BLong( listen_port );
×
5047
    break;
5048
  case MBR_DISABLE_INACTIVITY_TIMEOUT:
×
5049
    return new BLong( disable_inactivity_timeout() );
×
5050
    break;
5051
  case MBR_VISUAL_RANGE:
×
5052
    return new BLong( update_range() );
×
5053
    break;
5054
  }
5055

5056
  return nullptr;
1✔
5057
}
5058

5059
}  // namespace Network
5060

5061
namespace Core
5062
{
5063
bool UObject::script_isa( unsigned isatype ) const
6,240✔
5064
{
5065
  return ( isatype == POLCLASS_OBJECT );
6,240✔
5066
}
5067

5068
bool ULockable::script_isa( unsigned isatype ) const
123✔
5069
{
5070
  return ( isatype == POLCLASS_LOCKABLE ) || base::script_isa( isatype );
123✔
5071
}
5072

5073
bool UContainer::script_isa( unsigned isatype ) const
171✔
5074
{
5075
  return ( isatype == POLCLASS_CONTAINER ) || base::script_isa( isatype );
171✔
5076
}
5077

5078
bool UCorpse::script_isa( unsigned isatype ) const
71✔
5079
{
5080
  return ( isatype == POLCLASS_CORPSE ) || base::script_isa( isatype );
71✔
5081
}
5082

5083
bool UDoor::script_isa( unsigned isatype ) const
×
5084
{
5085
  return ( isatype == POLCLASS_DOOR ) || base::script_isa( isatype );
×
5086
}
5087

5088
bool Spellbook::script_isa( unsigned isatype ) const
×
5089
{
5090
  return ( isatype == POLCLASS_SPELLBOOK ) || base::script_isa( isatype );
×
5091
}
5092

5093
bool Map::script_isa( unsigned isatype ) const
×
5094
{
5095
  return ( isatype == POLCLASS_MAP ) || base::script_isa( isatype );
×
5096
}
5097
}  // namespace Core
5098

5099
namespace Items
5100
{
5101
bool Item::script_isa( unsigned isatype ) const
6,225✔
5102
{
5103
  return ( isatype == Core::POLCLASS_ITEM ) || base::script_isa( isatype );
6,225✔
5104
}
5105

5106
bool Equipment::script_isa( unsigned isatype ) const
×
5107
{
5108
  return ( isatype == Core::POLCLASS_EQUIPMENT ) || base::script_isa( isatype );
×
5109
}
5110

5111
bool UArmor::script_isa( unsigned isatype ) const
×
5112
{
5113
  return ( isatype == Core::POLCLASS_ARMOR ) || base::script_isa( isatype );
×
5114
}
5115

5116
bool UWeapon::script_isa( unsigned isatype ) const
×
5117
{
5118
  return ( isatype == Core::POLCLASS_WEAPON ) || base::script_isa( isatype );
×
5119
}
5120
}  // namespace Items
5121

5122
namespace Mobile
5123
{
5124
bool Character::script_isa( unsigned isatype ) const
140✔
5125
{
5126
  return ( isatype == Core::POLCLASS_MOBILE ) || base::script_isa( isatype );
140✔
5127
}
5128

5129
bool NPC::script_isa( unsigned isatype ) const
56✔
5130
{
5131
  return ( isatype == Core::POLCLASS_NPC ) || base::script_isa( isatype );
56✔
5132
}
5133
}  // namespace Mobile
5134
namespace Multi
5135
{
5136
bool UMulti::script_isa( unsigned isatype ) const
3✔
5137
{
5138
  return ( isatype == Core::POLCLASS_MULTI ) || base::script_isa( isatype );
3✔
5139
}
5140

5141
bool UMulti::setgraphic( u16 /* newobjtype */ )
×
5142
{
5143
  return false;
×
5144
}
5145

5146
bool UBoat::script_isa( unsigned isatype ) const
9✔
5147
{
5148
  return ( isatype == Core::POLCLASS_BOAT ) || base::script_isa( isatype );
9✔
5149
}
5150

5151
bool UHouse::script_isa( unsigned isatype ) const
×
5152
{
5153
  return ( isatype == Core::POLCLASS_HOUSE ) || base::script_isa( isatype );
×
5154
}
5155
}  // namespace Multi
5156
}  // namespace Pol
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