mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
Boat refactor Part 1 of N (#654)
* test for traveller movement due to turn/move check relative position of a component * refactor BoatComponents, turn/move
This commit is contained in:
parent
b216a16d36
commit
0d00a675d0
3 changed files with 213 additions and 218 deletions
|
|
@ -82,15 +82,13 @@ BoatShape::ComponentShape::ComponentShape( const std::string& str, unsigned char
|
|||
graphic = static_cast<unsigned short>( strtoul( tmp.c_str(), nullptr, 0 ) );
|
||||
if ( graphic )
|
||||
{
|
||||
unsigned short xd, yd;
|
||||
s16 xd, yd;
|
||||
if ( is >> xd >> yd )
|
||||
{
|
||||
xdelta = xd;
|
||||
ydelta = yd;
|
||||
zdelta = 0;
|
||||
signed short zd;
|
||||
delta = Core::Vec3d( xd, yd, 0 );
|
||||
s16 zd;
|
||||
if ( is >> zd )
|
||||
zdelta = zd;
|
||||
delta.z( zd );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -113,15 +111,13 @@ BoatShape::ComponentShape::ComponentShape( const std::string& str, const std::st
|
|||
graphic = static_cast<unsigned short>( strtoul( tmp.c_str(), nullptr, 0 ) );
|
||||
if ( graphic )
|
||||
{
|
||||
unsigned short xd, yd;
|
||||
s16 xd, yd;
|
||||
if ( is >> xd >> yd )
|
||||
{
|
||||
xdelta = xd;
|
||||
ydelta = yd;
|
||||
zdelta = 0;
|
||||
signed short zd;
|
||||
delta = Core::Vec3d( xd, yd, 0 );
|
||||
s16 zd;
|
||||
if ( is >> zd )
|
||||
zdelta = zd;
|
||||
delta.z( zd );
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -282,13 +278,13 @@ bool BoatShapeExists( u16 multiid )
|
|||
return Core::gamestate.boatshapes.count( multiid ) != 0;
|
||||
}
|
||||
|
||||
void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u8 speed, u16 newx,
|
||||
u16 newy, bool relative )
|
||||
// TODO: why not send after actual movement like the other pkts
|
||||
void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u8 speed,
|
||||
const Core::Pos4d& newpos, bool relative ) const
|
||||
{
|
||||
Network::PktHelper::PacketOut<Network::PktOut_F6> msg;
|
||||
|
||||
u16 xmod = newx - x();
|
||||
u16 ymod = newy - y();
|
||||
auto posdelta = newpos.xyz() - pos3d();
|
||||
Core::UFACING b_facing = boat_facing();
|
||||
|
||||
if ( relative == false )
|
||||
|
|
@ -301,10 +297,10 @@ void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u
|
|||
msg->Write<u8>( move_dir );
|
||||
msg->Write<u8>( b_facing );
|
||||
|
||||
msg->WriteFlipped<u16>( newx );
|
||||
msg->WriteFlipped<u16>( newy );
|
||||
msg->WriteFlipped<u16>( ( z() < 0 ) ? static_cast<u16>( 0x10000 + z() )
|
||||
: static_cast<u16>( z() ) );
|
||||
msg->WriteFlipped<u16>( newpos.x() );
|
||||
msg->WriteFlipped<u16>( newpos.y() );
|
||||
msg->WriteFlipped<u16>( ( newpos.z() < 0 ) ? static_cast<u16>( 0x10000 + newpos.z() )
|
||||
: static_cast<u16>( newpos.z() ) );
|
||||
|
||||
// 0xf000 encoding room, huffman can take more space then the maximum of 0xffff
|
||||
const u16 max_count = ( 0xf000 - 18 ) / 10;
|
||||
|
|
@ -322,10 +318,11 @@ void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u
|
|||
if ( component == nullptr || component->orphan() )
|
||||
continue;
|
||||
msg->Write<u32>( component->serial_ext );
|
||||
msg->WriteFlipped<u16>( static_cast<u16>( component->x() + xmod ) );
|
||||
msg->WriteFlipped<u16>( static_cast<u16>( component->y() + ymod ) );
|
||||
msg->WriteFlipped<u16>( static_cast<u16>( ( component->z() < 0 ) ? ( 0x10000 + component->z() )
|
||||
: ( component->z() ) ) );
|
||||
const auto comppos = component->pos() + posdelta;
|
||||
msg->WriteFlipped<u16>( comppos.x() );
|
||||
msg->WriteFlipped<u16>( comppos.y() );
|
||||
msg->WriteFlipped<u16>(
|
||||
static_cast<u16>( ( comppos.z() < 0 ) ? ( 0x10000 + comppos.z() ) : ( comppos.z() ) ) );
|
||||
++object_count;
|
||||
}
|
||||
for ( auto& travellerRef : travellers_ )
|
||||
|
|
@ -353,10 +350,11 @@ void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u
|
|||
continue;
|
||||
}
|
||||
msg->Write<u32>( obj->serial_ext );
|
||||
msg->WriteFlipped<u16>( static_cast<u16>( obj->x() + xmod ) );
|
||||
msg->WriteFlipped<u16>( static_cast<u16>( obj->y() + ymod ) );
|
||||
const auto objpos = obj->pos() + posdelta;
|
||||
msg->WriteFlipped<u16>( objpos.x() );
|
||||
msg->WriteFlipped<u16>( objpos.y() );
|
||||
msg->WriteFlipped<u16>(
|
||||
static_cast<u16>( ( obj->z() < 0 ) ? ( 0x10000 + obj->z() ) : ( obj->z() ) ) );
|
||||
static_cast<u16>( ( objpos.z() < 0 ) ? ( 0x10000 + objpos.z() ) : ( objpos.z() ) ) );
|
||||
++object_count;
|
||||
}
|
||||
u16 len = msg->offset;
|
||||
|
|
@ -368,12 +366,11 @@ void UBoat::send_smooth_move( Network::Client* client, Core::UFACING move_dir, u
|
|||
msg.Send( client, len );
|
||||
}
|
||||
|
||||
void UBoat::send_smooth_move_to_inrange( Core::UFACING move_dir, u8 speed, u16 newx, u16 newy,
|
||||
bool relative )
|
||||
void UBoat::send_smooth_move_to_inrange( Core::UFACING move_dir, u8 speed,
|
||||
const Core::Pos4d& newpos, bool relative ) const
|
||||
{
|
||||
const Core::Pos2d newpos = Core::Pos2d( newx, newy );
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
newpos, realm(),
|
||||
newpos,
|
||||
[&]( Mobile::Character* zonechr )
|
||||
{
|
||||
Network::Client* client = zonechr->client;
|
||||
|
|
@ -381,7 +378,7 @@ void UBoat::send_smooth_move_to_inrange( Core::UFACING move_dir, u8 speed, u16 n
|
|||
if ( zonechr->in_visual_range( this, newpos ) && zonechr->in_visual_range( this ) &&
|
||||
client->ClientType & Network::CLIENTTYPE_7090 ) // send this only to those who see the
|
||||
// old location aswell
|
||||
send_smooth_move( client, move_dir, speed, newx, newy, relative );
|
||||
send_smooth_move( client, move_dir, speed, newpos, relative );
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
@ -760,7 +757,7 @@ bool UBoat::on_ship( const BoatContext& bc, const UObject* obj )
|
|||
if ( item->container != nullptr )
|
||||
return false;
|
||||
}
|
||||
Core::Vec2d rxy = obj->pos2d() - Core::Pos2d( bc.x, bc.y );
|
||||
Core::Vec2d rxy = obj->pos2d() - bc.oldpos.xy();
|
||||
|
||||
return bc.mdef.body_contains( rxy );
|
||||
}
|
||||
|
|
@ -768,6 +765,7 @@ bool UBoat::on_ship( const BoatContext& bc, const UObject* obj )
|
|||
void UBoat::move_travellers( Core::UFACING move_dir, const BoatContext& oldlocation,
|
||||
unsigned short newx, unsigned short newy, Realms::Realm* oldrealm )
|
||||
{
|
||||
Core::Pos2d newpos2d{ newx, newy };
|
||||
bool any_orphans = false;
|
||||
|
||||
for ( auto& travellerRef : travellers_ )
|
||||
|
|
@ -783,28 +781,27 @@ void UBoat::move_travellers( Core::UFACING move_dir, const BoatContext& oldlocat
|
|||
}
|
||||
|
||||
obj->set_dirty();
|
||||
auto oldpos = obj->pos();
|
||||
auto newtravellerpos = obj->pos();
|
||||
if ( newx != USHRT_MAX &&
|
||||
newy != USHRT_MAX ) // dave added 3/27/3, if move_xy was used, dont use facing
|
||||
{
|
||||
// keeps relative distance from boat mast
|
||||
auto delta = newtravellerpos.xy() - oldlocation.oldpos.xy();
|
||||
newtravellerpos.xy( newpos2d + delta );
|
||||
}
|
||||
else
|
||||
{
|
||||
newtravellerpos.move_to( move_dir );
|
||||
}
|
||||
if ( obj->ismobile() )
|
||||
{
|
||||
Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
|
||||
chr->lastpos = oldpos;
|
||||
chr->setposition( newtravellerpos );
|
||||
|
||||
if ( chr->logged_in() )
|
||||
{
|
||||
Core::Pos4d oldpos = chr->pos();
|
||||
chr->lastpos = oldpos;
|
||||
|
||||
if ( newx != USHRT_MAX &&
|
||||
newy != USHRT_MAX ) // dave added 3/27/3, if move_xy was used, dont use facing
|
||||
{
|
||||
s16 dx, dy;
|
||||
dx = chr->x() - oldlocation.x; // keeps relative distance from boat mast
|
||||
dy = chr->y() - oldlocation.y;
|
||||
chr->setposition( Core::Pos4d( chr->pos() ).x( newx + dx ).y( newy + dy ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
chr->setposition( chr->pos().move( move_dir ) );
|
||||
}
|
||||
|
||||
MoveCharacterWorldPosition( oldpos, chr );
|
||||
chr->position_changed();
|
||||
if ( chr->client != nullptr )
|
||||
|
|
@ -836,57 +833,16 @@ void UBoat::move_travellers( Core::UFACING move_dir, const BoatContext& oldlocat
|
|||
}
|
||||
chr->move_reason = Mobile::Character::MULTIMOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// characters that are logged out move with the boat
|
||||
// they aren't in the worldzones so this is real easy.
|
||||
chr->lastpos = chr->pos(); // I think in this case setting last? isn't
|
||||
// necessary, but I'll do it anyway.
|
||||
|
||||
if ( newx != USHRT_MAX &&
|
||||
newy != USHRT_MAX ) // dave added 3/27/3, if move_xy was used, dont use facing
|
||||
{
|
||||
s16 dx, dy;
|
||||
dx = chr->x() - oldlocation.x; // keeps relative distance from boat mast
|
||||
dy = chr->y() - oldlocation.y;
|
||||
chr->setposition( Core::Pos4d( chr->pos() ).x( newx + dx ).y( newy + dy ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
chr->setposition( chr->pos().move( move_dir ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Items::Item* item = static_cast<Items::Item*>( obj );
|
||||
Core::Pos4d oldpos = item->pos();
|
||||
|
||||
if ( newx != USHRT_MAX &&
|
||||
newy != USHRT_MAX ) // dave added 4/9/3, if move_xy was used, dont use facing
|
||||
{
|
||||
s16 dx, dy;
|
||||
dx = item->x() - oldlocation.x; // keeps relative distance from boat mast
|
||||
dy = item->y() - oldlocation.y;
|
||||
item->setposition( newtravellerpos );
|
||||
|
||||
item->set_dirty();
|
||||
|
||||
item->setposition( Core::Pos4d( item->pos() ).x( newx + dx ).y( newy + dy ) );
|
||||
|
||||
if ( Core::settingsManager.ssopt.refresh_decay_after_boat_moves )
|
||||
item->restart_decay_timer();
|
||||
MoveItemWorldPosition( oldpos, item );
|
||||
}
|
||||
else
|
||||
{
|
||||
item->set_dirty();
|
||||
|
||||
item->setposition( item->pos().move( move_dir ) );
|
||||
|
||||
if ( Core::settingsManager.ssopt.refresh_decay_after_boat_moves )
|
||||
item->restart_decay_timer();
|
||||
MoveItemWorldPosition( oldpos, item );
|
||||
}
|
||||
if ( Core::settingsManager.ssopt.refresh_decay_after_boat_moves )
|
||||
item->restart_decay_timer();
|
||||
MoveItemWorldPosition( oldpos, item );
|
||||
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
item,
|
||||
|
|
@ -917,30 +873,29 @@ void UBoat::move_travellers( Core::UFACING move_dir, const BoatContext& oldlocat
|
|||
remove_orphans();
|
||||
}
|
||||
|
||||
void UBoat::turn_traveller_coords( Mobile::Character* chr, RELATIVE_DIR dir )
|
||||
Core::Pos4d UBoat::turn_coords( const Core::Pos4d& oldpos, RELATIVE_DIR dir ) const
|
||||
{
|
||||
chr->lastpos = chr->pos();
|
||||
|
||||
s16 xd = chr->x() - x();
|
||||
s16 yd = chr->y() - y();
|
||||
|
||||
Core::Vec2d delta = oldpos.xy() - pos2d();
|
||||
switch ( dir )
|
||||
{
|
||||
case LEFT:
|
||||
chr->setposition( Core::Pos4d( x() + yd, y() - xd, chr->z(), chr->realm() ) );
|
||||
chr->facing = static_cast<Core::UFACING>( ( chr->facing + 6 ) & 7 );
|
||||
delta = Core::Vec2d( delta.y(), -delta.x() );
|
||||
break;
|
||||
case AROUND:
|
||||
chr->setposition( Core::Pos4d( x() - xd, y() - yd, chr->z(), chr->realm() ) );
|
||||
chr->facing = static_cast<Core::UFACING>( ( chr->facing + 4 ) & 7 );
|
||||
delta.x( -delta.x() ).y( -delta.y() );
|
||||
break;
|
||||
case RIGHT:
|
||||
chr->setposition( Core::Pos4d( x() - yd, y() + xd, chr->z(), chr->realm() ) );
|
||||
chr->facing = static_cast<Core::UFACING>( ( chr->facing + 2 ) & 7 );
|
||||
delta = Core::Vec2d( -delta.y(), delta.x() );
|
||||
break;
|
||||
case NO_TURN:
|
||||
break;
|
||||
return oldpos;
|
||||
}
|
||||
return pos() + delta;
|
||||
}
|
||||
|
||||
u8 UBoat::turn_facing( u8 oldfacing, RELATIVE_DIR dir ) const
|
||||
{
|
||||
return ( ( dir * 2 ) + oldfacing ) & 7;
|
||||
}
|
||||
|
||||
void UBoat::turn_travellers( RELATIVE_DIR dir, const BoatContext& oldlocation )
|
||||
|
|
@ -960,17 +915,17 @@ void UBoat::turn_travellers( RELATIVE_DIR dir, const BoatContext& oldlocation )
|
|||
}
|
||||
|
||||
obj->set_dirty();
|
||||
Core::Pos4d oldpos = obj->pos();
|
||||
obj->setposition( turn_coords( oldpos, dir ) );
|
||||
if ( obj->ismobile() )
|
||||
{
|
||||
Mobile::Character* chr = static_cast<Mobile::Character*>( obj );
|
||||
chr->lastpos = oldpos;
|
||||
chr->setfacing( turn_facing( chr->facing, dir ) );
|
||||
if ( chr->logged_in() )
|
||||
{
|
||||
// send_remove_character_to_nearby( chr );
|
||||
|
||||
Core::Pos4d oldpos = chr->pos();
|
||||
turn_traveller_coords( chr, dir );
|
||||
|
||||
|
||||
Core::MoveCharacterWorldPosition( oldpos, chr );
|
||||
chr->position_changed();
|
||||
if ( chr->client != nullptr )
|
||||
|
|
@ -999,41 +954,10 @@ void UBoat::turn_travellers( RELATIVE_DIR dir, const BoatContext& oldlocation )
|
|||
// deletes.
|
||||
// chr->lasty = ~ (unsigned short) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
turn_traveller_coords( chr, dir );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Items::Item* item = static_cast<Items::Item*>( obj );
|
||||
s16 xd = item->x() - x();
|
||||
s16 yd = item->y() - y();
|
||||
u16 newx( 0 );
|
||||
u16 newy( 0 );
|
||||
switch ( dir )
|
||||
{
|
||||
case NO_TURN:
|
||||
newx = item->x();
|
||||
newy = item->y();
|
||||
break;
|
||||
case LEFT:
|
||||
newx = x() + yd;
|
||||
newy = y() - xd;
|
||||
break;
|
||||
case AROUND:
|
||||
newx = x() - xd;
|
||||
newy = y() - yd;
|
||||
break;
|
||||
case RIGHT:
|
||||
newx = x() - yd;
|
||||
newy = y() + xd;
|
||||
break;
|
||||
}
|
||||
item->set_dirty();
|
||||
|
||||
Core::Pos4d oldpos = item->pos();
|
||||
item->setposition( Core::Pos4d( item->pos() ).x( newx ).y( newy ) );
|
||||
|
||||
if ( Core::settingsManager.ssopt.refresh_decay_after_boat_moves )
|
||||
item->restart_decay_timer();
|
||||
|
|
@ -1290,64 +1214,60 @@ bool UBoat::move( Core::UFACING dir, u8 speed, bool relative )
|
|||
|
||||
auto newpos = pos().move( move_dir );
|
||||
|
||||
if ( navigable( multidef(), newpos ) )
|
||||
{
|
||||
BoatContext bc( *this );
|
||||
|
||||
send_smooth_move_to_inrange( move_dir, speed, newpos.x(), newpos.y(), relative );
|
||||
|
||||
set_dirty();
|
||||
|
||||
move_multi_in_world( x(), y(), newpos.x(), newpos.y(), this, realm() );
|
||||
|
||||
const Core::Pos4d oldpos = pos();
|
||||
setposition( newpos );
|
||||
|
||||
// NOTE, send_boat_to_inrange pauses those it sends to.
|
||||
// send_boat_to_inrange( this, oldx, oldy );
|
||||
move_travellers( move_dir, bc, x(), y(), realm() );
|
||||
move_components( realm() );
|
||||
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
this,
|
||||
[&]( Mobile::Character* zonechr )
|
||||
{
|
||||
Network::Client* client = zonechr->client;
|
||||
if ( !zonechr->in_visual_range( this ) )
|
||||
return;
|
||||
if ( client->ClientType & Network::CLIENTTYPE_7090 )
|
||||
{
|
||||
if ( zonechr->in_visual_range( this, oldpos ) )
|
||||
return;
|
||||
else
|
||||
send_boat_newly_inrange( client ); // send HSA packet only for newly inrange
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( client->ClientType & Network::CLIENTTYPE_7000 )
|
||||
send_boat( client ); // Send
|
||||
else
|
||||
send_boat_old( client );
|
||||
}
|
||||
} );
|
||||
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
oldpos,
|
||||
[&]( Mobile::Character* zonechr )
|
||||
{
|
||||
if ( zonechr->in_visual_range( this, oldpos ) &&
|
||||
!zonechr->in_visual_range( this ) ) // send remove to chrs only seeing the old loc
|
||||
send_remove_boat( zonechr->client );
|
||||
} );
|
||||
|
||||
do_tellmoves();
|
||||
unpause_paused();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !navigable( multidef(), newpos ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
BoatContext bc( *this );
|
||||
|
||||
send_smooth_move_to_inrange( move_dir, speed, newpos, relative );
|
||||
|
||||
set_dirty();
|
||||
|
||||
move_multi_in_world( x(), y(), newpos.x(), newpos.y(), this, realm() );
|
||||
|
||||
const Core::Pos4d oldpos = pos();
|
||||
setposition( newpos );
|
||||
|
||||
// NOTE, send_boat_to_inrange pauses those it sends to.
|
||||
// send_boat_to_inrange( this, oldx, oldy );
|
||||
move_travellers( move_dir, bc, x(), y(), realm() );
|
||||
move_components( realm() );
|
||||
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
this,
|
||||
[&]( Mobile::Character* zonechr )
|
||||
{
|
||||
Network::Client* client = zonechr->client;
|
||||
if ( !zonechr->in_visual_range( this ) )
|
||||
return;
|
||||
if ( client->ClientType & Network::CLIENTTYPE_7090 )
|
||||
{
|
||||
if ( zonechr->in_visual_range( this, oldpos ) )
|
||||
return; // TODO POS: better place for smooth move
|
||||
else
|
||||
send_boat_newly_inrange( client ); // send HSA packet only for newly inrange
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( client->ClientType & Network::CLIENTTYPE_7000 )
|
||||
send_boat( client ); // Send
|
||||
else
|
||||
send_boat_old( client );
|
||||
}
|
||||
} );
|
||||
|
||||
Core::WorldIterator<Core::OnlinePlayerFilter>::InMaxVisualRange(
|
||||
oldpos,
|
||||
[&]( Mobile::Character* zonechr )
|
||||
{
|
||||
if ( zonechr->in_visual_range( this, oldpos ) &&
|
||||
!zonechr->in_visual_range( this ) ) // send remove to chrs only seeing the old loc
|
||||
send_remove_boat( zonechr->client );
|
||||
} );
|
||||
|
||||
do_tellmoves();
|
||||
unpause_paused();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned short UBoat::multiid_ifturn( RELATIVE_DIR dir )
|
||||
|
|
@ -1418,8 +1338,7 @@ void UBoat::transform_components( const BoatShape& old_boatshape, Realms::Realm*
|
|||
|
||||
Core::Pos4d oldpos = item->pos();
|
||||
|
||||
item->setposition(
|
||||
pos() + Core::Vec3d( itr2->xdelta, itr2->ydelta, static_cast<s8>( itr2->zdelta ) ) );
|
||||
item->setposition( pos() + itr2->delta );
|
||||
|
||||
MoveItemWorldPosition( oldpos, item );
|
||||
|
||||
|
|
@ -1483,8 +1402,7 @@ void UBoat::move_components( Realms::Realm* /*oldrealm*/ )
|
|||
item->set_dirty();
|
||||
Core::Pos4d oldpos = item->pos();
|
||||
|
||||
item->setposition(
|
||||
pos() + Core::Vec3d( itr2->xdelta, itr2->ydelta, static_cast<s8>( itr2->zdelta ) ) );
|
||||
item->setposition( pos() + itr2->delta );
|
||||
|
||||
MoveItemWorldPosition( oldpos, item );
|
||||
|
||||
|
|
@ -1535,7 +1453,7 @@ bool UBoat::turn( RELATIVE_DIR dir )
|
|||
send_display_boat_to_inrange( x(), y() );
|
||||
do_tellmoves();
|
||||
unpause_paused();
|
||||
facing = ( ( dir * 2 ) + facing ) & 7;
|
||||
facing = turn_facing( facing, dir );
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
|
|
@ -1830,8 +1748,7 @@ void UBoat::create_components()
|
|||
component->graphic = itr->graphic;
|
||||
// component itemdesc entries generally have graphic=1, so they don't get their height set.
|
||||
component->height = Plib::tileheight( component->graphic );
|
||||
component->setposition(
|
||||
pos() + Core::Vec3d( itr->xdelta, itr->ydelta, static_cast<s8>( itr->zdelta ) ) );
|
||||
component->setposition( pos() + itr->delta );
|
||||
component->disable_decay();
|
||||
component->movable( false );
|
||||
add_item_to_world( component );
|
||||
|
|
|
|||
|
|
@ -77,9 +77,7 @@ struct BoatShape
|
|||
unsigned int objtype;
|
||||
unsigned short graphic;
|
||||
unsigned short altgraphic;
|
||||
unsigned short xdelta;
|
||||
unsigned short ydelta;
|
||||
signed short zdelta;
|
||||
Core::Vec3d delta;
|
||||
ComponentShape( const std::string& str, const std::string& altstr, unsigned char type );
|
||||
ComponentShape( const std::string& str, unsigned char type );
|
||||
};
|
||||
|
|
@ -99,10 +97,9 @@ class UBoat final : public UMulti
|
|||
class BoatContext
|
||||
{
|
||||
const MultiDef& mdef;
|
||||
unsigned short x; // TODO Pos2d
|
||||
unsigned short y;
|
||||
Core::Pos4d oldpos;
|
||||
|
||||
explicit BoatContext( const UBoat& ub ) : mdef( ub.multidef() ), x( ub.x() ), y( ub.y() ){};
|
||||
explicit BoatContext( const UBoat& ub ) : mdef( ub.multidef() ), oldpos( ub.pos() ){};
|
||||
friend class UBoat;
|
||||
BoatContext& operator=( const BoatContext& ) { return *this; }
|
||||
};
|
||||
|
|
@ -130,7 +127,7 @@ public:
|
|||
bool move( Core::UFACING dir, u8 speed, bool relative );
|
||||
bool move_xy( const Core::Pos2d& newp, int flags, Realms::Realm* oldrealm );
|
||||
|
||||
enum RELATIVE_DIR
|
||||
enum RELATIVE_DIR // order matters! facing = ( ( dir * 2 ) + facing ) & 7;
|
||||
{
|
||||
NO_TURN,
|
||||
RIGHT,
|
||||
|
|
@ -143,10 +140,6 @@ public:
|
|||
virtual void unregister_object( Core::UObject* obj ) override;
|
||||
Core::UFACING boat_facing() const;
|
||||
|
||||
void send_smooth_move( Network::Client* client, Core::UFACING move_dir, u8 speed, u16 newx,
|
||||
u16 newy, bool relative );
|
||||
void send_smooth_move_to_inrange( Core::UFACING move_dir, u8 speed, u16 newx, u16 newy,
|
||||
bool relative );
|
||||
void send_display_boat( Network::Client* client );
|
||||
void send_display_boat_to_inrange( u16 oldx = USHRT_MAX, u16 oldy = USHRT_MAX );
|
||||
void send_boat( Network::Client* client );
|
||||
|
|
@ -192,7 +185,6 @@ protected:
|
|||
unsigned short x = USHRT_MAX, unsigned short y = USHRT_MAX,
|
||||
Realms::Realm* oldrealm = nullptr );
|
||||
void turn_travellers( RELATIVE_DIR dir, const BoatContext& oldlocation );
|
||||
void turn_traveller_coords( Mobile::Character* chr, RELATIVE_DIR dir );
|
||||
static bool on_ship( const BoatContext& bc, const Core::UObject* obj );
|
||||
void move_offline_mobiles( const Core::Pos4d& newpos );
|
||||
const MultiDef& multi_ifturn( RELATIVE_DIR dir );
|
||||
|
|
@ -226,6 +218,13 @@ protected:
|
|||
friend struct BoatMoveGuard;
|
||||
|
||||
private:
|
||||
void send_smooth_move( Network::Client* client, Core::UFACING move_dir, u8 speed,
|
||||
const Core::Pos4d& newpos, bool relative ) const;
|
||||
void send_smooth_move_to_inrange( Core::UFACING move_dir, u8 speed, const Core::Pos4d& newpos,
|
||||
bool relative ) const;
|
||||
|
||||
Core::Pos4d turn_coords( const Core::Pos4d& oldpos, RELATIVE_DIR dir ) const;
|
||||
u8 turn_facing( u8 oldfacing, RELATIVE_DIR dir ) const;
|
||||
void create_components();
|
||||
typedef Core::UObjectRef Traveller;
|
||||
typedef std::vector<Traveller> Travellers;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ exported function create()
|
|||
DestroyMulti(res);
|
||||
return ret_error(er);
|
||||
endif
|
||||
if (res.portplank.x != 10 || res.portplank.y != 48 || res.portplank.z != -4)
|
||||
var er:="Wrong portplank pos: {},{},{}".format(res.portplank.x, res.portplank.y, res.portplank.z);
|
||||
DestroyMulti(res);
|
||||
return ret_error(er);
|
||||
endif
|
||||
|
||||
for i:=1 to 5
|
||||
sleepms(10);
|
||||
if (res.getprop("started"))
|
||||
|
|
@ -269,3 +275,76 @@ endfunction
|
|||
DestroyMulti(boat);
|
||||
return 1;
|
||||
endfunction*/
|
||||
|
||||
exported function test_boat_turn_travellers()
|
||||
var boat:=CreateMultiAtLocation(10,50,-4,0x11000, CRMULTI_FACING_EAST);
|
||||
if (!boat)
|
||||
return ret_error("Failed to create boat "+boat);
|
||||
endif
|
||||
var item:=CreateItemAtLocation(10,51,0,0xf3f);
|
||||
if (!item)
|
||||
DestroyMulti(boat);
|
||||
return ret_error($"Failed to create item {item}");
|
||||
endif
|
||||
var npc := CreateNPCFromTemplate( ":testnpc:probe_npc", 9, 50, 0 );
|
||||
if ( !npc )
|
||||
DestroyItem(item);
|
||||
DestroyMulti(boat);
|
||||
return ret_error( $"Failed to create npc: {npc}" );
|
||||
endif
|
||||
var checks:={
|
||||
{1,4, 9,50, 10,49}, // right
|
||||
{3,2, 10,51, 9,50}, // left
|
||||
{2,6, 10,49, 11,50}, // around
|
||||
{0,6, 10,49, 11,50} // nothing
|
||||
};
|
||||
var result:=1;
|
||||
foreach check in checks
|
||||
var res:=TurnBoat(boat,check[1]);
|
||||
if (!res)
|
||||
result:=ret_error($"Failed to turn {check} {res}");
|
||||
break;
|
||||
endif
|
||||
if (boat.facing != check[2] || item.x != check[3] || item.y != check[4] || npc.x != check[5] || npc.y != check[6])
|
||||
result := ret_error($"Check failed {check}: facing {boat.facing} item {item.x},{item.y} npc {npc.x},{npc.y}");
|
||||
break;
|
||||
endif
|
||||
endforeach
|
||||
MoveObjectToLocation( npc, 100, 100, 0, flags := MOVEOBJECT_FORCELOCATION );
|
||||
npc.kill();
|
||||
DestroyItem(item);
|
||||
DestroyMulti(boat);
|
||||
return result;
|
||||
endfunction
|
||||
|
||||
exported function test_boat_move_travellers()
|
||||
var boat:=CreateMultiAtLocation(10,50,-4,0x11000, CRMULTI_FACING_EAST);
|
||||
if (!boat)
|
||||
return ret_error("Failed to create boat "+boat);
|
||||
endif
|
||||
var item:=CreateItemAtLocation(10,51,0,0xf3f);
|
||||
if (!item)
|
||||
DestroyMulti(boat);
|
||||
return ret_error($"Failed to create item {item}");
|
||||
endif
|
||||
var npc := CreateNPCFromTemplate( ":testnpc:probe_npc", 9, 50, 0 );
|
||||
if ( !npc )
|
||||
DestroyItem(item);
|
||||
DestroyMulti(boat);
|
||||
return ret_error( $"Failed to create npc: {npc}" );
|
||||
endif
|
||||
var result:=1;
|
||||
var res:=MoveBoat(boat,0);
|
||||
if (!res)
|
||||
result:=ret_error($"Failed to move {res}");
|
||||
else
|
||||
if ( item.x != 10 || item.y != 50 || npc.x != 9 || npc.y != 49)
|
||||
result := ret_error($"Move failed: item {item.x},{item.y} npc {npc.x},{npc.y}");
|
||||
endif
|
||||
endif
|
||||
MoveObjectToLocation( npc, 100, 100, 0, flags := MOVEOBJECT_FORCELOCATION );
|
||||
npc.kill();
|
||||
DestroyItem(item);
|
||||
DestroyMulti(boat);
|
||||
return result;
|
||||
endfunction
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue