24 #include "../../bscript/berror.h" 25 #include "../../clib/cfgelem.h" 26 #include "../../clib/cfgfile.h" 27 #include "../../clib/clib_endian.h" 28 #include "../../clib/logfacility.h" 29 #include "../../clib/passert.h" 30 #include "../../clib/stlutil.h" 31 #include "../../clib/streamsaver.h" 32 #include "../../plib/systemstate.h" 33 #include "../containr.h" 34 #include "../extobj.h" 35 #include "../fnsearch.h" 36 #include "../globals/object_storage.h" 37 #include "../globals/settings.h" 38 #include "../globals/uvars.h" 39 #include "../item/item.h" 40 #include "../item/itemdesc.h" 41 #include "../mdelta.h" 42 #include "../mkscrobj.h" 43 #include "../mobile/charactr.h" 44 #include "../network/client.h" 45 #include "../network/packethelper.h" 46 #include "../network/packets.h" 47 #include "../pktdef.h" 48 #include "../polvar.h" 49 #include "../realms/realm.h" 50 #include "../scrsched.h" 52 #include "../uconst.h" 54 #include "../uobject.h" 55 #include "../uworld.h" 77 graphic =
static_cast<unsigned short>( strtoul( tmp.c_str(),
nullptr, 0 ) );
80 unsigned short xd, yd;
94 ERROR_PRINT <<
"Boat component definition '" << str <<
"' is poorly formed.\n";
95 throw std::runtime_error(
"Poorly formed boat.cfg component definition" );
108 graphic =
static_cast<unsigned short>( strtoul( tmp.c_str(),
nullptr, 0 ) );
111 unsigned short xd, yd;
112 if ( is >> xd >> yd )
127 if ( ok && altis >> alttmp )
129 altgraphic =
static_cast<unsigned short>( strtoul( alttmp.c_str(),
nullptr, 0 ) );
137 ERROR_PRINT <<
"Boat component definition '" << str <<
"' is poorly formed.\n";
138 throw std::runtime_error(
"Poorly formed boat.cfg component definition" );
148 while ( elem.
remove_prop(
"Tillerman", &tmp_str ) )
150 while ( elem.
remove_prop(
"PortGangplankRetracted", &tmp_str ) )
153 while ( elem.
remove_prop(
"StarboardGangplankRetracted", &tmp_str ) )
172 while ( elem.
remove_prop(
"Weaponslot", &tmp_str ) )
248 while ( cf.
read( elem ) )
255 catch ( std::exception& )
257 ERROR_PRINT <<
"Error occurred reading definition for boat 0x" << fmt::hexu( multiid )
269 if ( iter->second !=
nullptr )
271 iter->second =
nullptr;
282 u16 newy,
bool relative )
290 if ( relative ==
false )
291 move_dir =
static_cast<Core::UFACING>( ( b_facing + move_dir ) * 7 );
294 msg->Write<
u32>( serial_ext );
295 msg->Write<
u8>( speed );
297 msg->Write<
u8>( move_dir );
298 msg->Write<
u8>( b_facing );
300 msg->WriteFlipped<
u16>( newx );
301 msg->WriteFlipped<
u16>( newy );
302 msg->WriteFlipped<
u16>( ( z < 0 ) ? static_cast<u16>( 0x10000 + z ) : static_cast<u16>( z ) );
304 u16 object_count =
static_cast<u16>( travellers_.size() + Components.size() );
306 msg->WriteFlipped<
u16>( object_count );
308 for (
auto& travellerRef : travellers_ )
310 UObject* obj = travellerRef.get();
312 if ( !obj->orphan() )
314 msg->Write<
u32>( obj->serial_ext );
315 msg->WriteFlipped<
u16>(
static_cast<u16>( obj->x + xmod ) );
316 msg->WriteFlipped<
u16>(
static_cast<u16>( obj->y + ymod ) );
317 msg->WriteFlipped<
u16>(
318 static_cast<u16>( ( obj->z < 0 ) ? ( 0x10000 + obj->z ) : ( obj->z ) ) );
322 for (
auto& component : Components )
324 if ( component !=
nullptr && !component->orphan() )
326 msg->Write<
u32>( component->serial_ext );
327 msg->WriteFlipped<
u16>(
static_cast<u16>( component->x + xmod ) );
328 msg->WriteFlipped<
u16>(
static_cast<u16>( component->y + ymod ) );
329 msg->WriteFlipped<
u16>(
static_cast<u16>( ( component->z < 0 ) ? ( 0x10000 + component->z )
330 : ( component->z ) ) );
334 u16 len = msg->offset;
337 msg->WriteFlipped<
u16>( len );
339 msg.
Send( client, len );
352 send_smooth_move( client, move_dir, speed, newx, newy, relative );
362 u16 inner_packet_count =
363 static_cast<u16>( travellers_.size() + Components.size() + 1 );
365 msg->WriteFlipped<
u16>( inner_packet_count );
369 msg->Write<
u8>( 0xF3u );
370 msg->WriteFlipped<
u16>( 0x1u );
371 msg->Write<
u8>( 0x2u );
372 msg->Write<
u32>( this->serial_ext );
373 msg->WriteFlipped<
u16>( this->multidef().multiid );
375 msg->WriteFlipped<
u16>( 0x1u );
376 msg->WriteFlipped<
u16>( 0x1u );
377 msg->WriteFlipped<
u16>( this->x );
378 msg->WriteFlipped<
u16>( this->y );
379 msg->Write<
s8>( this->z );
381 msg->WriteFlipped<
u16>( this->color );
387 for (
auto& travellerRef : travellers_ )
389 UObject* obj = travellerRef.get();
391 if ( !obj->orphan() )
393 msg->Write<
u8>( 0xF3u );
394 msg->WriteFlipped<
u16>( 0x1u );
396 if ( obj->ismobile() )
397 msg->Write<
u8>( 0x1u );
399 msg->Write<
u8>( 0x0u );
401 msg->Write<
u32>( obj->serial_ext );
402 msg->WriteFlipped<
u16>( obj->graphic );
405 if ( obj->ismobile() )
409 msg->WriteFlipped<
u16>( 0x1u );
410 msg->WriteFlipped<
u16>( 0x1u );
429 msg->WriteFlipped<
u16>( obj->x );
430 msg->WriteFlipped<
u16>( obj->y );
431 msg->Write<
s8>( obj->z );
432 msg->Write<
u8>( obj->facing );
433 msg->WriteFlipped<
u16>( obj->color );
435 msg->Write<
u8>( flags );
440 for (
auto& component : Components )
442 if ( component !=
nullptr && !component->orphan() )
444 msg->Write<
u8>( 0xF3u );
445 msg->WriteFlipped<
u16>( 0x1u );
446 msg->Write<
u8>( 0x0u );
447 msg->Write<
u32>( component->serial_ext );
448 msg->WriteFlipped<
u16>( component->graphic );
450 msg->WriteFlipped<
u16>( component->get_senditem_amount() );
451 msg->WriteFlipped<
u16>( component->get_senditem_amount() );
452 msg->WriteFlipped<
u16>( component->x );
453 msg->WriteFlipped<
u16>( component->y );
454 msg->Write<
s8>( component->z );
455 msg->Write<
u8>( component->facing );
456 msg->WriteFlipped<
u16>( component->color );
462 u16 len = msg->offset;
465 msg->WriteFlipped<
u16>( len );
467 msg.
Send( client, len );
473 msg->WriteFlipped<
u16>( 0x1u );
474 msg->Write<
u8>( 0x02u );
475 msg->Write<
u32>( serial_ext );
476 msg->WriteFlipped<
u16>( multidef().multiid );
478 msg->WriteFlipped<
u16>( 0x1u );
479 msg->WriteFlipped<
u16>( 0x1u );
480 msg->WriteFlipped<
u16>( x );
481 msg->WriteFlipped<
u16>( y );
484 msg->WriteFlipped<
u16>( color );
489 for (
auto& travellerRef : travellers_ )
491 UObject* obj = travellerRef.get();
493 if ( !obj->orphan() )
495 if ( obj->ismobile() )
508 for (
auto& component : Components )
510 if ( component !=
nullptr && !component->orphan() )
522 send_display_boat( client );
526 send_boat_old( client );
534 send_remove_boat( client );
542 msg2->WriteFlipped<
u16>( 0x1u );
543 msg2->Write<
u8>( 0x02u );
544 msg2->Write<
u32>( this->serial_ext );
545 msg2->WriteFlipped<
u16>( this->multidef().multiid );
547 msg2->WriteFlipped<
u16>( 0x1u );
548 msg2->WriteFlipped<
u16>( 0x1u );
549 msg2->WriteFlipped<
u16>( this->x );
550 msg2->WriteFlipped<
u16>( this->y );
551 msg2->Write<
s8>( this->z );
553 msg2->WriteFlipped<
u16>( this->color );
563 u16 b_graphic = this->multidef().multiid | 0x4000;
564 msg->Write<
u32>( this->serial_ext );
565 msg->WriteFlipped<
u16>( b_graphic );
566 msg->WriteFlipped<
u16>( this->x );
567 msg->WriteFlipped<
u16>( this->y );
568 msg->Write<
s8>( this->z );
569 u16 len1A = msg->offset;
571 msg->WriteFlipped<
u16>( len1A );
574 msg.
Send( client, len1A );
575 boat_sent_to.push_back( client );
589 boat_sent_to.clear();
613 for ( MultiDef::HullList::const_iterator itr = md.
hull.begin(), end = md.
hull.end(); itr != end;
616 unsigned short ax =
x + ( *itr )->x;
617 unsigned short ay =
y + ( *itr )->y;
627 for ( MultiDef::HullList::const_iterator itr = md.
hull.begin(), end = md.
hull.end(); itr != end;
630 unsigned short ax =
x + ( *itr )->x;
631 unsigned short ay =
y + ( *itr )->y;
642 if (
int( x + md.
minrx ) < 0 ||
int( x + md.
maxrx ) >
int( realm->
width() ) ||
646 INFO_PRINT <<
"Location " << x <<
"," << y <<
" impassable, location is off the map\n";
653 for ( MultiDef::HullList::const_iterator itr = md.
hull.begin(), end = md.
hull.end(); itr != end;
656 unsigned short ax = x + ( *itr )->x;
657 unsigned short ay = y + ( *itr )->y;
658 short az = z + ( *itr )->z;
669 INFO_PRINT <<
"Location " << realm->
name() <<
" " << ax <<
"," << ay
670 <<
" already has a ship hull present\n";
689 const Item* item =
static_cast<const Item*
>( obj );
693 short rx = obj->
x - bc.
x;
694 short ry = obj->y - bc.
y;
700 unsigned short newx,
unsigned short newy,
Realms::Realm* oldrealm )
702 bool any_orphans =
false;
706 UObject* obj = travellerRef.get();
709 if ( obj->orphan() || !
on_ship( oldlocation, obj ) )
712 travellerRef.clear();
718 if ( obj->ismobile() )
727 if ( newx != USHRT_MAX &&
731 dx = chr->
x - oldlocation.
x;
732 dy = chr->
y - oldlocation.
y;
744 if ( chr->
client !=
nullptr )
746 if ( oldrealm != chr->
realm )
780 if ( newx != USHRT_MAX &&
784 dx = chr->
x - oldlocation.
x;
785 dy = chr->
y - oldlocation.
y;
802 if ( newx != USHRT_MAX &&
806 dx = item->
x - oldlocation.
x;
807 dy = item->
y - oldlocation.
y;
837 Network::Client* client = zonechr->client;
839 if ( !( client->ClientType & Network::CLIENTTYPE_7090 ) )
840 send_item( client, item );
890 bool any_orphans =
false;
894 UObject* obj = travellerRef.get();
897 if ( obj->orphan() || !
on_ship( oldlocation, obj ) )
900 travellerRef.clear();
905 if ( obj->ismobile() )
918 if ( chr->
client !=
nullptr )
952 s16 xd = item->
x -
x;
953 s16 yd = item->
y -
y;
989 Network::Client* client = zonechr->client;
991 if ( !( client->ClientType & Network::CLIENTTYPE_7090 ) )
992 send_item( client, item );
1012 bool any_orphan_travellers;
1015 any_orphan_travellers =
false;
1020 UObject* obj = ( *itr ).get();
1021 if ( obj ==
nullptr )
1025 any_orphan_travellers =
true;
1029 }
while ( any_orphan_travellers );
1038 UObject* obj = travellerRef.get();
1040 if ( obj->orphan() || !
on_ship( bc, obj ) )
1043 travellerRef.clear();
1055 UObject* obj = travellerRef.get();
1057 if ( !obj->orphan() &&
on_ship( bc, obj ) && obj->ismobile() )
1077 UObject* obj = travellerRef.get();
1079 if ( !obj->orphan() &&
on_ship( bc, obj ) && obj->ismobile() )
1088 chr->
z =
static_cast<signed char>( new_z );
1089 chr->
realm = new_realm;
1091 travellerRef.clear();
1102 UObject* obj = travellerRef.get();
1107 component->z += delta_z;
1122 UObject* obj = travellerRef.get();
1124 if ( !obj->orphan() &&
on_ship( bc, obj ) && obj->ismobile() )
1144 component->realm =
realm;
1156 if ( it ==
nullptr )
1161 return ( cont->
count() == 0 );
1171 UObject* obj = travellerRef.get();
1173 if ( obj !=
nullptr )
1175 if ( obj->ismobile() )
1231 if ( relative ==
false )
1236 unsigned short newx, newy;
1266 if ( Core::inrange( client->chr->x, client->chr->y, oldx, oldy ) )
1269 send_boat_newly_inrange( client );
1273 if ( client->ClientType & Network::CLIENTTYPE_7000 )
1274 send_boat( client );
1276 send_boat_old( client );
1334 for ( ; itr != end && itr2 != end2 && old_itr != old_end; ++itr, ++itr2, ++old_itr )
1337 if ( item !=
nullptr )
1345 if ( item->
container !=
nullptr || item->has_gotten_by() )
1349 "Boat component is gotten or in a container and couldn't be moved together with the " 1350 "boat: serial 0x{:X}\n, graphic: 0x{:X}, container: 0x{:X}." )
1357 item->
graphic == old_itr->altgraphic )
1358 item->
graphic = itr2->altgraphic;
1360 item->
graphic == old_itr->altgraphic )
1361 item->
graphic = itr2->altgraphic;
1363 item->
graphic = itr2->graphic;
1368 item->
x =
x + itr2->xdelta;
1369 item->
y =
y + itr2->ydelta;
1370 item->
z =
z +
static_cast<s8>( itr2->zdelta );
1376 Network::Client* client = zonechr->client;
1378 if ( !( client->ClientType & Network::CLIENTTYPE_7090 ) )
1379 send_item( client, item );
1401 for ( ; itr != end && itr2 != end2; ++itr, ++itr2 )
1404 if ( item !=
nullptr )
1414 if ( item->
container !=
nullptr || item->has_gotten_by() )
1418 "Boat component is gotten or in a container and couldn't be moved together with the " 1419 "boat: serial 0x{:X}\n, graphic: 0x{:X}, container: 0x{:X}." )
1429 item->
x =
x + itr2->xdelta;
1430 item->
y =
y + itr2->ydelta;
1431 item->
z =
z +
static_cast<s8>( itr2->zdelta );
1437 Network::Client* client = zonechr->client;
1439 if ( !( client->ClientType & Network::CLIENTTYPE_7090 ) )
1440 send_item( client, item );
1527 if ( component ==
nullptr )
1538 hold = component.get();
1566 while ( elem.
remove_prop(
"Traveller", &tmp_serial ) )
1571 if ( item !=
nullptr )
1577 else if (
on_ship( bc, item ) )
1587 if ( chr !=
nullptr )
1594 while ( elem.
remove_prop(
"Component", &tmp_serial ) )
1597 if ( item !=
nullptr )
1624 UObject* obj = travellerRef.get();
1625 if ( !obj->orphan() &&
on_ship( bc, obj ) )
1627 sw() <<
"\tTraveller\t0x" << fmt::hex( obj->serial ) <<
pf_endl;
1632 if ( component !=
nullptr && !component->orphan() )
1634 sw() <<
"\tComponent\t0x" << fmt::hex( component->serial ) <<
pf_endl;
1643 unsigned short multiid_offset =
1645 unsigned char facing =
static_cast<unsigned char>( multiid_offset * 2 );
1646 multiid += multiid_offset;
1649 if ( md ==
nullptr )
1662 if ( !
navigable( *md, x, y, z, realm ) )
1695 for ( std::vector<BoatShape::ComponentShape>::const_iterator itr = bshape.
Componentshapes.begin(),
1700 if ( component ==
nullptr )
1713 component->
graphic = itr->graphic;
1716 component->
x =
x + itr->xdelta;
1717 component->
y =
y + itr->ydelta;
1718 component->
z =
z +
static_cast<s8>( itr->zdelta );
1735 UObject* obj = travellerRef.get();
1738 Item* item =
static_cast<Item*
>( obj );
1751 UObject* obj = travellerRef.get();
1752 if ( !obj->orphan() &&
on_ship( bc, obj ) && obj->ismobile() )
1767 if ( component !=
nullptr && !component->orphan() )
1787 if ( component !=
nullptr && !component->orphan() )
1814 return new Bscript::BError(
"There are logged-out characters on the deck" );
void move_offline_mobiles(Core::xcoord new_x, Core::ycoord new_y, Core::zcoord new_z, Realms::Realm *new_realm)
void turn_traveller_coords(Mobile::Character *chr, RELATIVE_DIR dir)
static Item * create(u32 objtype, u32 serial=0)
bool move(Core::UFACING dir, u8 speed, bool relative)
void send_invulhealthbar(Client *client, const Character *chr)
#define ITEM_FLAG_FORCE_MOVABLE
std::string remove_string(const char *propname)
void send_smooth_move_to_inrange(Core::UFACING move_dir, u8 speed, u16 newx, u16 newy, bool relative)
void send_remove_character_to_nearby(const Character *chr)
void add_item_to_world(Items::Item *item)
void setboat(UBoat *boat)
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
#define RANGE_VISUAL_LARGE_BUILDINGS
Bscript::BObjectImp * items_list() const
const int CRMULTI_FACING_MASK
void destroy_components()
Items::Item * find_toplevel_item(u32 serial)
bool BoatShapeExists(u16 multiid)
UObject(u32 objtype, UOBJ_CLASS uobj_class)
ComponentShape(const std::string &str, const std::string &altstr, unsigned char type)
virtual void on_color_changed() POL_OVERRIDE
void move_components(Realms::Realm *oldrealm)
std::vector< ComponentShape > Componentshapes
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
unsigned short altgraphic
Core::UFACING boat_facing() const
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
bool has_active_client() const
bool inrange(const UObject *c1, unsigned short x, unsigned short y)
Core::UObjectRef Traveller
virtual void register_object(Core::UObject *obj) POL_OVERRIDE
std::vector< Network::Client * > boat_sent_to
void send_new_subserver(Client *client)
virtual void fixInvalidGraphic()
Fixes invalid graphic, moving here to allow it to be overridden in subclass (see Multi) ...
static void InRange(u16 x, u16 y, const Realms::Realm *realm, unsigned range, F &&f)
const MultiDef & multi_ifturn(RELATIVE_DIR dir)
const std::string name() const
void send_remove_boat(Network::Client *client)
bool can_seeinvisitems() const
static unsigned int encode_global_hull(unsigned short ax, unsigned short ay)
virtual u16 get_senditem_amount() const
void add_multi_to_world(Multi::UMulti *multi)
void send_boat(Network::Client *client)
void send_boat_newly_inrange(Network::Client *client)
std::string hexint(unsigned short v)
UBoat(const Items::ItemDesc &descriptor)
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
void send_poisonhealthbar(Client *client, const Character *chr)
Bscript::BObjectImp * mobiles_list() const
unsigned int get_component_objtype(unsigned char type)
bool turn(RELATIVE_DIR dir)
void send_smooth_move(Network::Client *client, Core::UFACING move_dir, u8 speed, u16 newx, u16 newy, bool relative)
void destroy_item(Item *item)
static bool navigable(const MultiDef &, unsigned short x, unsigned short y, short z, Realms::Realm *realm)
void send_goxyz(Client *client, const Character *chr)
unsigned int starboard_plank
virtual void unregister_object(Core::UObject *obj) POL_OVERRIDE
u32 GetNewItemSerialNumber(void)
unsigned short height() const
void send_remove_object(Client *client, const UObject *object)
void Send(Client *client, int len=-1) const
void send_boat_old(Network::Client *client)
char tileheight(unsigned short tilenum)
void setrealm(Item *item, void *arg)
void send_display_boat_to_inrange(u16 oldx=USHRT_MAX, u16 oldy=USHRT_MAX)
void send_display_boat(Network::Client *client)
Core::UContainer * container
virtual size_t estimatedSize() const POL_OVERRIDE
Items::Item * starboardplank
const int CRMULTI_FACING_SHIFT
#define passert_always_r(exp, reason)
size_t estimateSize() const
void send_objects_newly_inrange_on_boat(Network::Client *client, u32 serial)
SettingsManager settingsManager
static void InVisualRange(const UObject *obj, F &&f)
void MoveCharacterWorldPosition(unsigned short oldx, unsigned short oldy, unsigned short newx, unsigned short newy, Mobile::Character *chr, Realms::Realm *oldrealm)
Mobile::Character * system_find_mobile(u32 serial)
void adjust_traveller_z(s8 delta_z)
bool Insert(UObject *obj)
const int MOVEITEM_FORCELOCATION
bool remove_prop(const char *propname, std::string *value)
bool MultiDefByMultiIDExists(u16 multiid)
void send_item(Client *client, const Item *item)
Bscript::BObjectImp * make_itemref(Items::Item *item)
std::vector< Component > Components
Bscript::BObjectImp * component_list(unsigned char type) const
void addElement(BObjectImp *imp)
Items::Item * system_find_item(u32 serial)
void transform_components(const BoatShape &old_boatshape, Realms::Realm *oldrealm)
static bool objtype_is_component(unsigned int objtype)
void restart_decay_timer()
virtual UBoat * as_boat() POL_OVERRIDE
static bool on_ship(const BoatContext &bc, const Core::UObject *obj)
void turn_travellers(RELATIVE_DIR dir, const BoatContext &oldlocation)
void position_changed(void)
bool navigable(unsigned short x, unsigned short y, short z, short height) const
virtual size_t estimatedSize() const POL_OVERRIDE
std::set< unsigned int > global_hulls
ObjectStorageManager objStorageManager
unsigned short width() const
unsigned short remove_ushort(const char *propname)
static Bscript::BObjectImp * scripted_create(const Items::ItemDesc &descriptor, u16 x, u16 y, s8 z, Realms::Realm *realm, int flags)
void move_multi_in_world(unsigned short oldx, unsigned short oldy, unsigned short newx, unsigned short newy, Multi::UMulti *multi, Realms::Realm *oldrealm)
bool isa(UOBJ_CLASS uobj_class) const
Bscript::BObjectImp * make_boatref(Multi::UBoat *boat)
bool can_move(const Items::Item *item) const
const MultiDef & multidef() const
void move_travellers(enum Core::UFACING move_dir, const BoatContext &oldlocation, unsigned short x=USHRT_MAX, unsigned short y=USHRT_MAX, Realms::Realm *oldrealm=nullptr)
bool read(ConfigElem &elem)
void remove_multi_from_world(Multi::UMulti *multi)
void start_script(const char *filename, Bscript::BObjectImp *param0, Bscript::BObjectImp *param1)
bool has_offline_mobiles() const
void send_owncreate(Client *client, const Character *chr)
Bscript::BObjectImp * make_mobileref(Mobile::Character *chr)
const BoatShape & boatshape() const
void MoveItemWorldPosition(unsigned short oldx, unsigned short oldy, Items::Item *item, Realms::Realm *oldrealm)
virtual void fixInvalidGraphic() POL_OVERRIDE
POL098 and earlier were using graphic to store MultiID, this should not be lost to avoid screwing up ...
bool move_xy(unsigned short x, unsigned short y, int flags, Realms::Realm *oldrealm)
enum Pol::Mobile::Character::MOVEREASON move_reason
Bscript::BObjectImp * destroy_boat(UBoat *boat)
const MultiDef * MultiDefByMultiID(u16 multiid)
void update_item_to_inrange(const Item *item)
bool body_contains(short rx, short ry) const
unsigned short multiid_ifturn(RELATIVE_DIR dir)
virtual void for_each_item(void(*f)(Item *item, void *a), void *arg)