2016-01-28 14:52:40 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
* - 2009/09/01 Turley: VS2005/2008 Support moved inline MultiDef::getkey to .h
|
|
|
|
|
* - 2009/09/03 MuadDib: Relocation of multi related cpp/h
|
|
|
|
|
*/
|
2015-01-19 18:18:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "multidef.h"
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <cstdio>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <string>
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../../bscript/bstruct.h"
|
2015-01-19 18:18:21 +01:00
|
|
|
#include "../../clib/cfgelem.h"
|
|
|
|
|
#include "../../clib/cfgfile.h"
|
|
|
|
|
#include "../../clib/passert.h"
|
|
|
|
|
#include "../../clib/strutil.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../globals/multidefs.h"
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Multi
|
|
|
|
|
{
|
|
|
|
|
bool BoatShapeExists( u16 graphic );
|
|
|
|
|
|
|
|
|
|
MultiDef::MultiDef( Clib::ConfigElem& elem, u16 multiid )
|
|
|
|
|
: multiid( multiid ),
|
|
|
|
|
type( UNKNOWN ),
|
|
|
|
|
elems(),
|
|
|
|
|
|
2021-11-09 20:01:16 +01:00
|
|
|
minrxyz(),
|
2023-12-25 22:02:52 +01:00
|
|
|
maxrxyz(),
|
|
|
|
|
max_radius( 0 )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
if ( elem.type_is( "BOAT" ) )
|
|
|
|
|
{
|
|
|
|
|
if ( !BoatShapeExists( multiid ) )
|
|
|
|
|
elem.throw_error( "Entry for Boat (multiid " + Clib::hexint( multiid ) +
|
|
|
|
|
") not found in boats.cfg" );
|
|
|
|
|
type = BOAT;
|
|
|
|
|
}
|
|
|
|
|
else if ( elem.type_is( "HOUSE" ) )
|
|
|
|
|
{
|
|
|
|
|
type = HOUSE;
|
|
|
|
|
}
|
|
|
|
|
else if ( elem.type_is( "STAIRS" ) )
|
|
|
|
|
{
|
|
|
|
|
type = STAIRS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string tmp;
|
|
|
|
|
while ( elem.remove_prop( "static", &tmp ) )
|
|
|
|
|
{
|
|
|
|
|
std::istringstream is( tmp );
|
|
|
|
|
MULTI_ELEM multielem;
|
|
|
|
|
multielem.is_static = true;
|
2021-11-09 20:01:16 +01:00
|
|
|
s16 x, y, z;
|
|
|
|
|
if ( is >> std::hex >> multielem.objtype >> std::dec >> x >> y >> z )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
multielem.relpos.x( x ).y( y ).z( z );
|
2016-02-19 19:26:35 +01:00
|
|
|
elems.push_back( multielem );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::string message = "Badly formed static directive: '" + tmp + "'";
|
|
|
|
|
elem.throw_error( message );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while ( elem.remove_prop( "dynamic", &tmp ) )
|
|
|
|
|
{
|
|
|
|
|
std::istringstream is( tmp );
|
|
|
|
|
MULTI_ELEM multielem;
|
|
|
|
|
multielem.is_static = false;
|
2021-11-09 20:01:16 +01:00
|
|
|
s16 x, y, z;
|
|
|
|
|
if ( is >> std::hex >> multielem.objtype >> std::dec >> x >> y >> z )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
multielem.relpos.x( x ).y( y ).z( z );
|
2016-02-19 19:26:35 +01:00
|
|
|
elems.push_back( multielem );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::string message = "Badly formed dynamic directive: '" + tmp + "'";
|
|
|
|
|
elem.throw_error( message );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MultiDef::findcomponents( Components::const_iterator& beg, Components::const_iterator& end,
|
2021-11-09 20:01:16 +01:00
|
|
|
const Core::Vec2d& rxy ) const
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
ItrPair pr = components.equal_range( getkey( rxy ) );
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( pr.first == components.end() )
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
beg = pr.first;
|
|
|
|
|
end = pr.second;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 20:01:16 +01:00
|
|
|
bool MultiDef::body_contains( const Core::Vec2d& rxy ) const
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
return ( components.count( getkey( rxy ) ) != 0 );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2021-11-09 20:01:16 +01:00
|
|
|
const MULTI_ELEM* MultiDef::find_component( const Core::Vec2d& rxy ) const
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
if ( body_contains( rxy ) )
|
|
|
|
|
return ( *components.find( getkey( rxy ) ) ).second;
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
2018-07-31 14:30:29 +02:00
|
|
|
return nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiDef::add_to_hull( const MULTI_ELEM* elem )
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
unsigned short k = getkey( elem->relpos.xy() );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
if ( !hull2.count( k ) )
|
|
|
|
|
{
|
|
|
|
|
hull.push_back( elem );
|
|
|
|
|
hull2.insert( k );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( type == BOAT )
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
Core::Vec2d rxy = elem->relpos.xy();
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( ( multiid & 1 ) == 0 ) // N/S hull, so squeeze X
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
if ( rxy.x() == minrxyz.x() )
|
|
|
|
|
rxy.x( minrxyz.x() + 1 );
|
|
|
|
|
else if ( rxy.x() == maxrxyz.x() )
|
|
|
|
|
rxy.x( maxrxyz.x() - 1 );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
if ( rxy.y() == minrxyz.y() )
|
|
|
|
|
rxy.y( minrxyz.y() + 1 );
|
|
|
|
|
else if ( rxy.y() > 0 )
|
|
|
|
|
rxy.y( maxrxyz.y() - 1 );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2021-11-09 20:01:16 +01:00
|
|
|
elem = find_component( rxy );
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( elem )
|
|
|
|
|
add_to_internal_hull( elem );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiDef::add_to_internal_hull( const MULTI_ELEM* elem )
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
unsigned short k = getkey( elem->relpos.xy() );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
if ( !internal_hull2.count( k ) )
|
|
|
|
|
{
|
|
|
|
|
internal_hull.push_back( elem );
|
|
|
|
|
internal_hull2.insert( k );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiDef::add_body_tohull()
|
|
|
|
|
{
|
|
|
|
|
short rx, ry;
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( ry = minrxyz.y(); ry <= maxrxyz.y(); ++ry )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( rx = minrxyz.x(); rx <= maxrxyz.x(); ++rx )
|
2015-01-19 18:18:21 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
const MULTI_ELEM* elem = find_component( Core::Vec2d( rx, ry ) );
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( elem != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
add_to_hull( elem );
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( rx = maxrxyz.x(); rx >= minrxyz.x(); --rx )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
const MULTI_ELEM* elem = find_component( Core::Vec2d( rx, ry ) );
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( elem != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
add_to_hull( elem );
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
|
|
|
|
|
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( rx = minrxyz.x(); rx <= maxrxyz.x(); ++rx )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( ry = minrxyz.y(); ry <= maxrxyz.y(); ++ry )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
const MULTI_ELEM* elem = find_component( Core::Vec2d( rx, ry ) );
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( elem != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
add_to_hull( elem );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
}
|
2021-11-09 20:01:16 +01:00
|
|
|
for ( ry = maxrxyz.y(); ry >= minrxyz.y(); --ry )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
const MULTI_ELEM* elem = find_component( Core::Vec2d( rx, ry ) );
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( elem != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
add_to_hull( elem );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MultiDef::computehull()
|
|
|
|
|
{
|
|
|
|
|
add_body_tohull();
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void MultiDef::addrec( const MULTI_ELEM* elem )
|
|
|
|
|
{
|
2021-11-09 20:01:16 +01:00
|
|
|
minrxyz.x( std::min( minrxyz.x(), elem->relpos.x() ) )
|
|
|
|
|
.y( std::min( minrxyz.y(), elem->relpos.y() ) )
|
|
|
|
|
.z( std::min( minrxyz.z(), elem->relpos.z() ) );
|
|
|
|
|
maxrxyz.x( std::max( maxrxyz.x(), elem->relpos.x() ) )
|
|
|
|
|
.y( std::max( maxrxyz.y(), elem->relpos.y() ) )
|
|
|
|
|
.z( std::max( maxrxyz.z(), elem->relpos.z() ) );
|
2023-12-25 22:02:52 +01:00
|
|
|
max_radius = (u8)std::max( { std::abs( minrxyz.x() ), std::abs( minrxyz.y() ),
|
|
|
|
|
std::abs( maxrxyz.x() ), std::abs( maxrxyz.y() ) } );
|
2021-11-09 20:01:16 +01:00
|
|
|
components.insert( Components::value_type( getkey( elem->relpos.xy() ), elem ) );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiDef::init()
|
|
|
|
|
{
|
|
|
|
|
for ( unsigned i = 0; i < elems.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
addrec( &elems[i] );
|
|
|
|
|
}
|
|
|
|
|
computehull();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 20:01:16 +01:00
|
|
|
bool MultiDef::within_multi( const Core::Vec2d& relxy ) const
|
|
|
|
|
{
|
|
|
|
|
return relxy.x() >= minrxyz.x() && relxy.x() <= maxrxyz.x() && relxy.y() >= minrxyz.y() &&
|
|
|
|
|
relxy.y() <= maxrxyz.y();
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
size_t MultiDef::estimateSize() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = sizeof( MultiDef );
|
|
|
|
|
size += 3 * sizeof( MULTI_ELEM* ) + elems.capacity() * sizeof( MULTI_ELEM );
|
|
|
|
|
size += 3 * sizeof( MULTI_ELEM** ) + hull.capacity() * sizeof( MULTI_ELEM* );
|
|
|
|
|
size += 3 * sizeof( MULTI_ELEM** ) + internal_hull.capacity() * sizeof( MULTI_ELEM* );
|
|
|
|
|
|
|
|
|
|
size += 3 * sizeof( void* ) + hull2.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
|
|
|
|
|
size += 3 * sizeof( void* ) +
|
|
|
|
|
internal_hull2.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
|
|
|
|
|
|
|
|
|
|
size += ( sizeof( unsigned short ) + sizeof( MULTI_ELEM* ) + ( sizeof( void* ) * 3 + 1 ) / 2 ) *
|
|
|
|
|
components.size();
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MultiDefByMultiIDExists( u16 multiid )
|
|
|
|
|
{
|
|
|
|
|
return multidef_buffer.multidefs_by_multiid.count( multiid ) != 0;
|
|
|
|
|
}
|
|
|
|
|
const MultiDef* MultiDefByMultiID( u16 multiid )
|
|
|
|
|
{
|
|
|
|
|
passert( multidef_buffer.multidefs_by_multiid.count( multiid ) != 0 );
|
|
|
|
|
|
|
|
|
|
MultiDefs::const_iterator citr = multidef_buffer.multidefs_by_multiid.find( multiid );
|
|
|
|
|
if ( citr != multidef_buffer.multidefs_by_multiid.end() )
|
|
|
|
|
return ( *citr ).second;
|
|
|
|
|
else
|
2018-07-31 14:30:29 +02:00
|
|
|
return nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void read_multidefs()
|
|
|
|
|
{
|
|
|
|
|
Clib::ConfigFile cf( "config/multis.cfg", "BOAT HOUSE STAIRS" );
|
|
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
while ( cf.read( elem ) )
|
|
|
|
|
{
|
2018-07-31 14:30:29 +02:00
|
|
|
u16 multiid = static_cast<u16>( strtoul( elem.rest(), nullptr, 0 ) );
|
2016-02-19 19:26:35 +01:00
|
|
|
MultiDef* mdef = new MultiDef( elem, multiid );
|
|
|
|
|
mdef->init();
|
|
|
|
|
|
|
|
|
|
multidef_buffer.multidefs_by_multiid[mdef->multiid] = mdef;
|
2015-01-19 18:18:21 +01:00
|
|
|
}
|
2015-11-10 23:47:14 +01:00
|
|
|
}
|
2021-11-09 20:01:16 +01:00
|
|
|
} // namespace Multi
|
|
|
|
|
} // namespace Pol
|