Pol  Revision:cb584c9
uoscrobj.cpp
Go to the documentation of this file.
1 
52 #include "uoscrobj.h"
53 
54 #include <string>
55 
56 #include "../bscript/berror.h"
57 #include "../bscript/dict.h"
58 #include "../bscript/execmodl.h"
59 #include "../bscript/executor.h"
60 #include "../bscript/impstr.h"
61 #include "../bscript/objmembers.h"
62 #include "../bscript/objmethods.h"
63 #include "../clib/stlutil.h"
64 #include "accounts/account.h"
65 #include "accounts/acscrobj.h"
66 #include "cmdlevel.h"
67 #include "containr.h"
68 #include "door.h"
69 #include "dynproperties.h"
70 #include "equipdsc.h"
71 #include "exscrobj.h"
72 #include "fnsearch.h"
73 #include "globals/network.h"
74 #include "globals/uvars.h"
75 #include "item/armor.h"
76 #include "item/equipmnt.h"
77 #include "item/item.h"
78 #include "item/itemdesc.h"
79 #include "item/weapon.h"
80 #include "lockable.h"
81 #include "mobile/charactr.h"
82 #include "mobile/corpse.h"
83 #include "mobile/npc.h"
84 #include "mobile/ufacing.h"
85 #include "module/guildmod.h"
86 #include "module/partymod.h"
87 #include "module/uomod.h"
88 #include "multi/boat.h"
89 #include "multi/boatcomp.h"
90 #include "multi/house.h"
91 #include "multi/multi.h"
92 #include "network/client.h"
93 #include "network/packethelper.h"
94 #include "network/packets.h"
95 #include "npctmpl.h"
96 #include "pktdef.h"
97 #include "polclass.h"
98 #include "polclock.h"
99 #include "poltype.h"
100 #include "proplist.h"
101 #include "realms.h"
102 #include "realms/realm.h"
103 #include "spelbook.h"
104 #include "statmsg.h"
105 #include "syshookscript.h"
106 #include "tooltips.h"
107 #include "uconst.h"
108 #include "ufunc.h"
109 #include "umap.h"
110 #include "unicode.h"
111 #include "uobject.h"
112 #include "uoclient.h"
113 #include "uoexec.h"
114 #include "uoexhelp.h"
115 #include "uworld.h"
116 
117 namespace Pol
118 {
119 namespace Module
120 {
121 using namespace Bscript;
122 
131 
132 const char* ECharacterRefObjImp::typeOf() const
133 {
134  return "MobileRef";
135 }
137 {
138  return OTMobileRef;
139 }
140 
142 {
143  return new ECharacterRefObjImp( obj_.get() );
144 }
145 
147 {
148  BObjectImp* result = obj_->get_script_member_id( id );
149  if ( result != nullptr )
150  return BObjectRef( result );
151  else
152  return BObjectRef( UninitObject::create() );
153 }
154 
156 {
157  ObjMember* objmember = getKnownObjMember( membername );
158  if ( objmember != nullptr )
159  return this->get_member_id( objmember->id );
160  else
161  return BObjectRef( UninitObject::create() );
162 }
163 
164 BObjectRef ECharacterRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
165 {
166  BObjectImp* result = nullptr;
167  if ( value->isa( BObjectImp::OTLong ) )
168  {
169  BLong* lng = static_cast<BLong*>( value );
170  result = obj_->set_script_member_id( id, lng->value() );
171  }
172  else if ( value->isa( BObjectImp::OTString ) )
173  {
174  String* str = static_cast<String*>( value );
175  result = obj_->set_script_member_id( id, str->value() );
176  }
177  else if ( value->isa( BObjectImp::OTDouble ) )
178  {
179  Double* dbl = static_cast<Double*>( value );
180  result = obj_->set_script_member_id_double( id, dbl->value() );
181  }
182  if ( result != nullptr )
183  return BObjectRef( result );
184  else
185  return BObjectRef( UninitObject::create() );
186 }
187 
188 BObjectRef ECharacterRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
189 {
190  ObjMember* objmember = getKnownObjMember( membername );
191  if ( objmember != nullptr )
192  return this->set_member_id( objmember->id, value, copy );
193  else
194  return BObjectRef( UninitObject::create() );
195 }
196 
197 BObjectImp* ECharacterRefObjImp::call_method_id( const int id, Executor& ex, bool forcebuiltin )
198 {
199  // MethodScript for npcs in npc->template_ (npctmpl.h) (aka templatebased)
200  // for chars in uoclient_general (uoclient.h) (aka one global definition)
201  if ( !obj_->orphan() )
202  {
203  ObjMethod* mth = getObjMethod( id );
204  if ( mth->overridden && !forcebuiltin )
205  {
206  BObjectImp* imp = obj_->custom_script_method( mth->code, ex );
207  if ( imp )
208  return imp;
209  }
210  BObjectImp* imp = obj_->script_method_id( id, ex );
211  if ( imp != nullptr )
212  return imp;
213  else
214  return base::call_method_id( id, ex );
215  }
216  else
217  return new BError( "That object no longer exists" );
218 }
219 
220 BObjectImp* ECharacterRefObjImp::call_method( const char* methodname, Executor& ex )
221 {
222  // MethodScript for npcs in npc->template_ (npctmpl.h) (aka templatebased)
223  // for chars in uoclient_general (uoclient.h) (aka one global definition)
224  bool forcebuiltin;
225  if ( methodname[0] == '_' )
226  {
227  ++methodname;
228  forcebuiltin = true;
229  }
230  else
231  forcebuiltin = false;
232  ObjMethod* objmethod = getKnownObjMethod( methodname );
233  if ( objmethod != nullptr )
234  return this->call_method_id( objmethod->id, ex, forcebuiltin );
235  else
236  {
237  BObjectImp* imp = obj_->custom_script_method( methodname, ex );
238  if ( imp )
239  return imp;
240  else
241  return base::call_method( methodname, ex );
242  }
243 }
244 
246 {
247  return ( !obj_->orphan() && obj_->logged_in() );
248 }
249 
250 bool ECharacterRefObjImp::operator==( const BObjectImp& objimp ) const
251 {
252  if ( objimp.isa( BObjectImp::OTApplicObj ) )
253  {
254  const BApplicObjBase* aob =
255  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
256 
257  if ( aob->object_type() == &echaracterrefobjimp_type )
258  {
259  const ECharacterRefObjImp* chrref_imp =
260  Clib::explicit_cast<const ECharacterRefObjImp*, const BApplicObjBase*>( aob );
261 
262  return ( chrref_imp->obj_->serial == obj_->serial );
263  }
264  else
265  return false;
266  }
267  else if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
268  return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
269  else
270  return false;
271 }
272 
273 bool ECharacterRefObjImp::operator<( const BObjectImp& objimp ) const
274 {
275  if ( objimp.isa( BObjectImp::OTApplicObj ) )
276  {
277  const BApplicObjBase* aob =
278  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
279 
280  if ( aob->object_type() == &echaracterrefobjimp_type )
281  {
282  const ECharacterRefObjImp* chrref_imp =
283  Clib::explicit_cast<const ECharacterRefObjImp*, const BApplicObjBase*>( aob );
284 
285  return ( chrref_imp->obj_->serial < obj_->serial );
286  }
287  else if ( aob->object_type() == &eitemrefobjimp_type )
288  return true;
289  else
290  return false;
291  }
292  return base::operator<( objimp );
293 }
294 
296 {
297  return "OfflineMobileRef";
298 }
300 {
301  return OTOfflineMobileRef;
302 }
303 
305 {
306  return new EOfflineCharacterRefObjImp( obj_.get() );
307 }
308 
310 {
311  return ( !obj_->orphan() );
312 }
313 
314 const char* EItemRefObjImp::typeOf() const
315 {
316  return "ItemRef";
317 }
319 {
320  return OTItemRef;
321 }
322 
324 {
325  return new EItemRefObjImp( obj_.get() );
326 }
327 
329 {
330  BObjectImp* result = obj_->get_script_member_id( id );
331  if ( result != nullptr )
332  return BObjectRef( result );
333  else
334  return BObjectRef( UninitObject::create() );
335 }
336 
337 BObjectRef EItemRefObjImp::get_member( const char* membername )
338 {
339  ObjMember* objmember = getKnownObjMember( membername );
340  if ( objmember != nullptr )
341  return this->get_member_id( objmember->id );
342  else
343  return BObjectRef( UninitObject::create() );
344 }
345 
346 BObjectRef EItemRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
347 {
348  BObjectImp* result = nullptr;
349  if ( value->isa( BObjectImp::OTLong ) )
350  {
351  BLong* lng = static_cast<BLong*>( value );
352  result = obj_->set_script_member_id( id, lng->value() );
353  }
354  else if ( value->isa( BObjectImp::OTString ) )
355  {
356  String* str = static_cast<String*>( value );
357  result = obj_->set_script_member_id( id, str->value() );
358  }
359  else if ( value->isa( BObjectImp::OTDouble ) )
360  {
361  Double* dbl = static_cast<Double*>( value );
362  result = obj_->set_script_member_id_double( id, dbl->value() );
363  }
364  if ( result != nullptr )
365  return BObjectRef( result );
366  else
367  return BObjectRef( UninitObject::create() );
368 }
369 
370 BObjectRef EItemRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
371 {
372  ObjMember* objmember = getKnownObjMember( membername );
373  if ( objmember != nullptr )
374  return this->set_member_id( objmember->id, value, copy );
375  else
376  return BObjectRef( UninitObject::create() );
377 }
378 
379 BObjectImp* EItemRefObjImp::call_method_id( const int id, Executor& ex, bool forcebuiltin )
380 {
381  if ( !obj_->orphan() )
382  {
383  ObjMethod* mth = getObjMethod( id );
384  if ( mth->overridden && !forcebuiltin )
385  {
386  BObjectImp* imp = obj_->custom_script_method( mth->code, ex );
387  if ( imp )
388  return imp;
389  }
390  BObjectImp* imp = obj_->script_method_id( id, ex );
391  if ( imp != nullptr )
392  return imp;
393  else
394  {
395  return base::call_method_id( id, ex );
396  }
397  }
398  else
399  {
400  return new BError( "That object no longer exists" );
401  }
402 }
403 
404 BObjectImp* EItemRefObjImp::call_method( const char* methodname, Executor& ex )
405 {
406  bool forcebuiltin;
407  if ( methodname[0] == '_' )
408  {
409  ++methodname;
410  forcebuiltin = true;
411  }
412  else
413  forcebuiltin = false;
414 
415  ObjMethod* objmethod = getKnownObjMethod( methodname );
416  if ( objmethod != nullptr )
417  return this->call_method_id( objmethod->id, ex, forcebuiltin );
418  else
419  {
420  Items::Item* item = obj_.get();
421  BObjectImp* imp = item->custom_script_method( methodname, ex );
422  if ( imp )
423  return imp;
424  else
425  return base::call_method( methodname, ex );
426  }
427 }
428 
430 {
431  return ( !obj_->orphan() );
432 }
433 
434 bool EItemRefObjImp::operator==( const BObjectImp& objimp ) const
435 {
436  if ( objimp.isa( BObjectImp::OTApplicObj ) )
437  {
438  const BApplicObjBase* aob =
439  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
440 
441  if ( aob->object_type() == &eitemrefobjimp_type )
442  {
443  const EItemRefObjImp* itemref_imp =
444  Clib::explicit_cast<const EItemRefObjImp*, const BApplicObjBase*>( aob );
445 
446  return ( itemref_imp->obj_->serial == obj_->serial );
447  }
448  else
449  return false;
450  }
451  else if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
452  return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
453  else
454  return false;
455 }
456 
457 bool EItemRefObjImp::operator<( const BObjectImp& objimp ) const
458 {
459  if ( objimp.isa( BObjectImp::OTApplicObj ) )
460  {
461  const BApplicObjBase* aob =
462  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
463 
464  if ( aob->object_type() == &eitemrefobjimp_type )
465  {
466  const EItemRefObjImp* itemref_imp =
467  Clib::explicit_cast<const EItemRefObjImp*, const BApplicObjBase*>( aob );
468 
469  return ( itemref_imp->obj_->serial < obj_->serial );
470  }
471  else
472  return ( &eitemrefobjimp_type < aob->object_type() );
473  }
474 
475  return base::operator<( objimp );
476 }
477 
478 const char* EUBoatRefObjImp::typeOf() const
479 {
480  return "BoatRef";
481 }
483 {
484  return OTBoatRef;
485 }
486 
488 {
489  return new EUBoatRefObjImp( obj_.get() );
490 }
491 
493 {
494  BObjectImp* result = obj_->get_script_member_id( id );
495  if ( result != nullptr )
496  return BObjectRef( result );
497  else
498  return BObjectRef( UninitObject::create() );
499 }
500 
501 BObjectRef EUBoatRefObjImp::get_member( const char* membername )
502 {
503  ObjMember* objmember = getKnownObjMember( membername );
504  if ( objmember != nullptr )
505  return this->get_member_id( objmember->id );
506  else
507  return BObjectRef( UninitObject::create() );
508 }
509 
510 BObjectRef EUBoatRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
511 {
512  BObjectImp* result = nullptr;
513  if ( value->isa( BObjectImp::OTLong ) )
514  {
515  BLong* lng = static_cast<BLong*>( value );
516  result = obj_->set_script_member_id( id, lng->value() );
517  }
518  else if ( value->isa( BObjectImp::OTString ) )
519  {
520  String* str = static_cast<String*>( value );
521  result = obj_->set_script_member_id( id, str->value() );
522  }
523  else if ( value->isa( BObjectImp::OTDouble ) )
524  {
525  Double* dbl = static_cast<Double*>( value );
526  result = obj_->set_script_member_id_double( id, dbl->value() );
527  }
528  if ( result != nullptr )
529  return BObjectRef( result );
530  else
531  return BObjectRef( UninitObject::create() );
532 }
533 
534 BObjectRef EUBoatRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
535 {
536  ObjMember* objmember = getKnownObjMember( membername );
537  if ( objmember != nullptr )
538  return this->set_member_id( objmember->id, value, copy );
539  else
540  return BObjectRef( UninitObject::create() );
541 }
542 
543 BObjectImp* EUBoatRefObjImp::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
544 {
545  if ( !obj_->orphan() )
546  {
547  BObjectImp* imp = obj_->script_method_id( id, ex );
548  if ( imp != nullptr )
549  return imp;
550  else
551  return base::call_method_id( id, ex );
552  }
553  else
554  return new BError( "That object no longer exists" );
555 }
556 
557 BObjectImp* EUBoatRefObjImp::call_method( const char* methodname, Executor& ex )
558 {
559  ObjMethod* objmethod = getKnownObjMethod( methodname );
560  if ( objmethod != nullptr )
561  return this->call_method_id( objmethod->id, ex );
562  else
563  return base::call_method( methodname, ex );
564 }
565 
567 {
568  return ( !obj_->orphan() );
569 }
570 
571 bool EUBoatRefObjImp::operator==( const BObjectImp& objimp ) const
572 {
573  if ( objimp.isa( BObjectImp::OTApplicObj ) )
574  {
575  const BApplicObjBase* aob =
576  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
577 
578  if ( aob->object_type() == &euboatrefobjimp_type )
579  {
580  const EUBoatRefObjImp* boatref_imp =
581  Clib::explicit_cast<const EUBoatRefObjImp*, const BApplicObjBase*>( aob );
582 
583  return ( boatref_imp->obj_->serial == obj_->serial );
584  }
585  else
586  return false;
587  }
588  else if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
589  return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
590  else
591  return false;
592 }
593 
594 BObjectImp* EMultiRefObjImp::call_method( const char* methodname, Executor& ex )
595 {
596  bool forcebuiltin;
597  if ( methodname[0] == '_' )
598  {
599  ++methodname;
600  forcebuiltin = true;
601  }
602  else
603  forcebuiltin = false;
604 
605  ObjMethod* objmethod = getKnownObjMethod( methodname );
606  if ( objmethod != nullptr )
607  return this->call_method_id( objmethod->id, ex, forcebuiltin );
608  else
609  {
610  Multi::UMulti* multi = obj_.get();
611  BObjectImp* imp = multi->custom_script_method( methodname, ex );
612  if ( imp )
613  return imp;
614  else
615  return base::call_method( methodname, ex );
616  }
617 }
618 
619 BObjectImp* EMultiRefObjImp::call_method_id( const int id, Executor& ex, bool forcebuiltin )
620 {
621  Multi::UMulti* multi = obj_.get();
622  if ( !multi->orphan() )
623  {
624  ObjMethod* mth = getObjMethod( id );
625  if ( mth->overridden && !forcebuiltin )
626  {
627  BObjectImp* imp = multi->custom_script_method( mth->code, ex );
628  if ( imp )
629  return imp;
630  }
631 
632  BObjectImp* imp = multi->script_method_id( id, ex );
633  if ( imp != nullptr )
634  return imp;
635  else
636  return base::call_method_id( id, ex, forcebuiltin );
637  }
638  else
639  {
640  return new BError( "That object no longer exists" );
641  }
642 }
643 
644 const char* EMultiRefObjImp::typeOf() const
645 {
646  return "MultiRef";
647 }
649 {
650  return OTMultiRef;
651 }
652 
654 {
655  return new EMultiRefObjImp( obj_.get() );
656 }
657 
659 {
660  BObjectImp* result = obj_->get_script_member_id( id );
661  if ( result != nullptr )
662  return BObjectRef( result );
663  else
664  return BObjectRef( UninitObject::create() );
665 }
666 
667 BObjectRef EMultiRefObjImp::get_member( const char* membername )
668 {
669  ObjMember* objmember = getKnownObjMember( membername );
670  if ( objmember != nullptr )
671  return this->get_member_id( objmember->id );
672  else
673  return BObjectRef( UninitObject::create() );
674 }
675 
676 BObjectRef EMultiRefObjImp::set_member_id( const int id, BObjectImp* value, bool /*copy*/ )
677 {
678  BObjectImp* result = nullptr;
679  if ( value->isa( BObjectImp::OTLong ) )
680  {
681  BLong* lng = static_cast<BLong*>( value );
682  result = obj_->set_script_member_id( id, lng->value() );
683  }
684  else if ( value->isa( BObjectImp::OTString ) )
685  {
686  String* str = static_cast<String*>( value );
687  result = obj_->set_script_member_id( id, str->value() );
688  }
689  else if ( value->isa( BObjectImp::OTDouble ) )
690  {
691  Double* dbl = static_cast<Double*>( value );
692  result = obj_->set_script_member_id_double( id, dbl->value() );
693  }
694  if ( result != nullptr )
695  return BObjectRef( result );
696  else
697  return BObjectRef( UninitObject::create() );
698 }
699 BObjectRef EMultiRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
700 {
701  ObjMember* objmember = getKnownObjMember( membername );
702  if ( objmember != nullptr )
703  return this->set_member_id( objmember->id, value, copy );
704  else
705  return BObjectRef( UninitObject::create() );
706 }
707 
709 {
710  return ( !obj_->orphan() );
711 }
712 
713 bool EMultiRefObjImp::operator==( const BObjectImp& objimp ) const
714 {
715  if ( objimp.isa( BObjectImp::OTApplicObj ) )
716  {
717  const BApplicObjBase* aob =
718  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
719 
720  if ( aob->object_type() == &emultirefobjimp_type )
721  {
722  const EMultiRefObjImp* multiref_imp =
723  Clib::explicit_cast<const EMultiRefObjImp*, const BApplicObjBase*>( aob );
724 
725  return ( multiref_imp->obj_->serial == obj_->serial );
726  }
727  else
728  return false;
729  }
730  else if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
731  return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
732  else
733  return false;
734 }
735 } // namespace Module
736 
737 namespace Core
738 {
739 using namespace Bscript;
740 
742 {
743  if ( orphan() )
744  return new UninitObject;
745  switch ( id )
746  {
747  case MBR_X:
748  return new BLong( x );
749  break;
750  case MBR_Y:
751  return new BLong( y );
752  break;
753  case MBR_Z:
754  return new BLong( z );
755  break;
756  case MBR_NAME:
757  return new String( name() );
758  break;
759  case MBR_OBJTYPE:
760  return new BLong( objtype_ );
761  break;
762  case MBR_GRAPHIC:
763  return new BLong( graphic );
764  break;
765  case MBR_SERIAL:
766  return new BLong( serial );
767  break;
768  case MBR_COLOR:
769  return new BLong( color );
770  break;
771  case MBR_HEIGHT:
772  return new BLong( height );
773  break;
774  case MBR_FACING:
775  return new BLong( facing );
776  break;
777  case MBR_DIRTY:
778  return new BLong( dirty() ? 1 : 0 );
779  break;
780  case MBR_WEIGHT:
781  return new BLong( weight() );
782  break;
783  case MBR_MULTI:
784  if ( realm != nullptr )
785  {
786  Multi::UMulti* multi;
787  if ( nullptr != ( multi = realm->find_supporting_multi( x, y, z ) ) )
788  return multi->make_ref();
789  else
790  return new BLong( 0 );
791  }
792  else
793  return new BLong( 0 );
794  break;
795  case MBR_REALM:
796  if ( realm != nullptr )
797  return new String( realm->name() );
798  else
799  return new BError( "object does not belong to a realm." );
800  break;
801  case MBR_SPECIFIC_NAME:
802  return new BLong( specific_name() );
803  default:
804  return nullptr;
805  }
806 }
807 
808 BObjectImp* UObject::get_script_member( const char* membername ) const
809 {
810  ObjMember* objmember = getKnownObjMember( membername );
811  if ( objmember != nullptr )
812  return this->get_script_member_id( objmember->id );
813  else
814  return nullptr;
815 }
816 
817 BObjectImp* UObject::set_script_member_id( const int id, const std::string& value )
818 {
819  if ( orphan() )
820  return new UninitObject;
821 
822  set_dirty();
823  switch ( id )
824  {
825  case MBR_NAME:
826  if ( ismobile() && ( value.empty() || isspace( value[0] ) ) )
827  return new BError( "mobile.name must not be empty, and must not begin with a space" );
828  setname( value );
829  return new String( name() );
830  break;
831  default:
832  return nullptr;
833  }
834 }
835 
836 BObjectImp* UObject::set_script_member( const char* membername, const std::string& value )
837 {
838  ObjMember* objmember = getKnownObjMember( membername );
839  if ( objmember != nullptr )
840  return this->set_script_member_id( objmember->id, value );
841  else
842  return nullptr;
843 }
844 
845 BObjectImp* UObject::set_script_member_id( const int id, int value )
846 {
847  if ( orphan() )
848  return new UninitObject;
849 
850  set_dirty();
851  switch ( id )
852  {
853  case MBR_GRAPHIC:
854  setgraphic( static_cast<unsigned short>( value ) );
855  return new BLong( graphic );
856  case MBR_COLOR:
857  {
858  bool res = setcolor( static_cast<unsigned short>( value ) );
859  if ( !res ) // TODO log?
860  return new BError( "Invalid color value " + Clib::hexint( value ) );
861  else
862  return new BLong( color );
863  }
864  default:
865  return nullptr;
866  }
867 }
868 
869 BObjectImp* UObject::set_script_member( const char* membername, int value )
870 {
871  ObjMember* objmember = getKnownObjMember( membername );
872  if ( objmember != nullptr )
873  return this->set_script_member_id( objmember->id, value );
874  else
875  return nullptr;
876 }
877 
878 BObjectImp* UObject::set_script_member_id_double( const int /*id*/, double /*value*/ )
879 {
880  set_dirty();
881  return nullptr;
882 }
883 
884 BObjectImp* UObject::set_script_member_double( const char* membername, double value )
885 {
886  ObjMember* objmember = getKnownObjMember( membername );
887  if ( objmember != nullptr )
888  return this->set_script_member_id_double( objmember->id, value );
889  else
890  return nullptr;
891 }
892 } // namespace Core
893 
894 namespace Items
895 {
896 using namespace Bscript;
897 
899 {
900  BObjectImp* imp = base::get_script_member_id( id );
901  if ( imp != nullptr )
902  return imp;
903 
904  switch ( id )
905  {
906  case MBR_AMOUNT:
907  return new BLong( amount_ );
908  break;
909  case MBR_LAYER:
910  return new BLong( layer );
911  break;
912  case MBR_TILE_LAYER:
913  return new BLong( tile_layer );
914  break;
915  case MBR_CONTAINER:
916  if ( container != nullptr )
917  return container->make_ref();
918  else
919  return new BLong( 0 );
920  break;
921  case MBR_USESCRIPT:
922  return new String( on_use_script_ );
923  break;
924  case MBR_EQUIPSCRIPT:
925  return new String( equip_script_ );
926  break;
927  case MBR_UNEQUIPSCRIPT:
928  return new String( unequip_script_ );
929  break;
930  case MBR_DESC:
931  return new String( description() );
932  break;
933  case MBR_MOVABLE:
934  return new BLong( movable() ? 1 : 0 );
935  break;
936  case MBR_INVISIBLE:
937  return new BLong( invisible() ? 1 : 0 );
938  break;
939  case MBR_DECAYAT:
940  return new BLong( decayat_gameclock_ );
941  break;
942  case MBR_SELLPRICE:
943  return new BLong( sellprice() );
944  break;
945  case MBR_BUYPRICE:
946  return new BLong( buyprice() );
947  break;
948  case MBR_NEWBIE:
949  return new BLong( newbie() ? 1 : 0 );
950  break;
951  case MBR_INSURED:
952  return new BLong( insured() ? 1 : 0 );
953  break;
954  case MBR_ITEM_COUNT:
955  return new BLong( item_count() );
956  break;
957  case MBR_STACKABLE:
958  return new BLong( stackable() ? 1 : 0 );
959  break;
960  case MBR_SAVEONEXIT:
961  return new BLong( saveonexit() );
962  break;
963  case MBR_FIRE_RESIST:
964  return new BLong( fire_resist().sum() );
965  break;
966  case MBR_COLD_RESIST:
967  return new BLong( cold_resist().sum() );
968  break;
969  case MBR_ENERGY_RESIST:
970  return new BLong( energy_resist().sum() );
971  break;
972  case MBR_POISON_RESIST:
973  return new BLong( poison_resist().sum() );
974  break;
975  case MBR_PHYSICAL_RESIST:
976  return new BLong( physical_resist().sum() );
977  break;
978  case MBR_FIRE_RESIST_MOD:
979  return new BLong( fire_resist().mod );
980  break;
981  case MBR_COLD_RESIST_MOD:
982  return new BLong( cold_resist().mod );
983  break;
985  return new BLong( energy_resist().mod );
986  break;
988  return new BLong( poison_resist().mod );
989  break;
991  return new BLong( physical_resist().mod );
992  break;
993  case MBR_FIRE_DAMAGE:
994  return new BLong( fire_damage().sum() );
995  break;
996  case MBR_COLD_DAMAGE:
997  return new BLong( cold_damage().sum() );
998  break;
999  case MBR_ENERGY_DAMAGE:
1000  return new BLong( energy_damage().sum() );
1001  break;
1002  case MBR_POISON_DAMAGE:
1003  return new BLong( poison_damage().sum() );
1004  break;
1005  case MBR_PHYSICAL_DAMAGE:
1006  return new BLong( physical_damage().sum() );
1007  break;
1008  case MBR_FIRE_DAMAGE_MOD:
1009  return new BLong( fire_damage().mod );
1010  break;
1011  case MBR_COLD_DAMAGE_MOD:
1012  return new BLong( cold_damage().mod );
1013  break;
1014  case MBR_ENERGY_DAMAGE_MOD:
1015  return new BLong( energy_damage().mod );
1016  break;
1017  case MBR_POISON_DAMAGE_MOD:
1018  return new BLong( poison_damage().mod );
1019  break;
1021  return new BLong( physical_damage().mod );
1022  break;
1023  case MBR_GETGOTTENBY:
1024  if ( has_gotten_by() )
1025  return new Module::ECharacterRefObjImp( gotten_by() );
1026  else
1027  return new BError( "Gotten By nullptr" );
1028  break;
1029  case MBR_PROCESS:
1030  {
1031  Module::UOExecutorModule* proc = process();
1032  if ( proc )
1033  {
1034  Core::UOExecutor* executor = static_cast<Core::UOExecutor*>( &proc->exec );
1035  return new Core::ScriptExObjImp( executor );
1036  }
1037  else
1038  return new BError( "No script running" );
1039  break;
1040  }
1041  case MBR_DOUBLECLICKRANGE:
1042  {
1043  const ItemDesc& itemdesc = this->itemdesc();
1044  return new BLong( itemdesc.doubleclick_range );
1045  break;
1046  }
1047  case MBR_QUALITY:
1048  return new Double( getQuality() );
1049  break;
1050  case MBR_HP:
1051  return new BLong( hp_ );
1052  break;
1053  case MBR_MAXHP_MOD:
1054  return new BLong( maxhp_mod() );
1055  break;
1056  case MBR_MAXHP:
1057  return new BLong( static_cast<int>( maxhp() * getQuality() ) );
1058  break;
1059  case MBR_NAME_SUFFIX:
1060  return new String( name_suffix() );
1061  break;
1062  case MBR_HOUSE:
1063  if ( house() != nullptr )
1064  return house()->make_ref();
1065  return new BError( "This is a not component of any house" );
1066  break;
1067  case MBR_NO_DROP:
1068  return new BLong( no_drop() );
1069  default:
1070  return nullptr;
1071  }
1072 }
1073 
1074 BObjectImp* Item::get_script_member( const char* membername ) const
1075 {
1076  ObjMember* objmember = getKnownObjMember( membername );
1077  if ( objmember != nullptr )
1078  return this->get_script_member_id( objmember->id );
1079  else
1080  return nullptr;
1081 }
1082 
1083 BObjectImp* Item::set_script_member_id( const int id, const std::string& value )
1084 {
1085  BObjectImp* imp = base::set_script_member_id( id, value );
1086  if ( imp != nullptr )
1087  return imp;
1088 
1089  switch ( id )
1090  {
1091  case MBR_USESCRIPT:
1092  on_use_script_ = value;
1093  return new String( value );
1094  case MBR_EQUIPSCRIPT:
1095  equip_script_ = value;
1096  return new String( value );
1097  case MBR_UNEQUIPSCRIPT:
1098  unequip_script_ = value;
1099  return new String( value );
1100  case MBR_NAME_SUFFIX:
1101  set_dirty();
1102  increv();
1104  name_suffix( value );
1105  return new String( value );
1106 
1107  default:
1108  return nullptr;
1109  }
1110 }
1111 
1112 BObjectImp* Item::set_script_member( const char* membername, const std::string& value )
1113 {
1114  ObjMember* objmember = getKnownObjMember( membername );
1115  if ( objmember != nullptr )
1116  return this->set_script_member_id( objmember->id, value );
1117  else
1118  return nullptr;
1119 }
1120 
1121 BObjectImp* Item::set_script_member_id( const int id, int value )
1122 {
1123  BObjectImp* imp = base::set_script_member_id( id, value );
1124  if ( imp != nullptr )
1125  return imp;
1126 
1127  switch ( id )
1128  {
1129  case MBR_MOVABLE:
1130  restart_decay_timer();
1131  movable( value ? true : false );
1132  increv();
1133  return new BLong( movable() );
1134  case MBR_INVISIBLE:
1135  restart_decay_timer();
1136  invisible( value ? true : false );
1137  increv();
1138  return new BLong( invisible() );
1139  case MBR_DECAYAT:
1140  decayat_gameclock_ = value;
1141  return new BLong( decayat_gameclock_ );
1142  case MBR_SELLPRICE:
1143  sellprice( value );
1144  return new BLong( value );
1145  case MBR_BUYPRICE:
1146  buyprice( value );
1147  return new BLong( value );
1148  case MBR_NEWBIE:
1149  restart_decay_timer();
1150  newbie( value ? true : false );
1151  increv();
1152  return new BLong( newbie() );
1153  case MBR_INSURED:
1154  restart_decay_timer();
1155  insured( value ? true : false );
1156  increv();
1157  return new BLong( insured() );
1158  case MBR_FACING:
1159  setfacing( (u8)value );
1160  return new BLong( facing );
1161  case MBR_SAVEONEXIT:
1162  saveonexit( value ? true : false );
1163  return new BLong( saveonexit() );
1164  case MBR_FIRE_RESIST_MOD:
1165  fire_resist( fire_resist().setAsMod( static_cast<short>( value ) ) );
1166  if ( container != nullptr )
1167  {
1168  if ( Core::IsCharacter( container->serial ) )
1169  {
1170  Mobile::Character* chr = chr_from_wornitems( container );
1171  if ( chr != nullptr )
1172  chr->refresh_ar();
1173  }
1174  }
1175  return new BLong( fire_resist().mod );
1176  break;
1177  case MBR_COLD_RESIST_MOD:
1178  cold_resist( cold_resist().setAsMod( static_cast<short>( value ) ) );
1179  if ( container != nullptr )
1180  {
1181  if ( Core::IsCharacter( container->serial ) )
1182  {
1183  Mobile::Character* chr = chr_from_wornitems( container );
1184  if ( chr != nullptr )
1185  chr->refresh_ar();
1186  }
1187  }
1188  return new BLong( cold_resist().mod );
1189  break;
1190  case MBR_ENERGY_RESIST_MOD:
1191  energy_resist( energy_resist().setAsMod( static_cast<short>( value ) ) );
1192  if ( container != nullptr )
1193  {
1194  if ( Core::IsCharacter( container->serial ) )
1195  {
1196  Mobile::Character* chr = chr_from_wornitems( container );
1197  if ( chr != nullptr )
1198  chr->refresh_ar();
1199  }
1200  }
1201  return new BLong( energy_resist().mod );
1202  break;
1203  case MBR_POISON_RESIST_MOD:
1204  poison_resist( poison_resist().setAsMod( static_cast<short>( value ) ) );
1205  if ( container != nullptr )
1206  {
1207  if ( Core::IsCharacter( container->serial ) )
1208  {
1209  Mobile::Character* chr = chr_from_wornitems( container );
1210  if ( chr != nullptr )
1211  chr->refresh_ar();
1212  }
1213  }
1214  return new BLong( poison_resist().mod );
1215  break;
1217  physical_resist( physical_resist().setAsMod( static_cast<short>( value ) ) );
1218  if ( container != nullptr )
1219  {
1220  if ( Core::IsCharacter( container->serial ) )
1221  {
1222  Mobile::Character* chr = chr_from_wornitems( container );
1223  if ( chr != nullptr )
1224  chr->refresh_ar();
1225  }
1226  }
1227  return new BLong( physical_resist().mod );
1228  break;
1229  case MBR_FIRE_DAMAGE_MOD:
1230  fire_damage( fire_damage().setAsMod( static_cast<short>( value ) ) );
1231  return new BLong( static_cast<short>( value ) );
1232  break;
1233  case MBR_COLD_DAMAGE_MOD:
1234  cold_damage( cold_damage().setAsMod( static_cast<short>( value ) ) );
1235  return new BLong( static_cast<short>( value ) );
1236  break;
1237  case MBR_ENERGY_DAMAGE_MOD:
1238  energy_damage( energy_damage().setAsMod( static_cast<short>( value ) ) );
1239  return new BLong( static_cast<short>( value ) );
1240  break;
1241  case MBR_POISON_DAMAGE_MOD:
1242  poison_damage( poison_damage().setAsMod( static_cast<short>( value ) ) );
1243  return new BLong( static_cast<short>( value ) );
1244  break;
1246  physical_damage( physical_damage().setAsMod( static_cast<short>( value ) ) );
1247  return new BLong( static_cast<short>( value ) );
1248  break;
1249  case MBR_QUALITY:
1250  setQuality( double( value ) );
1251  return new Double( double( value ) );
1252  break;
1253  case MBR_HP:
1254  hp_ = static_cast<unsigned short>( value );
1255 
1256  if ( this->isa( Core::UOBJ_CLASS::CLASS_ARMOR ) )
1257  {
1258  if ( container != nullptr )
1259  {
1260  if ( Core::IsCharacter( container->serial ) )
1261  {
1262  Mobile::Character* chr = chr_from_wornitems( container );
1263  if ( chr != nullptr )
1264  chr->refresh_ar();
1265  }
1266  }
1267  }
1268  return new BLong( hp_ );
1269  case MBR_MAXHP_MOD:
1270  this->maxhp_mod( static_cast<s16>( value ) );
1271  if ( this->isa( Core::UOBJ_CLASS::CLASS_ARMOR ) )
1272  {
1273  if ( container != nullptr )
1274  {
1275  if ( Core::IsCharacter( container->serial ) )
1276  {
1277  Mobile::Character* chr = chr_from_wornitems( container );
1278  if ( chr != nullptr )
1279  chr->refresh_ar();
1280  }
1281  }
1282  }
1283  return new BLong( value );
1284  case MBR_NO_DROP:
1285  no_drop( value ? true : false );
1286  return new BLong( no_drop() );
1287  default:
1288  return nullptr;
1289  }
1290 }
1291 
1292 BObjectImp* Item::set_script_member( const char* membername, int value )
1293 {
1294  ObjMember* objmember = getKnownObjMember( membername );
1295  if ( objmember != nullptr )
1296  return this->set_script_member_id( objmember->id, value );
1297  else
1298  return nullptr;
1299 }
1300 
1301 BObjectImp* Item::set_script_member_id_double( const int id, double value )
1302 {
1303  BObjectImp* imp = base::set_script_member_id_double( id, value );
1304  if ( imp != nullptr )
1305  return imp;
1306  switch ( id )
1307  {
1308  case MBR_QUALITY:
1309  setQuality( value );
1310  return new Double( value );
1311  default:
1312  return nullptr;
1313  }
1314 }
1315 
1316 BObjectImp* Item::set_script_member_double( const char* membername, double value )
1317 {
1318  ObjMember* objmember = getKnownObjMember( membername );
1319  if ( objmember != nullptr )
1320  return this->set_script_member_id_double( objmember->id, value );
1321  else
1322  return nullptr;
1323 }
1324 
1326 {
1327  BObjectImp* imp = base::script_method_id( id, ex );
1328  if ( imp != nullptr )
1329  return imp;
1330  switch ( id )
1331  {
1332  case MTH_SPLITSTACK_AT:
1333  {
1334  unsigned short amt;
1335  unsigned short newx, newy;
1336  short newz;
1337  const String* realm_name;
1338  Item* new_stack( nullptr );
1339  u16 item_amount = this->getamount();
1340 
1341  if ( !ex.hasParams( 5 ) )
1342  return new BError( "Not enough parameters" );
1343  else if ( !ex.getParam( 0, newx ) || !ex.getParam( 1, newy ) || !ex.getParam( 2, newz ) ||
1344  !ex.getStringParam( 3, realm_name ) )
1345  return new BError( "Invalid parameter type" );
1346  else if ( !ex.getParam( 4, amt ) )
1347  return new BError( "No amount specified to pull from existing stack" );
1348  else if ( amt > this->getamount() )
1349  return new BError( "Amount must be less than or equal to the stack amount" );
1350  else if ( amt < 1 )
1351  return new BError( "Amount was less than 1" );
1352  else if ( this->inuse() )
1353  return new BError( "Item is in use" );
1354 
1355  // Validate where things are going
1356  Realms::Realm* newrealm = Core::find_realm( realm_name->value() );
1357  if ( !newrealm )
1358  return new BError( "Realm not found" );
1359  else if ( !newrealm->valid( newx, newy, newz ) )
1360  return new BError( "Invalid coordinates for realm" );
1361 
1362  // Check first if the item is non-stackable and just force stacked with CreateItemInInventory
1363  if ( !this->stackable() && amt > 1 )
1364  {
1365  unsigned short i;
1366 
1367  for ( i = 1; i <= amt; i++ )
1368  {
1369  if ( this->getamount() == 1 )
1370  new_stack = this->clone();
1371  else
1372  new_stack = this->remove_part_of_stack( 1 );
1373 
1374  new_stack->x = newx;
1375  new_stack->y = newy;
1376  new_stack->z = static_cast<s8>( newz );
1377  new_stack->realm = newrealm;
1378  add_item_to_world( new_stack );
1379  move_item( new_stack, newx, newy, static_cast<signed char>( newz ), newrealm );
1380  update_item_to_inrange( new_stack );
1381  }
1382 
1383  if ( this->getamount() == 1 )
1384  destroy_item( this );
1385  else
1386  update_item_to_inrange( this );
1387  if ( new_stack != nullptr )
1388  return new Module::EItemRefObjImp( new_stack );
1389  else
1390  return nullptr;
1391  }
1392 
1393 
1394  if ( amt == this->getamount() )
1395  new_stack = this->clone();
1396  else
1397  new_stack = this->remove_part_of_stack( amt );
1398 
1399  new_stack->x = newx;
1400  new_stack->y = newy;
1401  new_stack->z = static_cast<s8>( newz );
1402  new_stack->realm = newrealm;
1403  new_stack->setamount( amt );
1404  add_item_to_world( new_stack );
1405  move_item( new_stack, newx, newy, static_cast<signed char>( newz ), newrealm );
1406  update_item_to_inrange( new_stack );
1407 
1408  if ( amt == item_amount )
1409  destroy_item( this );
1410  else
1411  update_item_to_inrange( this );
1412 
1413  return new Module::EItemRefObjImp( new_stack );
1414 
1415  break;
1416  }
1417  case MTH_SPLITSTACK_INTO:
1418  {
1419  unsigned short amt;
1420  Item* cont_item;
1421 
1422  if ( !ex.hasParams( 2 ) )
1423  return new BError( "Not enough parameters" );
1424  else if ( !getItemParam( ex, 0, cont_item ) )
1425  return new BError( "No container specified" );
1426  else if ( !ex.getParam( 1, amt ) )
1427  return new BError( "No amount specified to pull from existing stack" );
1428  else if ( amt > this->getamount() )
1429  return new BError( "Amount must be less than or equal to stack amount" );
1430  else if ( amt < 1 )
1431  return new BError( "Amount was less than 1" );
1432  else if ( this->inuse() )
1433  return new BError( "Item is in use" );
1434  else if ( !cont_item->isa( Core::UOBJ_CLASS::CLASS_CONTAINER ) )
1435  return new BError( "Non-container selected as target" );
1436 
1437  Core::UContainer* newcontainer = static_cast<Core::UContainer*>( cont_item );
1438 
1439  // Check first if the item is non-stackable and just force stacked with CreateItemInInventory
1440 
1441  Item* new_stack( nullptr );
1442  u16 item_amount = this->getamount();
1443 
1444  if ( !this->stackable() && amt > 1 )
1445  {
1446  for ( unsigned short i = 1; i <= amt; i++ )
1447  {
1448  if ( this->getamount() == 1 )
1449  new_stack = this->clone();
1450  else
1451  new_stack = this->remove_part_of_stack( 1 );
1452 
1453  bool can_insert = newcontainer->can_insert_add_item(
1454  nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1455  if ( !can_insert )
1456  {
1457  // Put new_stack back with the original stack
1458  if ( new_stack != this )
1459  this->add_to_self( new_stack );
1460  return new BError( "Could not insert new stack into container" );
1461  }
1462 
1463  newcontainer->add_at_random_location( new_stack );
1464  update_item_to_inrange( new_stack );
1465  UpdateCharacterWeight( new_stack );
1466  newcontainer->on_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1467  }
1468 
1469  if ( this->getamount() == 1 )
1470  destroy_item( this );
1471  else
1472  update_item_to_inrange( this );
1473  if ( new_stack != nullptr )
1474  return new Module::EItemRefObjImp( new_stack );
1475  else
1476  return nullptr;
1477  }
1478 
1479  if ( amt == this->getamount() )
1480  new_stack = this->clone();
1481  else
1482  new_stack = this->remove_part_of_stack( amt );
1483 
1484  auto create_new_stack = [&]() -> BObjectImp* {
1485  bool can_insert =
1486  newcontainer->can_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1487  if ( !can_insert )
1488  {
1489  // Put newstack back with the original stack
1490  if ( new_stack != this )
1491  this->add_to_self( new_stack );
1492  return new BError( "Could not insert new stack into container" );
1493  }
1494  newcontainer->add_at_random_location( new_stack );
1495  new_stack->setamount( amt );
1496  update_item_to_inrange( new_stack );
1497  UpdateCharacterWeight( new_stack );
1498  newcontainer->on_insert_add_item( nullptr, Core::UContainer::MT_CORE_MOVED, new_stack );
1499 
1500  if ( amt == item_amount )
1501  destroy_item( this );
1502  else
1503  update_item_to_inrange( this );
1504 
1505  return new Module::EItemRefObjImp( new_stack );
1506  };
1507 
1508  int add_to_existing_stack;
1509  if ( !ex.hasParams( 3 ) ||
1510  ( ex.getParam( 2, add_to_existing_stack ) && add_to_existing_stack != 0 ) )
1511  {
1512  Item* existing_stack = newcontainer->find_addable_stack( new_stack );
1513  if ( existing_stack != nullptr && new_stack->stackable() )
1514  {
1515  if ( !newcontainer->can_insert_increase_stack( nullptr, Core::UContainer::MT_CORE_MOVED,
1516  existing_stack, new_stack->getamount(),
1517  new_stack ) )
1518  {
1519  if ( new_stack != this )
1520  this->add_to_self( new_stack );
1521  return new BError( "Could not add to existing stack" );
1522  }
1523  }
1524  else
1525  return create_new_stack();
1526 
1527  u16 amount = new_stack->getamount();
1528  existing_stack->add_to_self( new_stack );
1529  update_item_to_inrange( existing_stack );
1530 
1531  UpdateCharacterWeight( existing_stack );
1532 
1534  existing_stack, amount );
1535 
1536  if ( amt == item_amount )
1537  destroy_item( this );
1538  else
1539  update_item_to_inrange( this );
1540 
1541  return new Module::EItemRefObjImp( existing_stack );
1542  }
1543  else
1544  return create_new_stack();
1545 
1546  break;
1547  }
1549  {
1550  Item* cont = nullptr;
1551 
1552  if ( !ex.hasParams( 1 ) )
1553  return new BError( "Not enough params" );
1554  else if ( !getItemParam( ex, 0, cont ) )
1555  return new BError( "No container specified" );
1556  else if ( this->inuse() )
1557  return new BError( "Item is in use" );
1558  else if ( !cont->isa( Core::UOBJ_CLASS::CLASS_CONTAINER ) )
1559  return new BError( "Non-container selected as target" );
1560 
1561  Core::UContainer* stackcontainer = static_cast<Core::UContainer*>( cont );
1562 
1563  Item* existing_stack = stackcontainer->find_addable_stack( this );
1564 
1565  if ( existing_stack != nullptr )
1566  return new Module::EItemRefObjImp( existing_stack );
1567  else
1568  return nullptr;
1569 
1570  break;
1571  }
1572  default:
1573  return nullptr;
1574  }
1575 }
1576 
1577 BObjectImp* Item::script_method( const char* methodname, Executor& ex )
1578 {
1579  ObjMethod* objmethod = getKnownObjMethod( methodname );
1580  if ( objmethod != nullptr )
1581  return this->script_method_id( objmethod->id, ex );
1582  else
1583  return nullptr;
1584 }
1585 
1586 BObjectImp* Item::custom_script_method( const char* methodname, Executor& ex )
1587 {
1588  const ItemDesc& id = itemdesc();
1589  if ( id.method_script != nullptr )
1590  {
1591  unsigned PC;
1592  if ( id.method_script->FindExportedFunction(
1593  methodname, static_cast<unsigned int>( ex.numParams() + 1 ), PC ) )
1594  return id.method_script->call( PC, make_ref(), ex.fparams );
1595  }
1596  return nullptr;
1597 }
1598 
1599 BObject Item::call_custom_method( const char* methodname )
1600 {
1601  BObjectImpRefVec noparams;
1602  return call_custom_method( methodname, noparams );
1603 }
1604 
1605 BObject Item::call_custom_method( const char* methodname, BObjectImpRefVec& pmore )
1606 {
1607  const ItemDesc& id = itemdesc();
1608  if ( id.method_script != nullptr )
1609  {
1610  unsigned PC;
1611  if ( id.method_script->FindExportedFunction(
1612  methodname, static_cast<unsigned int>( pmore.size() + 1 ), PC ) )
1613  return id.method_script->call( PC, new Module::EItemRefObjImp( this ), pmore );
1614  else
1615  {
1616  std::string message;
1617  message = "Method script for objtype " + id.objtype_description() +
1618  " does not export function " + std::string( methodname ) + " taking " +
1619  Clib::decint( pmore.size() + 1 ) + " parameters";
1620  BError* err = new BError( message );
1621  return BObject( err );
1622  }
1623  }
1624  else
1625  return BObject( new BError( "No method script defined for " + id.objtype_description() ) );
1626 }
1627 
1629 {
1630  return new Module::EItemRefObjImp( this );
1631 }
1632 } // namespace Items
1633 namespace Mobile
1634 {
1635 using namespace Bscript;
1636 
1638 {
1639 public:
1640  static void on_change( Character* chr )
1641  {
1642  chr->refresh_ar(); // FIXME inefficient
1643  // if (chr->client != nullptr) // already send in refresh_ar()
1644  //{
1645  // send_full_statmsg( chr->client, chr );
1646  //}
1647  }
1648 };
1649 
1651 {
1652  return new Module::ECharacterRefObjImp( this );
1653 }
1655 {
1656  return new Module::EOfflineCharacterRefObjImp( this );
1657 }
1658 
1660 {
1661  BObjectImp* imp = base::get_script_member_id( id );
1662  if ( imp != nullptr )
1663  return imp;
1664 
1665  switch ( id )
1666  {
1667  case MBR_WARMODE:
1668  return new BLong( warmode() );
1669  break;
1670  case MBR_GENDER:
1671  return new BLong( gender );
1672  break;
1673  case MBR_RACE:
1674  return new BLong( race );
1675  break;
1676  case MBR_TRUEOBJTYPE:
1677  return new BLong( trueobjtype );
1678  break;
1679  case MBR_TRUECOLOR:
1680  return new BLong( truecolor );
1681  break;
1682  case MBR_AR_MOD:
1683  return new BLong( ar_mod() );
1684  break;
1685  case MBR_DELAY_MOD:
1686  return new BLong( delay_mod() );
1687  break;
1688  case MBR_HIDDEN:
1689  return new BLong( hidden() ? 1 : 0 );
1690  break;
1691  case MBR_CONCEALED:
1692  return new BLong( concealed() );
1693  break;
1694  case MBR_FROZEN:
1695  return new BLong( frozen() ? 1 : 0 );
1696  break;
1697  case MBR_PARALYZED:
1698  return new BLong( paralyzed() ? 1 : 0 );
1699  break;
1700  case MBR_POISONED:
1701  return new BLong( poisoned() ? 1 : 0 );
1702  break;
1703  case MBR_STEALTHSTEPS:
1704  return new BLong( stealthsteps_ );
1705  break;
1706  case MBR_MOUNTEDSTEPS:
1707  return new BLong( mountedsteps_ );
1708  break;
1709  case MBR_SQUELCHED:
1710  return new BLong( squelched() ? 1 : 0 );
1711  break;
1712  case MBR_DEAD:
1713  return new BLong( dead() );
1714  break;
1715  case MBR_AR:
1716  return new BLong( ar() );
1717  break;
1718  case MBR_BACKPACK:
1719  {
1720  Items::Item* bp = backpack();
1721  if ( bp != nullptr )
1722  return bp->make_ref();
1723  else
1724  return new BError( "That has no backpack" );
1725  break;
1726  }
1727  case MBR_TRADEWINDOW:
1728  {
1729  Core::UContainer* tw = trading_cont.get();
1730  if ( trading_with != nullptr )
1731  return tw->make_ref();
1732  else
1733  return new BError( "That has no active tradewindow" );
1734  break;
1735  }
1736  case MBR_WEAPON:
1737  if ( weapon != nullptr )
1738  return weapon->make_ref();
1739  else
1740  return new BLong( 0 );
1741  break;
1742  case MBR_SHIELD:
1743  if ( shield != nullptr )
1744  return shield->make_ref();
1745  else
1746  return new BLong( 0 );
1747  break;
1748  case MBR_ACCTNAME:
1749  if ( acct != nullptr )
1750  return new String( acct->name() );
1751  else
1752  return new BError( "Not attached to an account" );
1753  break;
1754 
1755  case MBR_ACCT:
1756  if ( acct != nullptr )
1758  else
1759  return new BError( "Not attached to an account" );
1760  break;
1761  case MBR_CMDLEVEL:
1762  return new BLong( cmdlevel() );
1763  break;
1764  case MBR_CMDLEVELSTR:
1765  return new String( Core::gamestate.cmdlevels[cmdlevel()].name );
1766  break;
1767  case MBR_CRIMINAL:
1768  return new BLong( is_criminal() ? 1 : 0 );
1769  break;
1771  return new BLong( is_temporally_criminal() ? 1 : 0 );
1772  break;
1773  case MBR_IP:
1774  if ( client != nullptr )
1775  return new String( client->ipaddrAsString() );
1776  else
1777  return new String( "" );
1778  break;
1779  case MBR_GOLD:
1780  return new BLong( gold_carried() );
1781  break;
1782 
1783  case MBR_TITLE_PREFIX:
1784  return new String( title_prefix() );
1785  break;
1786  case MBR_TITLE_SUFFIX:
1787  return new String( title_suffix() );
1788  break;
1789  case MBR_TITLE_GUILD:
1790  return new String( title_guild() );
1791  break;
1792  case MBR_TITLE_RACE:
1793  return new String( title_race() );
1794  break;
1795  case MBR_UCLANG:
1796  return new String( uclang );
1797  break;
1798  case MBR_GUILDID:
1799  return new BLong( guildid() );
1800  break;
1801  case MBR_GUILD:
1802  if ( has_guild() )
1804  else
1805  return new BError( "Not a member of a guild" );
1806  break;
1807 
1808  case MBR_MURDERER:
1809  return new BLong( is_murderer() ? 1 : 0 );
1810  break;
1811  case MBR_ATTACHED:
1812  if ( script_ex == nullptr )
1813  return new BError( "No script attached." );
1814  else
1815  return new Core::ScriptExObjImp( script_ex );
1816  break;
1817  case MBR_CLIENTVERSION:
1818  if ( client != nullptr )
1819  return new String( client->getversion() );
1820  else
1821  return new String( "" );
1822  break;
1824  if ( client != nullptr )
1825  {
1826  std::unique_ptr<BStruct> info( new BStruct );
1827  Network::VersionDetailStruct version = client->getversiondetail();
1828  info->addMember( "major", new BLong( version.major ) );
1829  info->addMember( "minor", new BLong( version.minor ) );
1830  info->addMember( "rev", new BLong( version.rev ) );
1831  info->addMember( "patch", new BLong( version.patch ) );
1832  return info.release();
1833  }
1834  else
1835  {
1836  std::unique_ptr<BStruct> info( new BStruct );
1837  info->addMember( "major", new BLong( 0 ) );
1838  info->addMember( "minor", new BLong( 0 ) );
1839  info->addMember( "rev", new BLong( 0 ) );
1840  info->addMember( "patch", new BLong( 0 ) );
1841  return info.release();
1842  }
1843  break;
1844 
1845  case MBR_CLIENTINFO:
1846  if ( client != nullptr )
1847  return client->getclientinfo();
1848  else
1849  return new BLong( 0 );
1850  break;
1851 
1852  case MBR_CREATEDAT:
1853  return new BLong( created_at );
1854  break;
1855 
1856  case MBR_REPORTABLES:
1857  return GetReportables();
1858  break;
1859 
1860  case MBR_OPPONENT:
1861  if ( opponent_ != nullptr )
1862  return opponent_->make_ref();
1863  else
1864  return new BError( "Mobile does not have any opponent selected." );
1865  break;
1866  case MBR_CONNECTED:
1867  return new BLong( connected() ? 1 : 0 );
1868  break;
1869  case MBR_TRADING_WITH:
1870  if ( trading_with != nullptr )
1871  return trading_with->make_ref();
1872  else
1873  return new BError( "Mobile is not currently trading with anyone." );
1874  break;
1875  case MBR_CLIENTTYPE:
1876  return new BLong( client != nullptr ? client->ClientType : 0 );
1877  break;
1878  case MBR_CURSOR:
1879  if ( client != nullptr )
1880  return new BLong( target_cursor_busy() ? 1 : 0 );
1881  else
1882  return new BLong( 0 );
1883  break;
1884  case MBR_GUMP:
1885  if ( client != nullptr )
1886  return new BLong( has_active_gump() ? 1 : 0 );
1887  else
1888  return new BLong( 0 );
1889  break;
1890  case MBR_PROMPT:
1891  if ( client != nullptr )
1892  return new BLong( has_active_prompt() ? 1 : 0 );
1893  else
1894  return new BLong( 0 );
1895  break;
1896  case MBR_MOVEMODE:
1897  {
1898  std::string mode = "";
1899  if ( movemode & Core::MOVEMODE_LAND )
1900  mode = "L";
1901  if ( movemode & Core::MOVEMODE_SEA )
1902  mode += "S";
1903  if ( movemode & Core::MOVEMODE_AIR )
1904  mode += "A";
1905  if ( movemode & Core::MOVEMODE_FLY )
1906  mode += "F";
1907  return new String( mode );
1908  break;
1909  }
1910  case MBR_HITCHANCE_MOD:
1911  return new BLong( hitchance_mod() );
1912  break;
1913  case MBR_EVASIONCHANCE_MOD:
1914  return new BLong( evasionchance_mod() );
1915  break;
1917  return new BLong( carrying_capacity_mod() );
1918  break;
1919  case MBR_CARRYINGCAPACITY:
1920  return new BLong( carrying_capacity() );
1921  break;
1922  case MBR_FIRE_RESIST:
1923  return new BLong( fire_resist().value );
1924  break;
1925  case MBR_COLD_RESIST:
1926  return new BLong( cold_resist().value );
1927  break;
1928  case MBR_ENERGY_RESIST:
1929  return new BLong( energy_resist().value );
1930  break;
1931  case MBR_POISON_RESIST:
1932  return new BLong( poison_resist().value );
1933  break;
1934  case MBR_PHYSICAL_RESIST:
1935  return new BLong( physical_resist().value );
1936  break;
1937  case MBR_FIRE_RESIST_MOD:
1938  return new BLong( fire_resist().mod );
1939  break;
1940  case MBR_COLD_RESIST_MOD:
1941  return new BLong( cold_resist().mod );
1942  break;
1943  case MBR_ENERGY_RESIST_MOD:
1944  return new BLong( energy_resist().mod );
1945  break;
1946  case MBR_POISON_RESIST_MOD:
1947  return new BLong( poison_resist().mod );
1948  break;
1950  return new BLong( physical_resist().mod );
1951  break;
1952  case MBR_STATCAP:
1953  return new BLong( skillstatcap().statcap );
1954  break;
1955  case MBR_SKILLCAP:
1956  return new BLong( skillstatcap().skillcap );
1957  break;
1958  case MBR_LUCK:
1959  return new BLong( luck() );
1960  break;
1961  case MBR_FOLLOWERSMAX:
1962  return new BLong( followers().followers_max );
1963  break;
1964  case MBR_TITHING:
1965  return new BLong( tithing() );
1966  break;
1967  case MBR_FOLLOWERS:
1968  return new BLong( followers().followers );
1969  break;
1970  case MBR_FIRE_DAMAGE:
1971  return new BLong( fire_damage().value );
1972  break;
1973  case MBR_COLD_DAMAGE:
1974  return new BLong( cold_damage().value );
1975  break;
1976  case MBR_ENERGY_DAMAGE:
1977  return new BLong( energy_damage().value );
1978  break;
1979  case MBR_POISON_DAMAGE:
1980  return new BLong( poison_damage().value );
1981  break;
1982  case MBR_PHYSICAL_DAMAGE:
1983  return new BLong( physical_damage().value );
1984  break;
1985  case MBR_FIRE_DAMAGE_MOD:
1986  return new BLong( fire_damage().mod );
1987  break;
1988  case MBR_COLD_DAMAGE_MOD:
1989  return new BLong( cold_damage().mod );
1990  break;
1991  case MBR_ENERGY_DAMAGE_MOD:
1992  return new BLong( energy_damage().mod );
1993  break;
1994  case MBR_POISON_DAMAGE_MOD:
1995  return new BLong( poison_damage().mod );
1996  break;
1998  return new BLong( physical_damage().mod );
1999  break;
2000  case MBR_PARTY:
2001  if ( has_party() )
2002  return Module::CreatePartyRefObjImp( party() );
2003  else
2004  return new BError( "Not a member of a party" );
2005  break;
2006  case MBR_PARTYLOOT:
2007  return new BLong( party_can_loot() );
2009  if ( has_candidate_of() )
2010  return Module::CreatePartyRefObjImp( candidate_of() );
2011  else
2012  return new BError( "Not a candidate of a party" );
2013  break;
2014  case MBR_MOVECOST_WALK:
2015  return new Double( movement_cost().walk );
2016  break;
2017  case MBR_MOVECOST_RUN:
2018  return new Double( movement_cost().run );
2019  break;
2021  return new Double( movement_cost().walk_mounted );
2022  break;
2024  return new Double( movement_cost().run_mounted );
2025  break;
2026 
2027  case MBR_AGGRESSORTO:
2028  return GetAggressorTo();
2029  break;
2030  case MBR_LAWFULLYDAMAGED:
2031  return GetLawFullyDamaged();
2032  break;
2033 
2035  return new BLong( client != nullptr ? client->UOExpansionFlagClient : 0 );
2036  break;
2037 
2038  case MBR_DEAFENED:
2039  return new BLong( deafened() ? 1 : 0 );
2040  break;
2041 
2042  case MBR_CLIENT:
2043  if ( ( client != nullptr ) && ( client->isConnected() ) )
2044  return client->make_ref();
2045  else
2046  return new BError( "No client attached." );
2047  break;
2048  case MBR_EDITING:
2049  return new BLong( is_house_editing() ? 1 : 0 );
2050  break;
2051  case MBR_LASTCOORD:
2052  if ( client != nullptr )
2053  {
2054  std::unique_ptr<BStruct> lastcoord( new BStruct );
2055  lastcoord->addMember( "lastx", new BLong( lastx ) );
2056  lastcoord->addMember( "lasty", new BLong( lasty ) );
2057  lastcoord->addMember( "lastz", new BLong( lastz ) );
2058  return lastcoord.release();
2059  }
2060  return new BError( "No client attached." );
2061  case MBR_ACTIVE_SKILL:
2062  return new BLong( skill_ex_active() );
2063  case MBR_CASTING_SPELL:
2064  return new BLong( casting_spell() );
2065  case MBR_LAST_TEXTCOLOR:
2066  return new BLong( last_textcolor() );
2067  }
2068  // if all else fails, returns nullptr
2069  return nullptr;
2070 }
2071 
2072 BObjectImp* Character::get_script_member( const char* membername ) const
2073 {
2074  ObjMember* objmember = getKnownObjMember( membername );
2075  if ( objmember != nullptr )
2076  return this->get_script_member_id( objmember->id );
2077  else
2078  return nullptr;
2079 }
2080 
2081 BObjectImp* Character::set_script_member_id( const int id, const std::string& value )
2082 {
2083  BObjectImp* imp = base::set_script_member_id( id, value );
2084  if ( imp != nullptr )
2085  return imp;
2086 
2087  String* ret;
2088  switch ( id )
2089  {
2090  case MBR_TITLE_PREFIX:
2091  title_prefix( value );
2092  ret = new String( value );
2093  break;
2094  case MBR_TITLE_SUFFIX:
2095  title_suffix( value );
2096  ret = new String( value );
2097  break;
2098  case MBR_TITLE_GUILD:
2099  title_guild( value );
2100  ret = new String( value );
2101  break;
2102  case MBR_TITLE_RACE:
2103  title_race( value );
2104  ret = new String( value );
2105  break;
2106  default:
2107  return nullptr;
2108  }
2109  set_dirty();
2110  increv();
2111  if ( this->has_active_client() )
2113  return ret;
2114 }
2115 
2116 BObjectImp* Character::set_script_member( const char* membername, const std::string& value )
2117 {
2118  ObjMember* objmember = getKnownObjMember( membername );
2119  if ( objmember != nullptr )
2120  return this->set_script_member_id( objmember->id, value );
2121  else
2122  return nullptr;
2123 }
2124 
2125 BObjectImp* Character::set_script_member_id( const int id, int value )
2126 {
2127  BObjectImp* imp = base::set_script_member_id( id, value );
2128  if ( imp != nullptr )
2129  return imp;
2130 
2131  switch ( id )
2132  {
2133  case MBR_GENDER:
2134  if ( value )
2135  gender = Core::GENDER_FEMALE;
2136  else
2137  gender = Core::GENDER_MALE;
2138  return new BLong( gender );
2139  case MBR_RACE:
2140  if ( value == Core::RACE_HUMAN )
2141  race = Core::RACE_HUMAN;
2142  else if ( value == Core::RACE_ELF )
2143  race = Core::RACE_ELF;
2144  else if ( value == Core::RACE_GARGOYLE )
2145  race = Core::RACE_GARGOYLE;
2146  if ( ( race != Core::RACE_GARGOYLE ) &&
2147  ( movemode & Core::MOVEMODE_FLY ) ) // FIXME graphic based maybe?
2148  movemode = ( Core::MOVEMODE )( movemode ^ Core::MOVEMODE_FLY ); // remove flying
2149  return new BLong( race );
2150  case MBR_TRUEOBJTYPE:
2151  return new BLong( trueobjtype = static_cast<unsigned int>( value ) );
2152  case MBR_TRUECOLOR:
2153  return new BLong( truecolor = static_cast<unsigned short>( value ) );
2154  case MBR_AR_MOD:
2155  ar_mod( static_cast<short>( value ) );
2156  refresh_ar();
2157  return new BLong( ar_mod() );
2158  case MBR_DELAY_MOD:
2159  delay_mod( static_cast<short>( value ) );
2160  return new BLong( delay_mod() );
2161  case MBR_HIDDEN:
2162  {
2163  // FIXME: don't call on_change unless the value actually changed?
2164  hidden( value ? true : false );
2165  return new BLong( hidden() );
2166  }
2167  case MBR_CONCEALED:
2168  concealed( static_cast<unsigned char>( value ) );
2169  return new BLong( concealed() );
2170  case MBR_FROZEN:
2171  mob_flags_.change( MOB_FLAGS::FROZEN, value ? true : false );
2172  return new BLong( frozen() );
2173  case MBR_PARALYZED:
2174  mob_flags_.change( MOB_FLAGS::PARALYZED, value ? true : false );
2175  return new BLong( paralyzed() );
2176  case MBR_POISONED:
2177  poisoned( value ? true : false );
2178  return new BLong( poisoned() );
2179  case MBR_STEALTHSTEPS:
2180  return new BLong( stealthsteps_ = static_cast<unsigned short>( value ) );
2181  case MBR_MOUNTEDSTEPS:
2182  return new BLong( mountedsteps_ = static_cast<unsigned int>( value ) );
2183  case MBR_CMDLEVEL:
2184  if ( value >= static_cast<int>( Core::gamestate.cmdlevels.size() ) )
2185  cmdlevel( static_cast<unsigned char>( Core::gamestate.cmdlevels.size() ) - 1, true );
2186  else
2187  cmdlevel( static_cast<unsigned char>( value ), true );
2188  return new BLong( cmdlevel() );
2189  case MBR_MURDERER:
2190  // make_murderer handles the updating
2191  make_murderer( value ? true : false );
2192  return new BLong( is_murderer() );
2193  case MBR_HITCHANCE_MOD:
2194  hitchance_mod( static_cast<short>( value ) );
2195  return new BLong( hitchance_mod() );
2196  case MBR_EVASIONCHANCE_MOD:
2197  evasionchance_mod( static_cast<short>( value ) );
2198  return new BLong( evasionchance_mod() );
2200  carrying_capacity_mod( static_cast<short>( value ) );
2201  if ( client != nullptr )
2202  { // CHECKME consider sending less frequently
2203  send_full_statmsg( client, this );
2204  }
2205  return new BLong( carrying_capacity_mod() );
2206  case MBR_FACING:
2207  if ( !face( static_cast<Core::UFACING>( value & PKTIN_02_FACING_MASK ), 0 ) )
2208  return new BLong( 0 );
2209  on_facing_changed();
2210  return new BLong( 1 );
2211  case MBR_FIRE_RESIST_MOD:
2212  fire_resist( fire_resist().setAsMod( static_cast<short>( value ) ) );
2213  refresh_ar();
2214  return new BLong( fire_resist().mod );
2215  break;
2216  case MBR_COLD_RESIST_MOD:
2217  cold_resist( cold_resist().setAsMod( static_cast<short>( value ) ) );
2218  refresh_ar();
2219  return new BLong( cold_resist().mod );
2220  break;
2221  case MBR_ENERGY_RESIST_MOD:
2222  energy_resist( energy_resist().setAsMod( static_cast<short>( value ) ) );
2223  refresh_ar();
2224  return new BLong( energy_resist().mod );
2225  break;
2226  case MBR_POISON_RESIST_MOD:
2227  poison_resist( poison_resist().setAsMod( static_cast<short>( value ) ) );
2228  refresh_ar();
2229  return new BLong( poison_resist().mod );
2230  break;
2232  physical_resist( physical_resist().setAsMod( static_cast<short>( value ) ) );
2233  refresh_ar();
2234  return new BLong( physical_resist().mod );
2235  break;
2236  case MBR_STATCAP:
2237  {
2238  auto val = skillstatcap();
2239  val.statcap = static_cast<short>( value );
2240  skillstatcap( val );
2241  if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
2242  on_aos_ext_stat_changed();
2243  return new BLong( skillstatcap().statcap );
2244  }
2245  case MBR_SKILLCAP:
2246  {
2247  auto val = skillstatcap();
2248  val.skillcap = static_cast<u16>( value );
2249  skillstatcap( val );
2250  return new BLong( skillstatcap().skillcap );
2251  }
2252  case MBR_LUCK:
2253  luck( static_cast<short>( value ) );
2254  if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
2255  on_aos_ext_stat_changed();
2256  return new BLong( luck() );
2257  break;
2258  case MBR_FOLLOWERSMAX:
2259  {
2260  auto val = followers();
2261  val.followers_max = static_cast<u8>( value );
2262  followers( val );
2263  if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
2264  on_aos_ext_stat_changed();
2265  return new BLong( followers().followers_max );
2266  }
2267  case MBR_TITHING:
2268  tithing( static_cast<s32>( value ) );
2269  if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
2270  on_aos_ext_stat_changed();
2271  return new BLong( tithing() );
2272  break;
2273  case MBR_FOLLOWERS:
2274  {
2275  auto val = followers();
2276  val.followers = static_cast<u8>( value );
2277  followers( val );
2278  if ( !this->isa( Core::UOBJ_CLASS::CLASS_NPC ) )
2279  on_aos_ext_stat_changed();
2280  return new BLong( followers().followers );
2281  }
2282  case MBR_FIRE_DAMAGE_MOD:
2283  fire_damage( fire_damage().setAsMod( static_cast<short>( value ) ) );
2284  refresh_ar();
2285  return new BLong( fire_damage().mod );
2286  break;
2287  case MBR_COLD_DAMAGE_MOD:
2288  cold_damage( cold_damage().setAsMod( static_cast<short>( value ) ) );
2289  refresh_ar();
2290  return new BLong( cold_damage().mod );
2291  break;
2292  case MBR_ENERGY_DAMAGE_MOD:
2293  energy_damage( energy_damage().setAsMod( static_cast<short>( value ) ) );
2294  refresh_ar();
2295  return new BLong( energy_damage().mod );
2296  break;
2297  case MBR_POISON_DAMAGE_MOD:
2298  poison_damage( poison_damage().setAsMod( static_cast<short>( value ) ) );
2299  refresh_ar();
2300  return new BLong( poison_damage().mod );
2301  break;
2303  physical_damage( physical_damage().setAsMod( static_cast<short>( value ) ) );
2304  refresh_ar();
2305  return new BLong( physical_damage().mod );
2306  break;
2307  case MBR_MOVECOST_WALK:
2308  {
2309  auto val = movement_cost();
2310  val.walk = static_cast<double>( value );
2311  movement_cost( val );
2312  return new Double( movement_cost().walk );
2313  }
2314  case MBR_MOVECOST_RUN:
2315  {
2316  auto val = movement_cost();
2317  val.run = static_cast<double>( value );
2318  movement_cost( val );
2319  return new Double( movement_cost().run );
2320  }
2322  {
2323  auto val = movement_cost();
2324  val.walk_mounted = static_cast<double>( value );
2325  movement_cost( val );
2326  return new Double( movement_cost().walk_mounted );
2327  }
2329  {
2330  auto val = movement_cost();
2331  val.run_mounted = static_cast<double>( value );
2332  movement_cost( val );
2333  return new Double( movement_cost().run_mounted );
2334  }
2335  default:
2336  return nullptr;
2337  }
2338 }
2339 
2341 {
2342  switch ( id )
2343  {
2344  case MBR_MOVECOST_WALK:
2345  {
2346  auto val = movement_cost();
2347  val.walk = value;
2348  movement_cost( val );
2349  return new Double( movement_cost().walk );
2350  }
2351  case MBR_MOVECOST_RUN:
2352  {
2353  auto val = movement_cost();
2354  val.run = value;
2355  movement_cost( val );
2356  return new Double( movement_cost().run );
2357  }
2359  {
2360  auto val = movement_cost();
2361  val.walk_mounted = value;
2362  movement_cost( val );
2363  return new Double( movement_cost().walk_mounted );
2364  }
2366  {
2367  auto val = movement_cost();
2368  val.run_mounted = value;
2369  movement_cost( val );
2370  return new Double( movement_cost().run_mounted );
2371  }
2372  default:
2373  return nullptr;
2374  }
2375 }
2376 
2377 BObjectImp* Character::set_script_member( const char* membername, int value )
2378 {
2379  ObjMember* objmember = getKnownObjMember( membername );
2380  if ( objmember != nullptr )
2381  return this->set_script_member_id( objmember->id, value );
2382  else
2383  return nullptr;
2384 }
2385 
2387 {
2388  BObjectImp* imp = base::script_method_id( id, ex );
2389  if ( imp != nullptr )
2390  return imp;
2391 
2392  switch ( id )
2393  {
2394  /*
2395  mobile.SetPoisoned( ispoisoned := 1 )
2396  If the poisoned flag was changed, and the script has a controller
2397  If poisoned was SET,
2398  apply RepSystem rules (Mobile damages Mobile)
2399  else poisoned was CLEARED, so
2400  apply RepSystem rules (Mobile helps Mobile)
2401  */
2402  case MTH_SETPOISONED:
2403  {
2404  bool newval = true;
2405  if ( ex.hasParams( 1 ) )
2406  {
2407  int lval;
2408  if ( !ex.getParam( 0, lval ) )
2409  return new BError( "Invalid parameter type" );
2410  if ( !lval )
2411  newval = false;
2412  }
2413 
2414  if ( newval != poisoned() )
2415  {
2416  set_dirty();
2417  poisoned( newval );
2418  check_undamaged();
2419  Module::UOExecutorModule* uoexec =
2420  static_cast<Module::UOExecutorModule*>( ex.findModule( "UO" ) );
2421  if ( uoexec != nullptr && uoexec->controller_.get() )
2422  {
2423  Character* attacker = uoexec->controller_.get();
2424  if ( !attacker->orphan() )
2425  {
2426  if ( poisoned() )
2427  attacker->repsys_on_damage( this );
2428  else
2429  attacker->repsys_on_help( this );
2430  }
2431  }
2432  }
2433  return new BLong( 1 );
2434  }
2435 
2436  /*
2437  mobile.SetParalyzed( isparalyzed := 1 )
2438  If the paralyzed flag was changed, and the script has a controller
2439  if paralyzed was SET,
2440  apply RepSystem rules (Mobile damages Mobile)
2441  else paralyzed was CLEARED, so
2442  apply RepSystem rules (Mobile heals Mobile)
2443  */
2444  case MTH_SETPARALYZED:
2445  {
2446  bool newval = true;
2447  if ( ex.hasParams( 1 ) )
2448  {
2449  int lval;
2450  if ( !ex.getParam( 0, lval ) )
2451  return new BError( "Invalid parameter type" );
2452  if ( !lval )
2453  newval = false;
2454  }
2455 
2456  if ( newval != paralyzed() )
2457  {
2458  set_dirty();
2459  mob_flags_.change( MOB_FLAGS::PARALYZED, newval );
2460  check_undamaged();
2461  Module::UOExecutorModule* uoexec =
2462  static_cast<Module::UOExecutorModule*>( ex.findModule( "UO" ) );
2463  if ( uoexec != nullptr && uoexec->controller_.get() )
2464  {
2465  Character* attacker = uoexec->controller_.get();
2466  if ( !attacker->orphan() )
2467  {
2468  if ( paralyzed() )
2469  attacker->repsys_on_damage( this );
2470  else
2471  attacker->repsys_on_help( this );
2472  }
2473  }
2474  }
2475  return new BLong( 1 );
2476  }
2477 
2478  /*
2479  mobile.SetCriminal( level := 1 )
2480  if level is 0, clears the CriminalTimer
2481  */
2482  case MTH_SETCRIMINAL:
2483  {
2484  int level = 1;
2485  if ( ex.hasParams( 1 ) )
2486  {
2487  if ( !ex.getParam( 0, level ) )
2488  return new BError( "Invalid parameter type" );
2489  if ( level < 0 )
2490  return new BError( "Level must be >= 0" );
2491  }
2492  set_dirty();
2493  // make_criminal handles the updating
2494  make_criminal( level );
2495  return new BLong( 1 );
2496  }
2497 
2498  case MTH_SETLIGHTLEVEL:
2499  {
2500  int level, duration;
2501  if ( !ex.hasParams( 2 ) )
2502  return new BError( "Not enough parameters" );
2503  if ( ex.getParam( 0, level ) && ex.getParam( 1, duration ) )
2504  {
2505  lightoverride( level );
2506 
2507  if ( duration == -1 )
2508  lightoverride_until( ~0u );
2509  else if ( duration == 0 )
2510  lightoverride_until( 0 );
2511  else
2512  lightoverride_until( Core::read_gameclock() + duration );
2513 
2514  check_region_changes();
2515  if ( duration == -1 )
2516  return new BLong( duration );
2517  return new BLong( lightoverride_until() );
2518  }
2519  break;
2520  }
2521 
2522  case MTH_SETSEASON:
2523  {
2524  int season_id, playsound;
2525 
2526  if ( !ex.hasParams( 2 ) )
2527  return new BError( "Not enough parameters" );
2528  if ( ex.getParam( 0, season_id ) && ex.getParam( 1, playsound ) )
2529  {
2530  if ( season_id < 0 || season_id > 4 )
2531  return new BError( "Invalid season id" );
2532 
2533  if ( client && client->getversiondetail().major >= 1 )
2534  {
2536  msg->Write<u8>( static_cast<u16>( season_id ) );
2537  msg->Write<u8>( static_cast<u16>( playsound ) );
2538  msg.Send( client );
2539  return new BLong( 1 );
2540  }
2541  }
2542  break;
2543  }
2544  case MTH_SQUELCH:
2545  {
2546  int duration;
2547  if ( !ex.hasParams( 1 ) )
2548  return new BError( "Not enough parameters" );
2549  if ( ex.getParam( 0, duration ) )
2550  {
2551  set_dirty();
2552  if ( duration == -1 )
2553  {
2554  squelched_until( ~0u );
2555  return new BLong( -1 );
2556  }
2557  else if ( duration == 0 )
2558  squelched_until( 0 );
2559  else
2560  squelched_until( Core::read_gameclock() + duration );
2561  return new BLong( squelched_until() );
2562  }
2563  break;
2564  }
2565  case MTH_ENABLE:
2566  {
2567  if ( !ex.hasParams( 1 ) )
2568  return new BError( "Not enough parameters" );
2569  const String* pstr;
2570  if ( ex.getStringParam( 0, pstr ) )
2571  {
2572  if ( has_privilege( pstr->data() ) )
2573  {
2574  set_dirty();
2575  set_setting( pstr->data(), true );
2576  return new BLong( 1 );
2577  }
2578  else
2579  return new BError( "Mobile doesn't have that privilege" );
2580  }
2581  break;
2582  }
2583 
2584  case MTH_DISABLE:
2585  {
2586  if ( !ex.hasParams( 1 ) )
2587  return new BError( "Not enough parameters" );
2588  const String* pstr;
2589  if ( ex.getStringParam( 0, pstr ) )
2590  {
2591  set_dirty();
2592  set_setting( pstr->data(), false );
2593  return new BLong( 1 );
2594  }
2595  break;
2596  }
2597 
2598  case MTH_ENABLED:
2599  {
2600  if ( !ex.hasParams( 1 ) )
2601  return new BError( "Not enough parameters" );
2602  const String* pstr;
2603  if ( ex.getStringParam( 0, pstr ) )
2604  return new BLong( setting_enabled( pstr->data() ) ? 1 : 0 );
2605  break;
2606  }
2607 
2608  case MTH_PRIVILEGES:
2609  {
2610  std::unique_ptr<BDictionary> dict( new BDictionary );
2611  ISTRINGSTREAM istrm( all_privs() );
2612  std::string tmp;
2613  while ( istrm >> tmp )
2614  {
2615  dict->addMember( new String( tmp ), new BLong( setting_enabled( tmp.c_str() ) ) );
2616  }
2617  return dict.release();
2618  break;
2619  }
2620 
2621  case MTH_SETCMDLEVEL:
2622  {
2623  if ( !ex.hasParams( 1 ) )
2624  return new BError( "Not enough parameters" );
2625  const String* pstr;
2626  if ( ex.getStringParam( 0, pstr ) )
2627  {
2628  Core::CmdLevel* pcmdlevel = Core::find_cmdlevel( pstr->data() );
2629  if ( pcmdlevel )
2630  {
2631  set_dirty();
2632  cmdlevel( pcmdlevel->cmdlevel, true );
2633  return new BLong( 1 );
2634  }
2635  else
2636  return new BError( "No such command level" );
2637  }
2638  break;
2639  }
2640  case MTH_SPENDGOLD:
2641  {
2642  int amt;
2643  if ( ex.numParams() != 1 || !ex.getParam( 0, amt ) )
2644  return new BError( "Invalid parameter type" );
2645 
2646  if ( gold_carried() < static_cast<unsigned int>( amt ) )
2647  return new BError( "Insufficient funds" );
2648 
2649  spend_gold( amt );
2650  return new BLong( 1 );
2651  }
2652 
2653  case MTH_SETMURDERER:
2654  {
2655  int lnewval = 1;
2656  if ( ex.hasParams( 1 ) )
2657  {
2658  if ( !ex.getParam( 0, lnewval ) )
2659  return new BError( "Invalid parameter type" );
2660  }
2661  set_dirty();
2662  // make_murderer handles the updating
2663  make_murderer( lnewval ? true : false );
2664  return new BLong( 1 );
2665  }
2666  case MTH_REMOVEREPORTABLE:
2667  {
2668  if ( !ex.hasParams( 2 ) )
2669  return new BError( "Not enough parameters" );
2670  int repserial, gameclock;
2671  if ( ex.getParam( 0, repserial ) && ex.getParam( 1, gameclock ) )
2672  {
2673  set_dirty();
2674  clear_reportable( repserial, gameclock );
2675  return new BLong( 1 );
2676  }
2677  break;
2678  }
2679  case MTH_GETGOTTENITEM:
2680  if ( has_gotten_item() )
2681  return new Module::EItemRefObjImp( gotten_item() );
2682  else
2683  return new BError( "Gotten Item nullptr" );
2684  break;
2685  case MTH_CLEARGOTTENITEM:
2686  if ( has_gotten_item() )
2687  {
2688  clear_gotten_item();
2689  return new BLong( 1 );
2690  }
2691  else
2692  return new BError( "No Gotten Item" );
2693  break;
2694  case MTH_SETWARMODE:
2695  {
2696  int newmode;
2697  if ( !ex.hasParams( 1 ) )
2698  return new BError( "Not enough parameters" );
2699  if ( ex.getParam( 0, newmode, 0, 1 ) )
2700  {
2701  set_warmode( ( newmode == 0 ) ? false : true );
2702  // FIXME: Additional checks needed?
2703  if ( client )
2704  send_warmode();
2705  return new BLong( warmode() );
2706  }
2707  break;
2708  }
2709  case MTH_GETCORPSE:
2710  {
2711  Core::UCorpse* corpse_obj =
2712  static_cast<Core::UCorpse*>( Core::system_find_item( last_corpse ) );
2713  if ( corpse_obj != nullptr && !corpse_obj->orphan() )
2714  return new Module::EItemRefObjImp( corpse_obj );
2715  else
2716  return new BError( "No corpse was found." );
2717  break;
2718  }
2719  case MTH_SET_SWINGTIMER:
2720  {
2721  int time;
2722  if ( !ex.hasParams( 1 ) )
2723  return new BError( "Not enough parameters" );
2724  if ( ex.getParam( 0, time ) )
2725  {
2726  if ( time < 0 )
2727  return new BError( "Time must be >= 0" );
2728  Core::polclock_t clocks;
2729  clocks = ( time * Core::POLCLOCKS_PER_SEC ) / 1000;
2730  return new BLong( manual_set_swing_timer( clocks ) ? 1 : 0 );
2731  }
2732  break;
2733  }
2734  case MTH_ATTACK_ONCE:
2735  {
2736  Character* chr;
2737  if ( ex.hasParams( 1 ) )
2738  {
2739  if ( getCharacterParam( ex, 0, chr ) )
2740  {
2741  if ( dead() )
2742  return new BError( "Character is dead" );
2743  if ( is_attackable( chr ) )
2744  attack( chr );
2745  else
2746  return new BError( "Opponent is not attackable" );
2747  }
2748  else
2749  return new BError( "Invalid parameter type" );
2750  }
2751  else
2752  {
2753  chr = get_attackable_opponent();
2754  if ( chr != nullptr )
2755  {
2756  if ( !dead() )
2757  attack( chr );
2758  else
2759  return new BError( "Character is dead" );
2760  }
2761  else
2762  return new BError( "No opponent" );
2763  }
2764  return new BLong( 1 );
2765  break;
2766  }
2767  case MTH_KILL:
2768  if ( ex.hasParams( 1 ) )
2769  {
2770  Character* chr;
2771  if ( getCharacterParam( ex, 0, chr ) )
2772  chr->repsys_on_damage( this );
2773  }
2774  if ( dead() )
2775  return new BError( "That is already dead!" );
2776 
2777  die();
2778  return new BLong( 1 );
2779  break;
2780  case MTH_SETFACING:
2781  {
2782  int flags = 0;
2783  Core::UFACING i_facing;
2784 
2785  if ( ex.hasParams( 2 ) && !ex.getParam( 1, flags, 0, 1 ) )
2786  return new BError( "Invalid flags for parameter 1" );
2787 
2788  BObjectImp* param0 = ex.getParamImp( 0 );
2789  if ( param0->isa( BObjectImp::OTString ) )
2790  {
2791  const char* szDir = ex.paramAsString( 0 );
2792  if ( DecodeFacing( szDir, i_facing ) == false )
2793  return new BError( "Invalid string for parameter 0" );
2794  }
2795  else if ( param0->isa( BObjectImp::OTLong ) )
2796  {
2797  BLong* blong = static_cast<BLong*>( param0 );
2798  i_facing = static_cast<Core::UFACING>( blong->value() & PKTIN_02_FACING_MASK );
2799  }
2800  else
2801  return new BError( "Invalid type for parameter 0" );
2802 
2803  if ( !face( i_facing, flags ) )
2804  return new BLong( 0 );
2805 
2806  on_facing_changed();
2807  return new BLong( 1 );
2808  break;
2809  }
2810  case MTH_COMPAREVERSION:
2811  if ( client != nullptr )
2812  {
2813  if ( !ex.hasParams( 1 ) )
2814  return new BError( "Not enough parameters" );
2815  const String* pstr;
2816  if ( ex.getStringParam( 0, pstr ) )
2817  return new BLong( client->compareVersion( pstr->getStringRep() ) ? 1 : 0 );
2818  else
2819  return new BError( "Invalid parameter type" );
2820  }
2821  else
2822  return new BError( "No client attached" );
2823  break;
2824  case MTH_SETAGGRESSORTO:
2825  if ( ex.hasParams( 1 ) )
2826  {
2827  Character* chr;
2828  if ( getCharacterParam( ex, 0, chr ) )
2829  {
2830  // make_aggressor_to handles the updating
2831  this->make_aggressor_to( chr );
2832  return new BLong( 1 );
2833  }
2834  else
2835  return new BError( "Invalid parameter type" );
2836  }
2837  else
2838  return new BError( "Not enough parameters" );
2839  break;
2841  if ( ex.hasParams( 1 ) )
2842  {
2843  Character* chr;
2844  if ( getCharacterParam( ex, 0, chr ) )
2845  {
2846  // make_lawfullydamaged_to handled the updating
2847  this->make_lawfullydamaged_to( chr );
2848  return new BLong( 1 );
2849  }
2850  else
2851  return new BError( "Invalid parameter type" );
2852  }
2853  else
2854  return new BError( "Not enough parameters" );
2855  break;
2856  case MTH_CLEARAGGRESSORTO:
2857  if ( ex.hasParams( 1 ) )
2858  {
2859  Character* chr;
2860  if ( getCharacterParam( ex, 0, chr ) )
2861  {
2862  this->remove_as_aggressor_to( chr );
2863  return new BLong( 1 );
2864  }
2865  else
2866  return new BError( "Invalid parameter type" );
2867  }
2868  else
2869  return new BError( "Not enough parameters" );
2870  break;
2872  if ( ex.hasParams( 1 ) )
2873  {
2874  Character* chr;
2875  if ( getCharacterParam( ex, 0, chr ) )
2876  {
2877  this->remove_as_lawful_damager( chr );
2878  return new BLong( 1 );
2879  }
2880  else
2881  return new BError( "Invalid parameter type" );
2882  }
2883  else
2884  return new BError( "Not enough parameters" );
2885  break;
2886  case MTH_DEAF:
2887  {
2888  int duration;
2889  if ( !ex.hasParams( 1 ) )
2890  return new BError( "Not enough parameters" );
2891  if ( ex.getParam( 0, duration ) )
2892  {
2893  set_dirty();
2894  if ( duration == -1 )
2895  {
2896  deafened_until( ~0u );
2897  return new BLong( -1 );
2898  }
2899  else if ( duration == 0 )
2900  deafened_until( 0 );
2901  else
2902  deafened_until( Core::read_gameclock() + duration );
2903  return new BLong( deafened_until() );
2904  }
2905  break;
2906  }
2908  {
2909  int duration;
2910  if ( !ex.hasParams( 1 ) )
2911  return new BError( "Not enough parameters" );
2912  if ( ex.getParam( 0, duration ) )
2913  {
2914  if ( duration < 0 )
2915  return new BError( "Duration must be >= 0" );
2916  disable_skills_until( Core::poltime() + duration );
2917  return new BLong( static_cast<int>( disable_skills_until() ) );
2918  }
2919  break;
2920  }
2921  case MTH_ADD_BUFF:
2922  {
2923  u16 icon;
2924  u16 duration;
2925  u32 cl_name;
2926  u32 cl_descr;
2927  ObjArray* oText;
2928 
2929  if ( !ex.hasParams( 5 ) )
2930  return new BError( "Not enough parameters" );
2931  if ( ex.getParam( 0, icon ) && ex.getParam( 1, duration ) && ex.getParam( 2, cl_name ) &&
2932  ex.getParam( 3, cl_descr ) && ex.getObjArrayParam( 4, oText ) )
2933  {
2934  if ( !( icon && cl_name && cl_descr ) )
2935  return new BError( "Invalid parameters" );
2936 
2937  // Retrieve and validate the unicode text as an array of u16
2938  if ( oText->ref_arr.size() > SPEECH_MAX_LEN )
2939  return new BError( "Unicode array exceeds maximum size." );
2940  u16 cltext[( SPEECH_MAX_LEN + 1 )];
2941  size_t textlen = oText->ref_arr.size();
2942  if ( !Core::convertArrayToUC( oText, cltext, textlen, false ) )
2943  return new BError( "Invalid value in Unicode array." );
2944 
2945  // Now convert it into a vector of u32
2946  // TODO: use a unicode string class or something bettwer when it will be ready
2947  std::vector<u32> arguments;
2948  arguments.reserve( textlen );
2949  for ( size_t i = 0; i < textlen; i++ )
2950  arguments.insert( arguments.end(), cltext[i] );
2951 
2952  addBuff( icon, duration, cl_name, cl_descr, arguments );
2953  return new BLong( 1 );
2954  }
2955  break;
2956  }
2957  case MTH_CLEAR_BUFFS:
2958  {
2959  clearBuffs();
2960 
2961  return new BLong( 1 );
2962  break;
2963  }
2964  case MTH_DEL_BUFF:
2965  {
2966  u16 icon;
2967 
2968  if ( !ex.hasParams( 1 ) )
2969  return new BError( "Not enough parameters" );
2970  if ( ex.getParam( 0, icon ) )
2971  {
2972  if ( !icon )
2973  return new BError( "Invalid parameter" );
2974 
2975  if ( !delBuff( icon ) )
2976  return new BError( "Buff not found" );
2977 
2978  return new BLong( 1 );
2979  }
2980  break;
2981  }
2982  default:
2983  return nullptr;
2984  }
2985  return new BError( "Invalid parameter type" );
2986 }
2987 
2988 
2989 BObjectImp* Character::script_method( const char* methodname, Executor& ex )
2990 {
2991  ObjMethod* objmethod = getKnownObjMethod( methodname );
2992  if ( objmethod != nullptr )
2993  return this->script_method_id( objmethod->id, ex );
2994  else
2995  return nullptr;
2996 }
2997 
2998 BObjectImp* Character::custom_script_method( const char* methodname, Executor& ex )
2999 {
3000  if ( Core::networkManager.uoclient_general.method_script != nullptr )
3001  {
3002  unsigned PC;
3003  if ( Core::networkManager.uoclient_general.method_script->FindExportedFunction(
3004  methodname, static_cast<unsigned int>( ex.numParams() + 1 ), PC ) )
3005  return Core::networkManager.uoclient_general.method_script->call( PC, make_ref(),
3006  ex.fparams );
3007  }
3008  return nullptr;
3009 }
3010 
3012 {
3013  std::unique_ptr<ObjArray> arr( new ObjArray );
3014 
3015  for ( ReportableList::const_iterator itr = reportable_.begin(), end = reportable_.end();
3016  itr != end; ++itr )
3017  {
3018  const reportable_t& rt = ( *itr );
3019 
3020  std::unique_ptr<BObjectImp> kmember( nullptr );
3021  Character* killer = Core::system_find_mobile( rt.serial );
3022  if ( killer )
3023  kmember.reset( new Module::EOfflineCharacterRefObjImp( killer ) );
3024  else
3025  kmember.reset( new BError( "Mobile not found" ) );
3026 
3027  std::unique_ptr<BStruct> elem( new BStruct );
3028  elem->addMember( "serial", new BLong( rt.serial ) );
3029  elem->addMember( "killer", kmember.release() );
3030  elem->addMember( "gameclock", new BLong( rt.polclock ) );
3031 
3032  arr->addElement( elem.release() );
3033  }
3034  return arr.release();
3035 }
3036 
3038 {
3039  std::unique_ptr<ObjArray> arr( new ObjArray );
3040 
3041  for ( Character::MobileCont::const_iterator itr = aggressor_to_.begin(),
3042  end = aggressor_to_.end();
3043  itr != end; ++itr )
3044  {
3045  std::unique_ptr<BObjectImp> member( nullptr );
3046  Character* chr = Core::system_find_mobile( ( *itr ).first->serial );
3047  if ( chr )
3048  member.reset( new Module::EOfflineCharacterRefObjImp( chr ) );
3049  else
3050  member.reset( new BError( "Mobile not found" ) );
3051 
3052  std::unique_ptr<BStruct> elem( new BStruct );
3053  elem->addMember( "serial", new BLong( ( *itr ).first->serial ) );
3054  elem->addMember( "ref", member.release() );
3055  elem->addMember(
3056  "seconds", new BLong( ( ( *itr ).second - Core::polclock() ) / Core::POLCLOCKS_PER_SEC ) );
3057 
3058  arr->addElement( elem.release() );
3059  }
3060  return arr.release();
3061 }
3062 
3064 {
3065  std::unique_ptr<ObjArray> arr( new ObjArray );
3066 
3067  for ( Character::MobileCont::const_iterator itr = lawfully_damaged_.begin(),
3068  end = lawfully_damaged_.end();
3069  itr != end; ++itr )
3070  {
3071  std::unique_ptr<BObjectImp> member( nullptr );
3072  Character* chr = Core::system_find_mobile( ( *itr ).first->serial );
3073  if ( chr )
3074  member.reset( new Module::EOfflineCharacterRefObjImp( chr ) );
3075  else
3076  member.reset( new BError( "Mobile not found" ) );
3077 
3078  std::unique_ptr<BStruct> elem( new BStruct );
3079  elem->addMember( "serial", new BLong( ( *itr ).first->serial ) );
3080  elem->addMember( "ref", member.release() );
3081  elem->addMember(
3082  "seconds", new BLong( ( ( *itr ).second - Core::polclock() ) / Core::POLCLOCKS_PER_SEC ) );
3083 
3084  arr->addElement( elem.release() );
3085  }
3086  return arr.release();
3087 }
3088 
3090 {
3091  BObjectImp* imp = base::get_script_member_id( id );
3092  if ( imp != nullptr )
3093  return imp;
3094 
3095  switch ( id )
3096  {
3097  case MBR_SCRIPT:
3098  return new String( script );
3099  break;
3100  case MBR_NPCTEMPLATE:
3101  return new String( template_name );
3102  break;
3103  case MBR_MASTER:
3104  {
3105  Character* master = master_.get();
3106  if ( master != nullptr && !master->orphan() )
3107  return new Module::EOfflineCharacterRefObjImp( master );
3108  else
3109  return new BLong( 0 );
3110  break;
3111  }
3112 
3113  case MBR_PROCESS:
3114  if ( ex )
3115  return new Core::ScriptExObjImp( ex );
3116  else
3117  return new BError( "No script running" );
3118  break;
3119 
3120  case MBR_EVENTMASK:
3121  if ( ex )
3122  return new BLong( ex->eventmask );
3123  else
3124  return new BError( "No script running" );
3125  break;
3126 
3127  case MBR_SPEECH_COLOR:
3128  return new BLong( speech_color() );
3129  break;
3130  case MBR_SPEECH_FONT:
3131  return new BLong( speech_font() );
3132  break;
3133  case MBR_USE_ADJUSTMENTS:
3134  return new BLong( use_adjustments() ? 1 : 0 );
3135  break;
3136  case MBR_RUN_SPEED:
3137  return new BLong( run_speed );
3138  break;
3139  case MBR_ALIGNMENT:
3140  return new BLong( this->template_.alignment );
3141  break;
3142  case MBR_SAVEONEXIT:
3143  return new BLong( saveonexit() );
3144  break;
3145  case MBR_NO_DROP_EXCEPTION:
3146  return new BLong( no_drop_exception() );
3147  default:
3148  return nullptr;
3149  }
3150 }
3151 
3152 BObjectImp* NPC::get_script_member( const char* membername ) const
3153 {
3154  ObjMember* objmember = getKnownObjMember( membername );
3155  if ( objmember != nullptr )
3156  return this->get_script_member_id( objmember->id );
3157  else
3158  return nullptr;
3159 }
3160 
3161 BObjectImp* NPC::set_script_member_id( const int id, const std::string& value )
3162 {
3163  BObjectImp* imp = base::set_script_member_id( id, value );
3164  if ( imp != nullptr )
3165  return imp;
3166  switch ( id )
3167  {
3168  case MBR_SCRIPT:
3169  return new String( script = value );
3170  default:
3171  return nullptr;
3172  }
3173 }
3174 
3175 BObjectImp* NPC::set_script_member( const char* membername, const std::string& value )
3176 {
3177  ObjMember* objmember = getKnownObjMember( membername );
3178  if ( objmember != nullptr )
3179  return this->set_script_member_id( objmember->id, value );
3180  else
3181  return nullptr;
3182 }
3183 
3184 BObjectImp* NPC::set_script_member_id( const int id, int value )
3185 {
3186  BObjectImp* imp = base::set_script_member_id( id, value );
3187  if ( imp != nullptr )
3188  return imp;
3189  switch ( id )
3190  {
3191  case MBR_SPEECH_COLOR:
3192  speech_color( static_cast<unsigned short>( value ) );
3193  return new BLong( speech_color() );
3194  case MBR_SPEECH_FONT:
3195  speech_font( static_cast<unsigned short>( value ) );
3196  return new BLong( speech_font() );
3197  case MBR_USE_ADJUSTMENTS:
3198  use_adjustments( value ? true : false );
3199  return new BLong( use_adjustments() );
3200  case MBR_RUN_SPEED:
3201  return new BLong( run_speed = static_cast<unsigned short>( value ) );
3202  case MBR_SAVEONEXIT:
3203  saveonexit( value ? true : false );
3204  return new BLong( saveonexit() );
3205  case MBR_NO_DROP_EXCEPTION:
3206  no_drop_exception( value ? true : false );
3207  return new BLong( no_drop_exception() );
3208  default:
3209  return nullptr;
3210  }
3211 }
3212 BObjectImp* NPC::set_script_member( const char* membername, int value )
3213 {
3214  ObjMember* objmember = getKnownObjMember( membername );
3215  if ( objmember != nullptr )
3216  return this->set_script_member_id( objmember->id, value );
3217  else
3218  return nullptr;
3219 }
3220 
3221 BObjectImp* NPC::script_method_id( const int id, Executor& executor )
3222 {
3223  BObjectImp* imp = base::script_method_id( id, executor );
3224  if ( imp != nullptr )
3225  return imp;
3226 
3227  switch ( id )
3228  {
3229  case MTH_SETMASTER:
3230  {
3231  if ( executor.numParams() != 1 )
3232  return new BError( "Not enough parameters" );
3233  Character* chr;
3234  set_dirty();
3235  if ( getCharacterParam( executor, 0, chr ) )
3236  {
3237  master_.set( chr );
3238  return new BLong( 1 );
3239  }
3240  else
3241  {
3242  master_.clear();
3243  return new BLong( 0 );
3244  }
3245  break;
3246  }
3247  default:
3248  return nullptr;
3249  }
3250 }
3251 
3252 BObjectImp* NPC::script_method( const char* methodname, Executor& executor )
3253 {
3254  ObjMethod* objmethod = getKnownObjMethod( methodname );
3255  if ( objmethod != nullptr )
3256  return this->script_method_id( objmethod->id, executor );
3257  else
3258  return nullptr;
3259 }
3260 
3261 BObjectImp* NPC::custom_script_method( const char* methodname, Executor& executor )
3262 {
3263  if ( template_.method_script != nullptr )
3264  {
3265  unsigned PC;
3266  if ( template_.method_script->FindExportedFunction(
3267  methodname, static_cast<unsigned int>( executor.numParams() + 1 ), PC ) )
3268  return template_.method_script->call( PC, make_ref(), executor.fparams );
3269  }
3270  return nullptr;
3271 }
3272 } // namespace Mobile
3273 namespace Core
3274 {
3275 using namespace Bscript;
3276 
3278 {
3280  if ( imp != nullptr )
3281  return imp;
3282 
3283  switch ( id )
3284  {
3285  case MBR_LOCKED:
3286  return new BLong( locked() ? 1 : 0 );
3287  break;
3288  default:
3289  return nullptr;
3290  }
3291 }
3292 
3293 BObjectImp* ULockable::get_script_member( const char* membername ) const
3294 {
3295  ObjMember* objmember = getKnownObjMember( membername );
3296  if ( objmember != nullptr )
3297  return this->get_script_member_id( objmember->id );
3298  else
3299  return nullptr;
3300 }
3301 
3302 BObjectImp* ULockable::set_script_member_id( const int id, int value )
3303 {
3304  BObjectImp* imp = Item::set_script_member_id( id, value );
3305  if ( imp != nullptr )
3306  return imp;
3307  switch ( id )
3308  {
3309  case MBR_LOCKED:
3310  locked( value ? true : false );
3311  return new BLong( locked() );
3312  default:
3313  return nullptr;
3314  }
3315 }
3316 
3317 BObjectImp* ULockable::set_script_member( const char* membername, int value )
3318 {
3319  ObjMember* objmember = getKnownObjMember( membername );
3320  if ( objmember != nullptr )
3321  return this->set_script_member_id( objmember->id, value );
3322  else
3323  return nullptr;
3324 }
3325 
3327 {
3328  BObjectImp* imp = base::get_script_member_id( id );
3329  if ( imp != nullptr )
3330  return imp;
3331 
3332  switch ( id )
3333  {
3334  case MBR_MAX_ITEMS_MOD:
3335  return new BLong( max_items_mod() );
3336  break;
3337  case MBR_MAX_WEIGHT_MOD:
3338  return new BLong( max_weight_mod() );
3339  break;
3340  case MBR_MAX_SLOTS_MOD:
3341  return new BLong( max_slots_mod() );
3342  break;
3343  case MBR_NO_DROP_EXCEPTION:
3344  return new BLong( no_drop_exception() );
3345  default:
3346  return nullptr;
3347  }
3348 }
3349 
3350 BObjectImp* UContainer::get_script_member( const char* membername ) const
3351 {
3352  ObjMember* objmember = getKnownObjMember( membername );
3353  if ( objmember != nullptr )
3354  return this->get_script_member_id( objmember->id );
3355  else
3356  return nullptr;
3357 }
3358 
3360 {
3361  BObjectImp* imp = base::set_script_member_id( id, value );
3362  if ( imp != nullptr )
3363  return imp;
3364  switch ( id )
3365  {
3366  case MBR_MAX_ITEMS_MOD:
3367  max_items_mod( static_cast<s16>( value ) );
3368  break;
3369  case MBR_MAX_WEIGHT_MOD:
3370  max_weight_mod( static_cast<s16>( value ) );
3371  break;
3372  case MBR_MAX_SLOTS_MOD:
3373  max_slots_mod( static_cast<s8>( value ) );
3374  break;
3375  case MBR_NO_DROP_EXCEPTION:
3376  no_drop_exception( value ? true : false );
3377  return new BLong( no_drop_exception() );
3378  default:
3379  return nullptr;
3380  }
3381  return new BLong( value );
3382 }
3383 
3384 BObjectImp* UContainer::set_script_member( const char* membername, int value )
3385 {
3386  ObjMember* objmember = getKnownObjMember( membername );
3387  if ( objmember != nullptr )
3388  return this->set_script_member_id( objmember->id, value );
3389  else
3390  return nullptr;
3391 }
3392 
3394 {
3395  BObjectImp* imp = base::get_script_member_id( id );
3396  if ( imp != nullptr )
3397  return imp;
3398 
3399  switch ( id )
3400  {
3401  case MBR_CORPSETYPE:
3402  return new BLong( corpsetype );
3403  break;
3404  case MBR_OWNERSERIAL:
3405  return new BLong( ownerserial );
3406  break;
3407  default:
3408  return nullptr;
3409  }
3410 }
3411 
3412 BObjectImp* UCorpse::get_script_member( const char* membername ) const
3413 {
3414  ObjMember* objmember = getKnownObjMember( membername );
3415  if ( objmember != nullptr )
3416  return this->get_script_member_id( objmember->id );
3417  else
3418  return nullptr;
3419 }
3420 
3422 {
3423  BObjectImp* imp = base::script_method_id( id, ex );
3424  if ( imp != nullptr )
3425  return imp;
3426 
3427  switch ( id )
3428  {
3429  case MTH_HASSPELL:
3430  {
3431  int sid;
3432  if ( !ex.hasParams( 1 ) )
3433  return new BError( "Not enough parameters" );
3434  if ( ex.getParam( 0, sid ) )
3435  {
3436  if ( sid <= 0 )
3437  return new BError( "SpellID must be >= 1" );
3438  if ( this->has_spellid( static_cast<unsigned int>( sid ) ) )
3439  return new BLong( 1 );
3440  else
3441  return new BLong( 0 );
3442  }
3443  break;
3444  }
3445  case MTH_SPELLS:
3446  {
3447  std::unique_ptr<ObjArray> arr( new ObjArray );
3448  for ( u16 i = 0; i < 64; ++i )
3449  {
3450  unsigned int sid;
3451 
3452  // Check for Mysticism spells here
3453  if ( this->spell_school == 3 )
3454  sid = 678 + i;
3455  else
3456  sid = this->spell_school * 100 + i + 1;
3457 
3458  if ( this->has_spellid( sid ) )
3459  arr->addElement( new BLong( sid ) );
3460  }
3461  return arr.release();
3462  break;
3463  }
3464  case MTH_REMOVESPELL:
3465  {
3466  int sid;
3467  if ( !ex.hasParams( 1 ) )
3468  return new BError( "Not enough parameters" );
3469  if ( ex.getParam( 0, sid ) )
3470  {
3471  if ( sid <= 0 )
3472  return new BError( "SpellID must be >= 1" );
3473  if ( this->remove_spellid( static_cast<unsigned int>( sid ) ) )
3474  return new BLong( 1 );
3475  else
3476  return new BLong( 0 );
3477  }
3478  break;
3479  }
3480  case MTH_ADDSPELL:
3481  {
3482  int sid;
3483  if ( !ex.hasParams( 1 ) )
3484  return new BError( "Not enough parameters" );
3485  if ( ex.getParam( 0, sid ) )
3486  {
3487  if ( sid <= 0 )
3488  return new BError( "SpellID must be >= 1" );
3489  if ( this->add_spellid( static_cast<unsigned int>( sid ) ) )
3490  return new BLong( 1 );
3491  else
3492  return new BLong( 0 );
3493  }
3494  break;
3495  }
3496 
3497  default:
3498  return nullptr;
3499  }
3500  return new BError( "Invalid parameter type" );
3501 }
3502 
3503 BObjectImp* Spellbook::script_method( const char* methodname, Executor& ex )
3504 {
3505  ObjMethod* objmethod = getKnownObjMethod( methodname );
3506  if ( objmethod != nullptr )
3507  return this->script_method_id( objmethod->id, ex );
3508  else
3509  return nullptr;
3510 }
3511 } // namespace Core
3512 namespace Multi
3513 {
3514 using namespace Bscript;
3515 
3516 BObjectImp* UBoat::make_ref()
3517 {
3518  return new Module::EUBoatRefObjImp( this );
3519 }
3520 
3521 BObjectImp* UMulti::make_ref()
3522 {
3523  return new Module::EMultiRefObjImp( this );
3524 }
3525 
3526 BObjectImp* UBoat::get_script_member_id( const int id ) const
3527 {
3528  BObjectImp* imp = base::get_script_member_id( id );
3529  if ( imp != nullptr )
3530  return imp;
3531 
3532  switch ( id )
3533  {
3534  case MBR_TILLERMAN:
3535  {
3536  Item* cp = tillerman;
3537  if ( cp != nullptr )
3538  return new Module::EItemRefObjImp( cp );
3539  else
3540  return new BError( std::string( "This ship doesn't have that component" ) );
3541  break;
3542  }
3543  case MBR_PORTPLANK:
3544  {
3545  Item* cp = portplank;
3546  if ( cp != nullptr )
3547  return new Module::EItemRefObjImp( cp );
3548  else
3549  return new BError( std::string( "This ship doesn't have that component" ) );
3550  break;
3551  }
3552  case MBR_STARBOARDPLANK:
3553  {
3554  Item* cp = starboardplank;
3555  if ( cp != nullptr )
3556  return new Module::EItemRefObjImp( cp );
3557  else
3558  return new BError( std::string( "This ship doesn't have that component" ) );
3559  break;
3560  }
3561  case MBR_HOLD:
3562  {
3563  Item* cp = hold;
3564  if ( cp != nullptr )
3565  return new Module::EItemRefObjImp( cp );
3566  else
3567  return new BError( std::string( "This ship doesn't have that component" ) );
3568  break;
3569  }
3570  case MBR_ROPE:
3571  return component_list( COMPONENT_ROPE );
3572  break;
3573  case MBR_WHEEL:
3574  return component_list( COMPONENT_WHEEL );
3575  break;
3576  case MBR_HULL:
3577  return component_list( COMPONENT_HULL );
3578  break;
3579  case MBR_TILLER:
3580  return component_list( COMPONENT_TILLER );
3581  break;
3582  case MBR_RUDDER:
3583  return component_list( COMPONENT_RUDDER );
3584  break;
3585  case MBR_SAILS:
3586  return component_list( COMPONENT_SAILS );
3587  break;
3588  case MBR_STORAGE:
3589  return component_list( COMPONENT_STORAGE );
3590  break;
3591  case MBR_WEAPONSLOT:
3592  return component_list( COMPONENT_WEAPONSLOT );
3593  break;
3594  case MBR_COMPONENTS:
3595  return component_list( COMPONENT_ALL );
3596  break;
3597  case MBR_ITEMS:
3598  return items_list();
3599  break;
3600  case MBR_MOBILES:
3601  return mobiles_list();
3602  break;
3604  return new BLong( has_offline_mobiles() ? 1 : 0 );
3605  break;
3606  case MBR_MULTIID:
3607  return new BLong( multiid );
3608  break;
3609  default:
3610  return nullptr;
3611  }
3612 }
3613 
3614 BObjectImp* UBoat::get_script_member( const char* membername ) const
3615 {
3616  ObjMember* objmember = getKnownObjMember( membername );
3617  if ( objmember != nullptr )
3618  return this->get_script_member_id( objmember->id );
3619  else
3620  return nullptr;
3621 }
3622 
3623 BObjectImp* UBoat::script_method_id( const int id, Executor& ex )
3624 {
3625  BObjectImp* imp = base::script_method_id( id, ex );
3626  if ( imp != nullptr )
3627  return imp;
3628 
3629  switch ( id )
3630  {
3632  {
3633  Core::xcoord newx;
3634  Core::ycoord newy;
3635  Core::zcoord newz;
3636 
3637  if ( ex.numParams() == 3 )
3638  {
3639  if ( ex.getParam( 0, newx ) && ex.getParam( 1, newy ) &&
3640  ex.getParam( 2, newz, Core::ZCOORD_MIN, Core::ZCOORD_MAX ) )
3641  {
3642  if ( !realm->valid( newx, newy, newz ) )
3643  return new BError( "Coordinates are out of range" );
3644 
3645  set_dirty();
3646  move_offline_mobiles( newx, newy, newz, realm );
3647  return new BLong( 1 );
3648  }
3649  else
3650  return new BError( "Invalid parameter type" );
3651  }
3652  else
3653  {
3654  if ( ex.numParams() == 4 )
3655  {
3656  const String* strrealm;
3657  if ( ex.getParam( 0, newx ) && ex.getParam( 1, newy ) &&
3658  ex.getParam( 2, newz, Core::ZCOORD_MIN, Core::ZCOORD_MAX ) &&
3659  ex.getStringParam( 3, strrealm ) )
3660  {
3661  Realms::Realm* newrealm = Core::find_realm( strrealm->value() );
3662  if ( !newrealm )
3663  return new BError( "Realm not found" );
3664 
3665  if ( !newrealm->valid( newx, newy, newz ) )
3666  return new BError( "Coordinates are out of range" );
3667 
3668  set_dirty();
3669  move_offline_mobiles( newx, newy, newz, newrealm );
3670  return new BLong( 1 );
3671  }
3672  else
3673  return new BError( "Invalid parameter type" );
3674  }
3675  else
3676  return new BError( "Not enough parameters" );
3677  }
3678  break;
3679  }
3680  default:
3681  return nullptr;
3682  }
3683 }
3684 
3685 BObjectImp* UBoat::script_method( const char* methodname, Executor& ex )
3686 {
3687  ObjMethod* objmethod = getKnownObjMethod( methodname );
3688  if ( objmethod != nullptr )
3689  return this->script_method_id( objmethod->id, ex );
3690  else
3691  return nullptr;
3692 }
3693 
3694 BObjectImp* UPlank::get_script_member_id( const int id ) const
3695 {
3696  switch ( id )
3697  {
3698  case MBR_MULTI:
3699  if ( boat_.get() )
3700  return new Module::EUBoatRefObjImp( boat_.get() );
3701  else
3702  return new BError( "No boat attached" );
3703  break;
3704  }
3705  return base::get_script_member_id( id );
3706 }
3707 
3708 /* UObject defines a 'multi' also, so we have to trap that here first */
3709 BObjectImp* UPlank::get_script_member( const char* membername ) const
3710 {
3711  ObjMember* objmember = getKnownObjMember( membername );
3712  if ( objmember != nullptr )
3713  return this->get_script_member_id( objmember->id );
3714  else
3715  return base::get_script_member( membername );
3716 }
3717 } // namespace Multi
3718 namespace Core
3719 {
3720 using namespace Bscript;
3721 
3723 {
3724  BObjectImp* imp = base::get_script_member_id( id );
3725  if ( imp != nullptr )
3726  return imp;
3727 
3728  switch ( id )
3729  {
3730  case MBR_XEAST:
3731  return new BLong( xeast );
3732  break;
3733  case MBR_XWEST:
3734  return new BLong( xwest );
3735  break;
3736  case MBR_YNORTH:
3737  return new BLong( ynorth );
3738  break;
3739  case MBR_YSOUTH:
3740  return new BLong( ysouth );
3741  break;
3742  case MBR_GUMPWIDTH:
3743  return new BLong( gumpwidth );
3744  break;
3745  case MBR_GUMPHEIGHT:
3746  return new BLong( gumpheight );
3747  break;
3748  case MBR_FACETID:
3749  return new BLong( facetid );
3750  break;
3751  case MBR_EDITABLE:
3752  return new BLong( editable ? 1 : 0 );
3753  break;
3754  default:
3755  return nullptr;
3756  }
3757 }
3758 
3759 BObjectImp* Map::get_script_member( const char* membername ) const
3760 {
3761  ObjMember* objmember = getKnownObjMember( membername );
3762  if ( objmember != nullptr )
3763  return this->get_script_member_id( objmember->id );
3764  else
3765  return nullptr;
3766 }
3767 
3768 BObjectImp* Map::set_script_member_id( const int id, int value )
3769 {
3770  BObjectImp* imp = base::set_script_member_id( id, value );
3771  if ( imp != nullptr )
3772  return imp;
3773  switch ( id )
3774  {
3775  case MBR_XEAST:
3776  return new BLong( xeast = static_cast<unsigned short>( value ) );
3777  case MBR_XWEST:
3778  return new BLong( xwest = static_cast<unsigned short>( value ) );
3779  case MBR_YNORTH:
3780  return new BLong( ynorth = static_cast<unsigned short>( value ) );
3781  case MBR_YSOUTH:
3782  return new BLong( ysouth = static_cast<unsigned short>( value ) );
3783  case MBR_GUMPWIDTH:
3784  return new BLong( gumpwidth = static_cast<unsigned short>( value ) );
3785  case MBR_GUMPHEIGHT:
3786  return new BLong( gumpheight = static_cast<unsigned short>( value ) );
3787  case MBR_FACETID:
3788  return new BLong( facetid = static_cast<unsigned short>( value ) );
3789  case MBR_EDITABLE:
3790  return new BLong( editable = value ? true : false );
3791  default:
3792  return nullptr;
3793  }
3794 }
3795 BObjectImp* Map::set_script_member( const char* membername, int value )
3796 {
3797  ObjMember* objmember = getKnownObjMember( membername );
3798  if ( objmember != nullptr )
3799  return this->set_script_member_id( objmember->id, value );
3800  else
3801  return nullptr;
3802 }
3803 
3805 {
3806  switch ( id )
3807  {
3808  case MTH_ISA:
3809  {
3810  if ( !ex.hasParams( 1 ) )
3811  return new BError( "Not enough parameters" );
3812  int isatype;
3813  if ( ex.getParam( 0, isatype ) )
3814  return new BLong( script_isa( static_cast<unsigned>( isatype ) ) );
3815  break;
3816  }
3817  case MTH_SET_MEMBER:
3818  {
3819  if ( !ex.hasParams( 2 ) )
3820  return new BError( "Not enough parameters" );
3821  BObjectImp* objimp;
3822  const String* mname;
3823  if ( ex.getStringParam( 0, mname ) && ( objimp = ex.getParamImp( 1 ) ) != nullptr )
3824  {
3825  BObjectImp* ret;
3826  if ( objimp->isa( BObjectImp::OTLong ) )
3827  {
3828  BLong* lng = static_cast<BLong*>( objimp );
3829  ret = set_script_member( mname->value().c_str(), lng->value() );
3830  }
3831  else if ( objimp->isa( BObjectImp::OTDouble ) )
3832  {
3833  Double* dbl = static_cast<Double*>( objimp );
3834  ret = set_script_member_double( mname->value().c_str(), dbl->value() );
3835  }
3836  else if ( objimp->isa( BObjectImp::OTString ) )
3837  {
3838  String* str = static_cast<String*>( objimp );
3839  ret = set_script_member( mname->value().c_str(), str->value() );
3840  }
3841  else
3842  return new BError( "Invalid value type" );
3843 
3844  if ( ret != nullptr )
3845  return ret;
3846  else
3847  {
3848  std::string message = std::string( "Member " ) + std::string( mname->value() ) +
3849  std::string( " not found on that object" );
3850  return new BError( message );
3851  }
3852  }
3853  break;
3854  }
3855  case MTH_GET_MEMBER:
3856  {
3857  if ( !ex.hasParams( 1 ) )
3858  return new BError( "Not enough parameters" );
3859 
3860  const String* mname;
3861  if ( ex.getStringParam( 0, mname ) )
3862  {
3863  BObjectImp* ret = get_script_member( mname->value().c_str() );
3864  if ( ret != nullptr )
3865  return ret;
3866  else
3867  {
3868  std::string message = std::string( "Member " ) + std::string( mname->value() ) +
3869  std::string( " not found on that object" );
3870  return new BError( message );
3871  }
3872  }
3873  break;
3874  }
3875  default:
3876  {
3877  bool changed = false;
3878  BObjectImp* imp = CallPropertyListMethod_id( proplist_, id, ex, changed );
3879  if ( changed )
3880  set_dirty();
3881  return imp;
3882  }
3883  }
3884  return new BError( "Invalid parameter type" );
3885 }
3886 
3887 
3888 BObjectImp* UObject::script_method( const char* methodname, Executor& ex )
3889 {
3890  ObjMethod* objmethod = getKnownObjMethod( methodname );
3891  if ( objmethod != nullptr )
3892  return this->script_method_id( objmethod->id, ex );
3893  else
3894  {
3895  bool changed = false;
3896  BObjectImp* imp = CallPropertyListMethod( proplist_, methodname, ex, changed );
3897  if ( changed )
3898  set_dirty();
3899 
3900  return imp;
3901  }
3902 }
3903 
3904 BObjectImp* UObject::custom_script_method( const char* methodname, Executor& ex )
3905 {
3906  ObjMethod* objmethod = getKnownObjMethod( methodname );
3907  if ( objmethod != nullptr )
3908  return this->script_method_id( objmethod->id, ex );
3909  else
3910  return nullptr;
3911 }
3912 
3914 {
3916  if ( imp != nullptr )
3917  return imp;
3918 
3919  switch ( id )
3920  {
3921  case MBR_ISOPEN:
3922  return new BLong( is_open() ? 1 : 0 );
3923  break;
3924  default:
3925  return nullptr;
3926  }
3927 }
3928 
3929 BObjectImp* UDoor::get_script_member( const char* membername ) const
3930 {
3931  ObjMember* objmember = getKnownObjMember( membername );
3932  if ( objmember != nullptr )
3933  return this->get_script_member_id( objmember->id );
3934  else
3935  return nullptr;
3936 }
3937 
3939 {
3940  BObjectImp* imp = base::script_method_id( id, ex );
3941  if ( imp != nullptr )
3942  return imp;
3943 
3944  switch ( id )
3945  {
3946  case MTH_OPEN:
3947  open();
3948  break;
3949  case MTH_CLOSE:
3950  close();
3951  break;
3952  case MTH_TOGGLE:
3953  toggle();
3954  break;
3955  default:
3956  return nullptr;
3957  }
3958  return new BLong( 1 );
3959 }
3960 
3961 BObjectImp* UDoor::script_method( const char* methodname, Executor& ex )
3962 {
3963  ObjMethod* objmethod = getKnownObjMethod( methodname );
3964  if ( objmethod != nullptr )
3965  return this->script_method_id( objmethod->id, ex );
3966  else
3967  return nullptr;
3968 }
3969 } // namespace Core
3970 namespace Items
3971 {
3972 using namespace Bscript;
3973 
3975 {
3977  if ( imp != nullptr )
3978  return imp;
3979 
3980  switch ( id )
3981  {
3982  case MBR_INTRINSIC:
3983  return new BLong( is_intrinsic() );
3984  break;
3985  default:
3986  return nullptr;
3987  }
3988 }
3989 BObjectImp* Equipment::get_script_member( const char* membername ) const
3990 {
3991  ObjMember* objmember = getKnownObjMember( membername );
3992  if ( objmember != nullptr )
3993  return this->get_script_member_id( objmember->id );
3994  else
3995  return nullptr;
3996 }
3997 
3998 BObjectImp* Equipment::set_script_member_id( const int id, int value )
3999 {
4000  BObjectImp* imp = Item::set_script_member_id( id, value );
4001  if ( imp != nullptr )
4002  return imp;
4003 
4004  return nullptr;
4005  /*
4006  switch(id)
4007  {
4008  default: return nullptr;
4009  }
4010  */
4011 }
4012 BObjectImp* Equipment::set_script_member( const char* membername, int value )
4013 {
4014  ObjMember* objmember = getKnownObjMember( membername );
4015  if ( objmember != nullptr )
4016  return this->set_script_member_id( objmember->id, value );
4017  else
4018  return nullptr;
4019 }
4020 
4022 {
4023  BObjectImp* imp = Item::set_script_member_id_double( id, value );
4024  if ( imp != nullptr )
4025  return imp;
4026 
4027  return nullptr;
4028  /*
4029  switch(id)
4030  {
4031  default: return nullptr;
4032  }
4033  */
4034 }
4035 BObjectImp* Equipment::set_script_member_double( const char* membername, double value )
4036 {
4037  ObjMember* objmember = getKnownObjMember( membername );
4038  if ( objmember != nullptr )
4039  return this->set_script_member_id_double( objmember->id, value );
4040  else
4041  return nullptr;
4042 }
4043 
4044 
4046 {
4048  if ( imp != nullptr )
4049  return imp;
4050 
4051  switch ( id )
4052  {
4053  case MBR_DMG_MOD:
4054  return new BLong( damage_mod() );
4055  break;
4056  case MBR_SPEED_MOD:
4057  return new BLong( speed_mod() );
4058  break;
4059  case MBR_ATTRIBUTE:
4060  return new String( attribute().name );
4061  break;
4062  case MBR_HITSCRIPT:
4063  return new String( hit_script_.relativename( tmpl->pkg ) );
4064  break;
4065  default:
4066  return nullptr;
4067  }
4068 }
4069 BObjectImp* UWeapon::get_script_member( const char* membername ) const
4070 {
4071  ObjMember* objmember = getKnownObjMember( membername );
4072  if ( objmember != nullptr )
4073  return this->get_script_member_id( objmember->id );
4074  else
4075  return nullptr;
4076 }
4077 
4078 BObjectImp* UWeapon::set_script_member_id( const int id, const std::string& value )
4079 {
4080  BObjectImp* imp = Item::set_script_member_id( id, value );
4081  if ( imp != nullptr )
4082  return imp;
4083 
4084  switch ( id )
4085  {
4086  case MBR_HITSCRIPT:
4087  set_hit_script( value );
4088  return new BLong( 1 );
4089  default:
4090  return nullptr;
4091  }
4092 }
4093 BObjectImp* UWeapon::set_script_member( const char* membername, const std::string& value )
4094 {
4095  ObjMember* objmember = getKnownObjMember( membername );
4096  if ( objmember != nullptr )
4097  return this->set_script_member_id( objmember->id, value );
4098  else
4099  return nullptr;
4100 }
4101 
4102 BObjectImp* UWeapon::set_script_member_id( const int id, int value )
4103 {
4104  if ( is_intrinsic() )
4105  return new BError( "Cannot alter an instrinsic NPC weapon member values" ); // executor won't
4106  // return this to
4107  // the script
4108  // currently.
4109 
4110  BObjectImp* imp = Equipment::set_script_member_id( id, value );
4111  if ( imp != nullptr )
4112  return imp;
4113 
4114  switch ( id )
4115  {
4116  case MBR_DMG_MOD:
4117  damage_mod( static_cast<s16>( value ) );
4118  break;
4119  case MBR_SPEED_MOD:
4120  speed_mod( static_cast<s16>( value ) );
4121  break;
4122  default:
4123  return nullptr;
4124  }
4125  return new BLong( value );
4126 }
4127 
4128 BObjectImp* UWeapon::set_script_member( const char* membername, int value )
4129 {
4130  ObjMember* objmember = getKnownObjMember( membername );
4131  if ( objmember != nullptr )
4132  return this->set_script_member_id( objmember->id, value );
4133  else
4134  return nullptr;
4135 }
4136 
4137 BObjectImp* UWeapon::set_script_member_id_double( const int id, double value )
4138 {
4139  if ( is_intrinsic() )
4140  return new BError( "Cannot alter an instrinsic NPC weapon member values" ); // executor won't
4141  // return this to
4142  // the script
4143  // currently.
4144  return base::set_script_member_id_double( id, value );
4145 }
4146 
4147 BObjectImp* UWeapon::set_script_member_double( const char* membername, double value )
4148 {
4149  ObjMember* objmember = getKnownObjMember( membername );
4150  if ( objmember != nullptr )
4151  return this->set_script_member_id_double( objmember->id, value );
4152  else
4153  return base::set_script_member_double( membername, value );
4154 }
4155 
4157 {
4159  if ( imp != nullptr )
4160  return imp;
4161 
4162  switch ( id )
4163  {
4164  case MBR_AR_MOD:
4165  return new BLong( ar_mod() );
4166  break;
4167  case MBR_AR:
4168  return new BLong( ar() );
4169  break;
4170  case MBR_AR_BASE:
4171  return new BLong( ar_base() );
4172  break;
4173  case MBR_ONHIT_SCRIPT:
4174  return new String( onhitscript_.relativename( tmpl->pkg ) );
4175  break;
4176  default:
4177  return nullptr;
4178  }
4179 }
4180 
4181 BObjectImp* UArmor::get_script_member( const char* membername ) const
4182 {
4183  ObjMember* objmember = getKnownObjMember( membername );
4184  if ( objmember != nullptr )
4185  return this->get_script_member_id( objmember->id );
4186  else
4187  return nullptr;
4188 }
4189 
4190 BObjectImp* UArmor::set_script_member_id( const int id, const std::string& value )
4191 {
4192  BObjectImp* imp = Item::set_script_member_id( id, value );
4193  if ( imp != nullptr )
4194  return imp;
4195  switch ( id )
4196  {
4197  case MBR_ONHIT_SCRIPT:
4198  set_onhitscript( value );
4199  return new BLong( 1 );
4200  default:
4201  return nullptr;
4202  }
4203 }
4204 
4205 BObjectImp* UArmor::set_script_member( const char* membername, const std::string& value )
4206 {
4207  ObjMember* objmember = getKnownObjMember( membername );
4208  if ( objmember != nullptr )
4209  return this->set_script_member_id( objmember->id, value );
4210  else
4211  return nullptr;
4212 }
4213 
4214 BObjectImp* UArmor::set_script_member_id( const int id, int value )
4215 {
4216  BObjectImp* imp = Equipment::set_script_member_id( id, value );
4217  if ( imp != nullptr )
4218  return imp;
4219 
4220  switch ( id )
4221  {
4222  case MBR_AR_MOD:
4223  this->ar_mod( static_cast<s16>( value ) );
4224  if ( container != nullptr )
4225  {
4226  if ( Core::IsCharacter( container->serial ) )
4227  {
4228  Mobile::Character* chr = chr_from_wornitems( container );
4229  if ( chr != nullptr )
4231  }
4232  }
4233  return new BLong( value );
4234  default:
4235  return nullptr;
4236  }
4237 }
4238 
4239 BObjectImp* UArmor::set_script_member( const char* membername, int value )
4240 {
4241  ObjMember* objmember = getKnownObjMember( membername );
4242  if ( objmember != nullptr )
4243  return this->set_script_member_id( objmember->id, value );
4244  else
4245  return nullptr;
4246 }
4247 } // namespace Items
4248 namespace Module
4249 {
4250 using namespace Bscript;
4251 
4252 const char* EClientRefObjImp::typeOf() const
4253 {
4254  return "ClientRef";
4255 }
4256 
4258 {
4259  return OTClientRef;
4260 }
4261 
4263 {
4264  if ( value().exists() )
4265  return value()->make_ref();
4266  else
4267  return new BError( "Client is disconnected" );
4268 }
4269 
4271 {
4272  return ( value().exists() && value()->isConnected() );
4273 }
4274 
4275 bool EClientRefObjImp::operator==( const BObjectImp& objimp ) const
4276 {
4277  if ( objimp.isa( BObjectImp::OTApplicObj ) )
4278  {
4279  const BApplicObjBase* aob =
4280  Clib::explicit_cast<const BApplicObjBase*, const BObjectImp*>( &objimp );
4281 
4282  if ( aob->object_type() == &eclientrefobjimp_type )
4283  {
4284  const EClientRefObjImp* clientref_imp =
4285  Clib::explicit_cast<const EClientRefObjImp*, const BApplicObjBase*>( aob );
4286 
4287  if ( clientref_imp->value().exists() && value().exists() &&
4288  ( clientref_imp->value()->chr != nullptr ) && ( value()->chr != nullptr ) )
4289  return ( clientref_imp->value()->chr->serial == value()->chr->serial );
4290  else
4291  return false;
4292  }
4293  else
4294  return false;
4295  }
4296  else if ( objimp.isa( Bscript::BObjectImp::OTBoolean ) )
4297  return isTrue() == static_cast<const Bscript::BBoolean&>( objimp ).isTrue();
4298  else
4299  return false;
4300 }
4301 
4303 {
4304  if ( ( !obj_.exists() ) || ( !obj_->isConnected() ) )
4305  return BObjectRef( new BError( "Client not ready or disconnected" ) );
4306 
4307  switch ( id )
4308  {
4309  case MBR_ACCTNAME:
4310  if ( obj_->acct != nullptr )
4311  return BObjectRef( new String( obj_->acct->name() ) );
4312  else
4313  return BObjectRef( new BError( "Not attached to an account" ) );
4314  break;
4315  case MBR_IP:
4316  return BObjectRef( new String( obj_->ipaddrAsString() ) );
4317  break;
4318  case MBR_CLIENTVERSION:
4319  return BObjectRef( new String( obj_->getversion() ) );
4320  break;
4322  {
4323  std::unique_ptr<BStruct> info( new BStruct );
4324  Network::VersionDetailStruct version = obj_->getversiondetail();
4325  info->addMember( "major", new BLong( version.major ) );
4326  info->addMember( "minor", new BLong( version.minor ) );
4327  info->addMember( "rev", new BLong( version.rev ) );
4328  info->addMember( "patch", new BLong( version.patch ) );
4329  return BObjectRef( info.release() );
4330  }
4331  break;
4332  case MBR_CLIENTINFO:
4333  return BObjectRef( obj_->getclientinfo() );
4334  break;
4335  case MBR_CLIENTTYPE:
4336  return BObjectRef( new BLong( obj_->ClientType ) );
4337  break;
4339  return BObjectRef( new BLong( obj_->UOExpansionFlagClient ) );
4340  break;
4341  case MBR_LAST_ACTIVITY_AT:
4342  return BObjectRef( new BLong( obj_->last_activity_at ) );
4343  break;
4344  case MBR_LAST_PACKET_AT:
4345  return BObjectRef( new BLong( obj_->last_packet_at ) );
4346  break;
4347  case MBR_PORT:
4348  return BObjectRef( new BLong( obj_->listen_port ) );
4349  break;
4350  }
4351 
4352  return base::get_member_id( id );
4353 }
4354 
4355 BObjectRef EClientRefObjImp::get_member( const char* membername )
4356 {
4357  if ( ( !obj_.exists() ) || ( !obj_->isConnected() ) )
4358  return BObjectRef( new BError( "Client not ready or disconnected" ) );
4359  ObjMember* objmember = getKnownObjMember( membername );
4360  if ( objmember != nullptr )
4361  return this->get_member_id( objmember->id );
4362  else
4363  return BObjectRef( UninitObject::create() );
4364 }
4365 
4366 BObjectRef EClientRefObjImp::set_member( const char* membername, BObjectImp* value, bool copy )
4367 {
4368  if ( !obj_.exists() || !obj_->isConnected() )
4369  return BObjectRef( new BError( "Client not ready or disconnected" ) );
4370  ObjMember* objmember = getKnownObjMember( membername );
4371  if ( objmember != nullptr )
4372  return this->set_member_id( objmember->id, value, copy );
4373  else
4374  return BObjectRef( UninitObject::create() );
4375 }
4376 
4377 BObjectRef EClientRefObjImp::set_member_id( const int /*id*/, BObjectImp* /*value*/, bool /*copy*/ )
4378 {
4379  if ( !obj_.exists() || !obj_->isConnected() )
4380  return BObjectRef( new BError( "Client not ready or disconnected" ) );
4381  return BObjectRef( UninitObject::create() );
4382 }
4383 
4384 BObjectImp* EClientRefObjImp::call_method( const char* methodname, Executor& ex )
4385 {
4386  if ( !obj_.exists() || !obj_->isConnected() )
4387  return new BError( "Client not ready or disconnected" );
4388  ObjMethod* objmethod = getKnownObjMethod( methodname );
4389  if ( objmethod != nullptr )
4390  return this->call_method_id( objmethod->id, ex );
4391  return nullptr;
4392 }
4393 
4394 BObjectImp* EClientRefObjImp::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
4395 {
4396  if ( !obj_.exists() || !obj_->isConnected() )
4397  return new BError( "Client not ready or disconnected" );
4398 
4399  switch ( id )
4400  {
4401  case MTH_COMPAREVERSION:
4402  {
4403  if ( !ex.hasParams( 1 ) )
4404  return new BError( "Not enough parameters" );
4405  const String* pstr;
4406  if ( ex.getStringParam( 0, pstr ) )
4407  return new BLong( obj_->compareVersion( pstr->getStringRep() ) ? 1 : 0 );
4408  return new BError( "Invalid parameter type" );
4409  }
4410  }
4411 
4412  return base::call_method_id( id, ex );
4413 }
4414 
4416 {
4417  addMember( "type", new BLong( type ) );
4418  addMember( "source", new Module::EOfflineCharacterRefObjImp( source ) );
4419 }
4420 
4421 SpeechEvent::SpeechEvent( Mobile::Character* speaker, const char* speech )
4422 {
4423  addMember( "type", new BLong( Core::EVID_SPOKE ) );
4424  addMember( "source", new Module::EOfflineCharacterRefObjImp( speaker ) );
4425  addMember( "text", new String( speech ) );
4426 }
4427 SpeechEvent::SpeechEvent( Mobile::Character* speaker, const char* speech, const char* texttype )
4428 {
4429  addMember( "type", new BLong( Core::EVID_SPOKE ) );
4430  addMember( "source", new Module::EOfflineCharacterRefObjImp( speaker ) );
4431  addMember( "text", new String( speech ) );
4432  addMember( "texttype", new String( texttype ) );
4433 }
4434 
4436  const u16* wspeech, const char lang[4],
4437  ObjArray* speechtokens )
4438 {
4439  ObjArray* arr;
4440  addMember( "type", new BLong( Core::EVID_SPOKE ) );
4441  addMember( "source", new Module::EOfflineCharacterRefObjImp( speaker ) );
4442  addMember( "text", new String( speech ) );
4443  unsigned wlen = 0;
4444  while ( wspeech[wlen] != L'\0' )
4445  ++wlen;
4446  if ( !Core::convertUCtoArray( wspeech, arr, wlen, true ) )
4447  addMember( "uc_text", new BError( "Invalid Unicode speech received." ) );
4448  else
4449  {
4450  addMember( "uc_text", arr );
4451  addMember( "langcode", new String( lang ) );
4452  }
4453  if ( speechtokens != nullptr )
4454  addMember( "tokens", speechtokens );
4455 }
4457  const char* texttype, const u16* wspeech,
4458  const char lang[4], ObjArray* speechtokens )
4459 {
4460  ObjArray* arr;
4461  addMember( "type", new BLong( Core::EVID_SPOKE ) );
4462  addMember( "source", new Module::EOfflineCharacterRefObjImp( speaker ) );
4463  addMember( "text", new String( speech ) );
4464  unsigned wlen = 0;
4465  while ( wspeech[wlen] != L'\0' )
4466  ++wlen;
4467  if ( !Core::convertUCtoArray( wspeech, arr, wlen, true ) )
4468  addMember( "uc_text", new BError( "Invalid Unicode speech received." ) );
4469  else
4470  {
4471  addMember( "uc_text", arr );
4472  addMember( "langcode", new String( lang ) );
4473  }
4474  addMember( "texttype", new String( texttype ) );
4475  if ( speechtokens != nullptr )
4476  addMember( "tokens", new ObjArray( *speechtokens ) );
4477 }
4478 
4479 DamageEvent::DamageEvent( Mobile::Character* source, unsigned short damage )
4480 {
4481  addMember( "type", new BLong( Core::EVID_DAMAGED ) );
4482 
4483  if ( source != nullptr )
4484  addMember( "source", new Module::EOfflineCharacterRefObjImp( source ) );
4485  else
4486  addMember( "source", new BLong( 0 ) );
4487 
4488  addMember( "damage", new BLong( damage ) );
4489 }
4490 
4492  Mobile::NPC* chr_givento )
4493  : SourcedEvent( Core::EVID_ITEM_GIVEN, chr_givenby ), given_by_( nullptr )
4494 {
4495  addMember( "item", new EItemRefObjImp( item_given ) );
4496 
4498  item_.set( item_given );
4499  cont_.set( item_given->container );
4500  given_by_.set( chr_givenby );
4501 
4502  item_given->setprop( "GivenBy", BLong::pack( chr_givenby->serial ) );
4503  item_given->setprop( "GivenTo", BLong::pack( chr_givento->serial ) );
4504  item_given->setprop( "GivenTime", BLong::pack( given_time_ ) );
4505 }
4506 
4508 {
4509  /* See if the item is still in the container it was in
4510  This means the AI script didn't do anything with it.
4511  */
4512  Items::Item* item = item_.get();
4513  Core::UContainer* cont = cont_.get();
4514  Mobile::Character* chr = given_by_.get();
4515 
4516  std::string given_time_str;
4517  if ( !item->getprop( "GivenTime", given_time_str ) )
4518  given_time_str = "";
4519 
4520  item->eraseprop( "GivenBy" );
4521  item->eraseprop( "GivenTo" );
4522  item->eraseprop( "GivenTime" );
4523 
4524  Bscript::BObject given_value( BObjectImp::unpack( given_time_str.c_str() ) );
4525  int gts = static_cast<BLong*>( given_value.impptr() )->value();
4526 
4527  if ( item->orphan() || cont->orphan() || chr->orphan() )
4528  return;
4529 
4530  if ( item->container == cont && Clib::decint( given_time_ ) == Clib::decint( gts ) )
4531  {
4532  Core::UContainer* backpack = chr->backpack();
4533  if ( backpack != nullptr && !chr->dead() )
4534  {
4535  if ( backpack->can_add( *item ) )
4536  {
4537  cont->remove( item );
4538  u8 newSlot = 1;
4539  if ( !backpack->can_add_to_slot( newSlot ) || !item->slot_index( newSlot ) )
4540  {
4541  item->x = chr->x;
4542  item->y = chr->y;
4543  item->z = chr->z;
4544  add_item_to_world( item );
4546  move_item( item, item->x, item->y, item->z, nullptr );
4547  return;
4548  }
4549  backpack->add( item );
4550  update_item_to_inrange( item );
4551  return;
4552  }
4553  }
4554  cont->remove( item );
4555  item->x = chr->x;
4556  item->y = chr->y;
4557  item->z = chr->z;
4558  add_item_to_world( item );
4560  move_item( item, item->x, item->y, item->z, nullptr );
4561  }
4562 }
4563 } // namespace Module
4564 namespace Core
4565 {
4566 bool UObject::script_isa( unsigned isatype ) const
4567 {
4568  return ( isatype == POLCLASS_OBJECT );
4569 }
4570 
4571 bool ULockable::script_isa( unsigned isatype ) const
4572 {
4573  return ( isatype == POLCLASS_LOCKABLE ) || base::script_isa( isatype );
4574 }
4575 
4576 bool UContainer::script_isa( unsigned isatype ) const
4577 {
4578  return ( isatype == POLCLASS_CONTAINER ) || base::script_isa( isatype );
4579 }
4580 
4581 bool UCorpse::script_isa( unsigned isatype ) const
4582 {
4583  return ( isatype == POLCLASS_CORPSE ) || base::script_isa( isatype );
4584 }
4585 
4586 bool UDoor::script_isa( unsigned isatype ) const
4587 {
4588  return ( isatype == POLCLASS_DOOR ) || base::script_isa( isatype );
4589 }
4590 
4591 bool Spellbook::script_isa( unsigned isatype ) const
4592 {
4593  return ( isatype == POLCLASS_SPELLBOOK ) || base::script_isa( isatype );
4594 }
4595 
4596 bool Map::script_isa( unsigned isatype ) const
4597 {
4598  return ( isatype == POLCLASS_MAP ) || base::script_isa( isatype );
4599 }
4600 } // namespace Core
4601 
4602 namespace Items
4603 {
4604 bool Item::script_isa( unsigned isatype ) const
4605 {
4606  return ( isatype == Core::POLCLASS_ITEM ) || base::script_isa( isatype );
4607 }
4608 
4609 bool Equipment::script_isa( unsigned isatype ) const
4610 {
4611  return ( isatype == Core::POLCLASS_EQUIPMENT ) || base::script_isa( isatype );
4612 }
4613 
4614 bool UArmor::script_isa( unsigned isatype ) const
4615 {
4616  return ( isatype == Core::POLCLASS_ARMOR ) || base::script_isa( isatype );
4617 }
4618 
4619 bool UWeapon::script_isa( unsigned isatype ) const
4620 {
4621  return ( isatype == Core::POLCLASS_WEAPON ) || base::script_isa( isatype );
4622 }
4623 } // namespace Items
4624 
4625 namespace Mobile
4626 {
4627 bool Character::script_isa( unsigned isatype ) const
4628 {
4629  return ( isatype == Core::POLCLASS_MOBILE ) || base::script_isa( isatype );
4630 }
4631 
4632 bool NPC::script_isa( unsigned isatype ) const
4633 {
4634  return ( isatype == Core::POLCLASS_NPC ) || base::script_isa( isatype );
4635 }
4636 } // namespace Mobile
4637 namespace Multi
4638 {
4639 bool UMulti::script_isa( unsigned isatype ) const
4640 {
4641  return ( isatype == Core::POLCLASS_MULTI ) || base::script_isa( isatype );
4642 }
4643 
4644 bool UBoat::script_isa( unsigned isatype ) const
4645 {
4646  return ( isatype == Core::POLCLASS_BOAT ) || base::script_isa( isatype );
4647 }
4648 
4649 bool UHouse::script_isa( unsigned isatype ) const
4650 {
4651  return ( isatype == Core::POLCLASS_HOUSE ) || base::script_isa( isatype );
4652 }
4653 } // namespace Multi
4654 } // namespace Pol
virtual Bscript::BObjectImp * call_method_id(const int id, Bscript::Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: uoscrobj.cpp:543
virtual void on_insert_add_item(Mobile::Character *mob, MoveType move, Items::Item *new_item)
Definition: containr.cpp:833
unsigned short doubleclick_range
Definition: itemdesc.h:114
unsigned char u8
Definition: rawtypes.h:25
virtual Bscript::BObjectImp * call_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:4384
void register_with_supporting_multi(Item *item)
Definition: ufunc.cpp:1875
virtual Bscript::BObjectImp * call_method_id(const int id, Bscript::Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: uoscrobj.cpp:379
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3326
BApplicObjType echaracterrefobjimp_type
Definition: uoscrobj.cpp:126
bool can_add_to_slot(u8 &slotIndex)
Definition: containr.cpp:178
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: uoscrobj.cpp:487
virtual Bscript::BObjectImp * custom_script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:2998
const std::string & value() const
Definition: impstr.h:67
Character * chr_from_wornitems(UContainer *wornitems)
Definition: ufunc.cpp:1529
virtual Bscript::BObjectRef set_member_id(const int id, Bscript::BObjectImp *value, bool copy) POL_OVERRIDE
Definition: uoscrobj.cpp:510
virtual Bscript::BObjectImp * set_script_member(const char *membername, const std::string &value) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:4205
virtual Bscript::BObjectImp * make_ref() POL_OVERRIDE
Definition: uoscrobj.cpp:1628
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: uoscrobj.cpp:4262
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3974
int value() const
Definition: bobject.h:592
virtual Bscript::BObjectImp * script_method_id(const int id, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:1325
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: uoscrobj.cpp:304
virtual Bscript::BObjectImp * script_method(const char *methodname, Bscript::Executor &ex)
Definition: uoscrobj.cpp:3888
virtual bool can_add(const Items::Item &item) const
Definition: containr.cpp:168
void add_item_to_world(Items::Item *item)
Definition: uworld.cpp:31
bool stackable() const
Definition: item.cpp:570
virtual Bscript::BObjectImp * get_script_member(const char *membername) const POL_OVERRIDE
Definition: uoscrobj.cpp:3293
bool operator<(T *ptr, const ref_ptr< T > &rptr)
Definition: refptr.h:323
short zcoord
Definition: poltype.h:21
virtual Bscript::BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: uoscrobj.cpp:501
virtual Bscript::BObjectImp * set_script_member_id_double(const int id, double value) POL_OVERRIDE
Definition: uoscrobj.cpp:2340
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:898
BApplicObjType eitemrefobjimp_type
Definition: uoscrobj.cpp:125
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
Definition: uoscrobj.cpp:4619
bool isa(BObjectType type) const
Definition: bobject.h:353
void setprop(const std::string &propname, const std::string &propvalue)
Definition: uobject.cpp:160
Core::gameclock_t given_time_
Definition: uoscrobj.h:304
polclock_t polclock()
Definition: polclock.cpp:72
virtual Bscript::BObjectRef set_member(const char *membername, Bscript::BObjectImp *value, bool copy) POL_OVERRIDE
Definition: uoscrobj.cpp:534
virtual Bscript::BObjectImp * call_method_id(const int id, Bscript::Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: uoscrobj.cpp:197
DamageEvent(Mobile::Character *source, unsigned short damage)
Definition: uoscrobj.cpp:4479
virtual Bscript::BObjectImp * get_script_member(const char *membername) const POL_OVERRIDE
Definition: uoscrobj.cpp:4181
unsigned short ycoord
Definition: poltype.h:20
virtual Bscript::BObjectImp * script_method_id(const int id, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:3938
virtual Bscript::BObjectRef set_member(const char *membername, Bscript::BObjectImp *value, bool copy) POL_OVERRIDE
Definition: uoscrobj.cpp:370
virtual Bscript::BObjectImp * set_script_member(const char *membername, const std::string &value) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:4093
const unsigned POLCLASS_WEAPON
Definition: polclass.h:28
Core::polclock_t polclock
Definition: charactr.h:276
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: uoscrobj.cpp:141
virtual Bscript::BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: uoscrobj.cpp:667
T * get() const
Definition: refptr.h:176
ObjMember * getKnownObjMember(const char *token)
Definition: parser.cpp:483
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
Definition: uoscrobj.cpp:4596
#define SPEECH_MAX_LEN
Definition: pktdef.h:27
virtual bool operator==(const Bscript::BObjectImp &objimp) const POL_OVERRIDE
Definition: uoscrobj.cpp:250
virtual bool isTrue() const POL_OVERRIDE
Definition: uoscrobj.cpp:429
std::string decint(unsigned short v)
Definition: strutil.cpp:64
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3089
virtual Bscript::BObjectRef set_member_id(const int id, Bscript::BObjectImp *value, bool copy) POL_OVERRIDE
Definition: uoscrobj.cpp:4377
const unsigned POLCLASS_BOAT
Definition: polclass.h:24
BObjectImp * CreatePartyRefObjImp(Core::Party *party)
Definition: partymod.cpp:119
const unsigned POLCLASS_ARMOR
Definition: polclass.h:27
virtual Bscript::BObjectRef get_member_id(const int id) POL_OVERRIDE
Definition: uoscrobj.cpp:658
const unsigned POLCLASS_MULTI
Definition: polclass.h:23
virtual void repsys_on_help(Character *recipient)
[15] Mobile (MA) Helps Mobile (MB)
Definition: repsys.cpp:932
virtual std::string getStringRep() const POL_OVERRIDE
Definition: impstr.h:129
const unsigned POLCLASS_OBJECT
Definition: polclass.h:13
virtual Bscript::BObjectImp * script_method_id(const int id, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:3221
Character * UpdateCharacterWeight(Item *item)
Definition: ufunc.cpp:1916
virtual Bscript::BObjectImp * set_script_member(const char *membername, const std::string &value)
id test
Definition: uoscrobj.cpp:836
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3393
virtual Bscript::BObjectImp * set_script_member_id(const int id, int value) POL_OVERRIDE
Definition: uoscrobj.cpp:3184
virtual Bscript::BObjectImp * custom_script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:3261
virtual void repsys_on_damage(Character *defender)
[14] Mobile (MA) Damages Mobile (MB)
Definition: repsys.cpp:872
virtual u8 typeOfInt() const POL_OVERRIDE
Definition: uoscrobj.cpp:318
BApplicObjType echaracterequipobjimp_type
Definition: uoscrobj.cpp:127
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
id test
Definition: uoscrobj.cpp:4581
virtual Bscript::BObjectImp * set_script_member(const char *membername, int value) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:3212
void addMember(const char *name, BObjectRef val)
Definition: bstruct.cpp:305
virtual Bscript::BObjectImp * set_script_member_double(const char *membername, double value) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:1316
Core::CharacterRef controller_
Definition: uomod.h:314
virtual Bscript::BObjectImp * set_script_member(const char *membername, const std::string &value) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:2116
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:666
virtual const char * typeOf() const POL_OVERRIDE
Definition: uoscrobj.cpp:478
Bscript::BObject call_custom_method(const char *methodname, Bscript::BObjectImpRefVec &pmore)
Definition: uoscrobj.cpp:1605
const unsigned POLCLASS_HOUSE
Definition: polclass.h:25
virtual Bscript::BObjectImp * set_script_member_id(const int id, const std::string &value) POL_OVERRIDE
Definition: uoscrobj.cpp:4078
virtual u8 typeOfInt() const POL_OVERRIDE
Definition: uoscrobj.cpp:648
void add_to_self(Item *&item)
Definition: item.cpp:600
virtual Bscript::BObjectImp * get_script_member_id(const int id) const
Definition: uoscrobj.cpp:741
const char * paramAsString(unsigned param)
Definition: executor.cpp:209
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3722
virtual bool operator==(const Bscript::BObjectImp &objimp) const POL_OVERRIDE
Definition: uoscrobj.cpp:713
virtual void add(Items::Item *item)
Definition: containr.cpp:194
virtual bool isTrue() const POL_OVERRIDE
Definition: uoscrobj.cpp:245
virtual bool script_isa(unsigned isatype) const
Definition: uoscrobj.cpp:4566
virtual Bscript::BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: uoscrobj.cpp:337
virtual Bscript::BObjectImp * script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:3503
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:4045
virtual Items::Item * remove(u32 serial, UContainer **found_in=nullptr)
Definition: containr.cpp:510
virtual bool operator==(const Bscript::BObjectImp &objimp) const POL_OVERRIDE
Definition: uoscrobj.cpp:434
BApplicObjType emultirefobjimp_type
Definition: uoscrobj.cpp:124
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
Definition: uoscrobj.cpp:4576
static gameclock_t gameclock
Definition: gameclck.cpp:21
virtual u8 typeOfInt() const POL_OVERRIDE
Definition: uoscrobj.cpp:299
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
Definition: uoscrobj.cpp:4604
MOVEMODE
Definition: uconst.h:79
virtual Bscript::BObjectImp * custom_script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:1586
virtual bool script_isa(unsigned isatype) const POL_OVERRIDE
Definition: uoscrobj.cpp:4627
std::string hexint(unsigned short v)
Definition: strutil.cpp:23
const BApplicObjType * object_type() const
Definition: bobject.h:897
Items::Item * find_addable_stack(const Items::Item *adding_item) const
Definition: containr.cpp:403
virtual Bscript::BObjectImp * get_script_member(const char *membername) const POL_OVERRIDE
Definition: uoscrobj.cpp:3929
unsigned short u16
Definition: rawtypes.h:26
virtual Bscript::BObjectImp * call_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:220
virtual Bscript::BObjectImp * script_method_id(const int id, Bscript::Executor &ex)
Definition: uoscrobj.cpp:3804
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: uoscrobj.cpp:653
unsigned int u32
Definition: rawtypes.h:27
virtual Bscript::BObjectImp * script_method_id(const int id, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:2386
bool getCharacterParam(Bscript::Executor &exec, unsigned param, Mobile::Character *&chrptr)
Definition: uoexhelp.cpp:140
BApplicObjType eclientrefobjimp_type
Definition: uoscrobj.cpp:130
bool getprop(const std::string &propname, std::string &propvalue) const
Definition: uobject.cpp:155
Bscript::BObjectImp * CallPropertyListMethod_id(PropertyList &proplist, const int id, Bscript::Executor &ex, bool &changed)
Definition: proplist.cpp:520
virtual Bscript::BObjectImp * script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: uoscrobj.cpp:2989
void setamount(u16 amount)
Definition: item.cpp:575
virtual u8 typeOfInt() const POL_OVERRIDE
Definition: uoscrobj.cpp:482
virtual Bscript::BObjectImp * get_script_member_id(const int id) const POL_OVERRIDE
Definition: uoscrobj.cpp:3277
virtual Bscript::BObjectImp * get_script_member(const char *membername) const POL_OVERRIDE
Definition: uoscrobj.cpp:3350
Core::CharacterRef given_by_
Definition: uoscrobj.h:303
virtual Bscript::BObjectImp * script_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
id test
Definition: uoscrobj.cpp:3961