2010-03-13 23:00:01 +01:00
// ==============================================================
2010-03-21 06:33:13 +01:00
// ==============================================================
2010-03-13 23:00:01 +01:00
// This file is part of Glest (www.glest.org)
//
2010-04-03 06:30:28 +02:00
// Copyright (C) 2001-2008 Martio Figueroa
2010-03-13 23:00:01 +01:00
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
# include "map.h"
# include <cassert>
# include "tileset.h"
# include "unit.h"
# include "resource.h"
# include "logger.h"
# include "tech_tree.h"
# include "config.h"
2010-03-21 06:33:13 +01:00
# include "util.h"
# include "game_settings.h"
# include "platform_util.h"
2010-07-11 20:31:02 +02:00
# include "pos_iterator.h"
2010-10-20 00:26:49 +02:00
# include "faction.h"
# include "command.h"
2010-03-13 23:00:01 +01:00
# include "leak_dumper.h"
2011-02-08 04:50:59 +01:00
# include "map_preview.h"
2011-01-20 16:56:30 +01:00
2010-03-13 23:00:01 +01:00
using namespace Shared : : Graphics ;
using namespace Shared : : Util ;
2010-03-21 06:33:13 +01:00
using namespace Shared : : Platform ;
2010-03-13 23:00:01 +01:00
namespace Glest { namespace Game {
// =====================================================
// class Cell
// =====================================================
2010-10-30 10:54:00 +02:00
Cell : : Cell ( ) {
2010-03-13 23:00:01 +01:00
//game data
2010-10-30 10:54:00 +02:00
for ( int i = 0 ; i < fieldCount ; + + i ) {
2010-03-13 23:00:01 +01:00
units [ i ] = NULL ;
2010-10-30 10:54:00 +02:00
unitsWithEmptyCellMap [ i ] = NULL ;
2010-03-13 23:00:01 +01:00
}
height = 0 ;
}
// ==================== misc ====================
//returns if the cell is free
2010-12-19 04:30:17 +01:00
bool Cell : : isFree ( Field field ) const {
2011-09-27 01:55:18 +02:00
bool result = getUnit ( field ) = = NULL | | getUnit ( field ) - > isPutrefacting ( ) ;
if ( result = = false ) {
//printf("[%s] Line: %d returning false, unit id = %d [%s]\n",__FUNCTION__,__LINE__,getUnit(field)->getId(),getUnit(field)->getType()->getName().c_str());
}
return result ;
}
//returns if the cell is free
bool Cell : : isFreeOrMightBeFreeSoon ( Vec2i originPos , Vec2i cellPos , Field field ) const {
bool result = getUnit ( field ) = = NULL | | getUnit ( field ) - > isPutrefacting ( ) ;
if ( result = = false ) {
if ( originPos . dist ( cellPos ) > 5 & & getUnit ( field ) - > getType ( ) - > isMobile ( ) = = true ) {
result = true ;
}
//printf("[%s] Line: %d returning false, unit id = %d [%s]\n",__FUNCTION__,__LINE__,getUnit(field)->getId(),getUnit(field)->getType()->getName().c_str());
}
return result ;
2010-03-13 23:00:01 +01:00
}
// =====================================================
// class SurfaceCell
// =====================================================
2010-12-19 04:30:17 +01:00
SurfaceCell : : SurfaceCell ( ) {
2010-03-13 23:00:01 +01:00
object = NULL ;
vertex = Vec3f ( 0.f ) ;
normal = Vec3f ( 0.f , 1.f , 0.f ) ;
surfaceType = - 1 ;
surfaceTexture = NULL ;
2011-03-23 06:49:38 +01:00
nearSubmerged = false ;
2011-09-01 03:11:23 +02:00
for ( int i = 0 ; i < GameConstants : : maxPlayers + GameConstants : : specialFactions ; + + i ) {
visible [ i ] = false ;
explored [ i ] = false ;
}
2010-03-13 23:00:01 +01:00
}
2010-12-19 04:30:17 +01:00
SurfaceCell : : ~ SurfaceCell ( ) {
2010-03-13 23:00:01 +01:00
delete object ;
}
2011-03-06 23:50:04 +01:00
void SurfaceCell : : end ( ) {
if ( object ! = NULL ) {
object - > end ( ) ;
}
}
2010-12-19 04:30:17 +01:00
bool SurfaceCell : : isFree ( ) const {
2011-09-27 01:55:18 +02:00
bool result = object = = NULL | | object - > getWalkable ( ) ;
if ( result = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
}
return result ;
2010-03-13 23:00:01 +01:00
}
2010-12-19 04:30:17 +01:00
void SurfaceCell : : deleteResource ( ) {
2010-03-13 23:00:01 +01:00
delete object ;
object = NULL ;
}
2010-12-19 04:30:17 +01:00
void SurfaceCell : : setExplored ( int teamIndex , bool explored ) {
2010-03-13 23:00:01 +01:00
this - > explored [ teamIndex ] = explored ;
}
2010-12-19 04:30:17 +01:00
void SurfaceCell : : setVisible ( int teamIndex , bool visible ) {
2010-03-13 23:00:01 +01:00
this - > visible [ teamIndex ] = visible ;
}
// =====================================================
// class Map
// =====================================================
// ===================== PUBLIC ========================
const int Map : : cellScale = 2 ;
const int Map : : mapScale = 2 ;
2010-12-19 04:30:17 +01:00
Map : : Map ( ) {
2010-03-13 23:00:01 +01:00
cells = NULL ;
surfaceCells = NULL ;
startLocations = NULL ;
2011-02-12 08:34:32 +01:00
title = " " ;
waterLevel = 0 ;
heightFactor = 0 ;
cliffLevel = 0 ;
2011-02-25 01:31:42 +01:00
cameraHeight = 0 ;
2011-02-12 08:34:32 +01:00
w = 0 ;
h = 0 ;
surfaceW = 0 ;
surfaceH = 0 ;
maxPlayers = 0 ;
maxMapHeight = 0 ;
2010-03-13 23:00:01 +01:00
}
2010-12-19 04:30:17 +01:00
Map : : ~ Map ( ) {
2011-11-04 02:12:05 +01:00
Logger : : getInstance ( ) . add ( Lang : : getInstance ( ) . get ( " LogScreenGameUnLoadingMapCells " , " " , true ) , true ) ;
2010-03-13 23:00:01 +01:00
delete [ ] cells ;
2010-11-01 17:44:05 +01:00
cells = NULL ;
2010-03-13 23:00:01 +01:00
delete [ ] surfaceCells ;
2010-11-01 17:44:05 +01:00
surfaceCells = NULL ;
2010-03-13 23:00:01 +01:00
delete [ ] startLocations ;
2010-11-01 17:44:05 +01:00
startLocations = NULL ;
}
2011-03-06 23:50:04 +01:00
void Map : : end ( ) {
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugSystem ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-11-04 02:12:05 +01:00
Logger : : getInstance ( ) . add ( Lang : : getInstance ( ) . get ( " LogScreenGameUnLoadingMap " , " " , true ) , true ) ;
2011-03-06 23:50:04 +01:00
//read heightmap
for ( int j = 0 ; j < surfaceH ; + + j ) {
for ( int i = 0 ; i < surfaceW ; + + i ) {
getSurfaceCell ( i , j ) - > end ( ) ;
}
}
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugSystem ) . enabled ) SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2011-03-06 23:50:04 +01:00
}
2010-11-01 17:44:05 +01:00
int Map : : getSurfaceCellArraySize ( ) const {
return ( surfaceW * surfaceH ) ;
}
2011-02-23 08:03:38 +01:00
SurfaceCell * Map : : getSurfaceCell ( const Vec2i & sPos ) const {
return getSurfaceCell ( sPos . x , sPos . y ) ;
}
2010-11-01 17:44:05 +01:00
SurfaceCell * Map : : getSurfaceCell ( int sx , int sy ) const {
int arrayIndex = sy * surfaceW + sx ;
2011-02-23 08:03:38 +01:00
if ( arrayIndex < 0 | | arrayIndex > = getSurfaceCellArraySize ( ) ) {
2011-04-28 00:35:45 +02:00
throw runtime_error ( " arrayIndex >= getSurfaceCellArraySize(), arrayIndex = " + intToStr ( arrayIndex ) +
" surfaceW = " + intToStr ( surfaceW ) + " surfaceH = " + intToStr ( surfaceH ) +
" sx: " + intToStr ( sx ) + " sy: " + intToStr ( sy ) ) ;
2010-11-01 17:44:05 +01:00
}
else if ( surfaceCells = = NULL ) {
throw runtime_error ( " surfaceCells == NULL " ) ;
}
return & surfaceCells [ arrayIndex ] ;
}
int Map : : getCellArraySize ( ) const {
return ( w * h ) ;
}
2011-02-23 08:03:38 +01:00
Cell * Map : : getCell ( const Vec2i & pos ) const {
return getCell ( pos . x , pos . y ) ;
}
2010-11-01 17:44:05 +01:00
Cell * Map : : getCell ( int x , int y ) const {
int arrayIndex = y * w + x ;
2011-02-23 08:03:38 +01:00
if ( arrayIndex < 0 | | arrayIndex > = getCellArraySize ( ) ) {
2011-02-23 00:59:21 +01:00
//abort();
throw runtime_error ( " arrayIndex >= getCellArraySize() , arrayIndex = " + intToStr(arrayIndex) + " w = " + intToStr(w) + " h = " + intToStr(h)) ;
2010-11-01 17:44:05 +01:00
}
else if ( cells = = NULL ) {
throw runtime_error ( " cells == NULL " ) ;
}
return & cells [ arrayIndex ] ;
}
Vec2i Map : : getStartLocation ( int locationIndex ) const {
if ( locationIndex > = maxPlayers ) {
2011-09-14 01:20:26 +02:00
char szBuf [ 4096 ] = " " ;
sprintf ( szBuf , " locationIndex >= maxPlayers [%d] [%d] " , locationIndex , maxPlayers ) ;
printf ( " %s \n " , szBuf ) ;
//throw runtime_error(szBuf);
assert ( locationIndex < maxPlayers ) ;
2010-11-01 17:44:05 +01:00
}
else if ( startLocations = = NULL ) {
throw runtime_error ( " startLocations == NULL " ) ;
}
return startLocations [ locationIndex ] ;
2010-03-13 23:00:01 +01:00
}
2011-01-09 05:49:21 +01:00
Checksum Map : : load ( const string & path , TechTree * techTree , Tileset * tileset ) {
Checksum mapChecksum ;
2010-03-13 23:00:01 +01:00
try {
2011-05-18 23:49:11 +02:00
# ifdef WIN32
FILE * f = _wfopen ( utf8_decode ( path ) . c_str ( ) , L " rb " ) ;
# else
2011-01-09 05:49:21 +01:00
FILE * f = fopen ( path . c_str ( ) , " rb " ) ;
2011-05-18 23:49:11 +02:00
# endif
2011-01-09 05:49:21 +01:00
if ( f ! = NULL ) {
mapChecksum . addFile ( path ) ;
checksumValue . addFile ( path ) ;
2010-03-13 23:00:01 +01:00
//read header
MapFileHeader header ;
size_t readBytes = fread ( & header , sizeof ( MapFileHeader ) , 1 , f ) ;
if ( next2Power ( header . width ) ! = header . width ) {
throw runtime_error ( " Map width is not a power of 2 " ) ;
}
if ( next2Power ( header . height ) ! = header . height ) {
throw runtime_error ( " Map height is not a power of 2 " ) ;
}
2011-02-08 04:50:59 +01:00
heightFactor = header . heightFactor ;
2010-03-13 23:00:01 +01:00
waterLevel = static_cast < float > ( ( header . waterLevel - 0.01f ) / heightFactor ) ;
title = header . title ;
2011-02-08 04:50:59 +01:00
maxPlayers = header . maxFactions ;
2010-03-13 23:00:01 +01:00
surfaceW = header . width ;
surfaceH = header . height ;
w = surfaceW * cellScale ;
h = surfaceH * cellScale ;
2011-02-08 04:50:59 +01:00
cliffLevel = 0 ;
2011-02-25 01:31:42 +01:00
cameraHeight = 0 ;
2011-02-08 04:50:59 +01:00
if ( header . version = = 1 ) {
//desc = header.description;
}
else if ( header . version = = 2 ) {
2011-02-08 21:59:34 +01:00
//desc = header.version2.short_desc;
2011-02-25 23:13:11 +01:00
if ( header . version2 . cliffLevel > 0 & & header . version2 . cliffLevel < 5000 ) {
2011-02-08 21:59:34 +01:00
cliffLevel = static_cast < float > ( ( header . version2 . cliffLevel - 0.01f ) / ( heightFactor ) ) ;
2011-02-08 04:50:59 +01:00
}
2011-02-25 23:13:11 +01:00
if ( header . version2 . cameraHeight > 0 & & header . version2 . cameraHeight < 5000 )
2011-02-25 01:31:42 +01:00
{
cameraHeight = header . version2 . cameraHeight ;
2011-02-08 04:50:59 +01:00
}
}
2010-03-13 23:00:01 +01:00
//start locations
startLocations = new Vec2i [ maxPlayers ] ;
2011-01-09 05:49:21 +01:00
for ( int i = 0 ; i < maxPlayers ; + + i ) {
int x = 0 , y = 0 ;
2010-03-13 23:00:01 +01:00
readBytes = fread ( & x , sizeof ( int32 ) , 1 , f ) ;
readBytes = fread ( & y , sizeof ( int32 ) , 1 , f ) ;
startLocations [ i ] = Vec2i ( x , y ) * cellScale ;
}
//cells
2010-11-01 17:44:05 +01:00
cells = new Cell [ getCellArraySize ( ) ] ;
surfaceCells = new SurfaceCell [ getSurfaceCellArraySize ( ) ] ;
2010-03-13 23:00:01 +01:00
//read heightmap
2011-01-09 05:49:21 +01:00
for ( int j = 0 ; j < surfaceH ; + + j ) {
for ( int i = 0 ; i < surfaceW ; + + i ) {
float32 alt = 0 ;
2010-03-13 23:00:01 +01:00
readBytes = fread ( & alt , sizeof ( float32 ) , 1 , f ) ;
SurfaceCell * sc = getSurfaceCell ( i , j ) ;
sc - > setVertex ( Vec3f ( i * mapScale , alt / heightFactor , j * mapScale ) ) ;
}
}
//read surfaces
2011-01-09 05:49:21 +01:00
for ( int j = 0 ; j < surfaceH ; + + j ) {
for ( int i = 0 ; i < surfaceW ; + + i ) {
int8 surf = 0 ;
2010-03-13 23:00:01 +01:00
readBytes = fread ( & surf , sizeof ( int8 ) , 1 , f ) ;
getSurfaceCell ( i , j ) - > setSurfaceType ( surf - 1 ) ;
}
}
//read objects and resources
2011-01-09 05:49:21 +01:00
for ( int j = 0 ; j < h ; j + = cellScale ) {
for ( int i = 0 ; i < w ; i + = cellScale ) {
2010-03-13 23:00:01 +01:00
2011-01-09 05:49:21 +01:00
int8 objNumber = 0 ;
2010-03-13 23:00:01 +01:00
readBytes = fread ( & objNumber , sizeof ( int8 ) , 1 , f ) ;
SurfaceCell * sc = getSurfaceCell ( toSurfCoords ( Vec2i ( i , j ) ) ) ;
2011-01-09 05:49:21 +01:00
if ( objNumber = = 0 ) {
2010-03-13 23:00:01 +01:00
sc - > setObject ( NULL ) ;
}
2011-01-09 05:49:21 +01:00
else if ( objNumber < = Tileset : : objCount ) {
2010-09-10 02:28:14 +02:00
Object * o = new Object ( tileset - > getObjectType ( objNumber - 1 ) , sc - > getVertex ( ) , Vec2i ( i , j ) ) ;
2010-03-13 23:00:01 +01:00
sc - > setObject ( o ) ;
2011-01-09 05:49:21 +01:00
for ( int k = 0 ; k < techTree - > getResourceTypeCount ( ) ; + + k ) {
2010-03-13 23:00:01 +01:00
const ResourceType * rt = techTree - > getResourceType ( k ) ;
2011-01-09 05:49:21 +01:00
if ( rt - > getClass ( ) = = rcTileset & & rt - > getTilesetObject ( ) = = objNumber ) {
2010-03-13 23:00:01 +01:00
o - > setResource ( rt , Vec2i ( i , j ) ) ;
}
}
}
else {
const ResourceType * rt = techTree - > getTechResourceType ( objNumber - Tileset : : objCount ) ;
2010-09-10 02:28:14 +02:00
Object * o = new Object ( NULL , sc - > getVertex ( ) , Vec2i ( i , j ) ) ;
2010-03-13 23:00:01 +01:00
o - > setResource ( rt , Vec2i ( i , j ) ) ;
sc - > setObject ( o ) ;
}
}
}
}
else {
2011-08-31 22:04:50 +02:00
if ( f ) fclose ( f ) ;
2010-03-13 23:00:01 +01:00
throw runtime_error ( " Can't open file " ) ;
}
fclose ( f ) ;
}
catch ( const exception & e ) {
2010-10-06 22:22:06 +02:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] Error [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , e . what ( ) ) ;
2010-03-13 23:00:01 +01:00
throw runtime_error ( " Error loading map: " + path + " \n " + e . what ( ) ) ;
}
2011-01-09 05:49:21 +01:00
return mapChecksum ;
2010-03-13 23:00:01 +01:00
}
2011-02-06 02:36:55 +01:00
void Map : : init ( Tileset * tileset ) {
2011-11-04 02:12:05 +01:00
Logger : : getInstance ( ) . add ( Lang : : getInstance ( ) . get ( " LogScreenGameUnLoadingMap " , " " , true ) , true ) ;
2011-02-10 01:14:21 +01:00
maxMapHeight = 0.0f ;
2011-02-06 02:36:55 +01:00
smoothSurface ( tileset ) ;
2010-03-13 23:00:01 +01:00
computeNormals ( ) ;
computeInterpolatedHeights ( ) ;
computeNearSubmerged ( ) ;
computeCellColors ( ) ;
}
// ==================== is ====================
2010-12-19 04:30:17 +01:00
bool Map : : isInside ( int x , int y ) const {
2010-03-13 23:00:01 +01:00
return x > = 0 & & y > = 0 & & x < w & & y < h ;
}
2010-12-19 04:30:17 +01:00
bool Map : : isInside ( const Vec2i & pos ) const {
2010-03-13 23:00:01 +01:00
return isInside ( pos . x , pos . y ) ;
}
2010-12-19 04:30:17 +01:00
bool Map : : isInsideSurface ( int sx , int sy ) const {
2010-03-13 23:00:01 +01:00
return sx > = 0 & & sy > = 0 & & sx < surfaceW & & sy < surfaceH ;
}
2010-12-19 04:30:17 +01:00
bool Map : : isInsideSurface ( const Vec2i & sPos ) const {
2010-03-13 23:00:01 +01:00
return isInsideSurface ( sPos . x , sPos . y ) ;
}
2011-03-29 06:57:36 +02:00
class FindBestPos {
public :
float distanceFromUnitNoAdjustment ;
float distanceFromClickNoAdjustment ;
Vec2i resourcePosNoAdjustment ;
} ;
2010-07-21 20:21:40 +02:00
//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource
2011-03-29 03:45:10 +02:00
bool Map : : isResourceNear ( const Vec2i & pos , const ResourceType * rt , Vec2i & resourcePos ,
int size , Unit * unit , bool fallbackToPeersHarvestingSameResource ,
Vec2i * resourceClickPos ) const {
2011-03-29 06:57:36 +02:00
2011-03-29 03:45:10 +02:00
bool resourceNear = false ;
float distanceFromUnit = - 1 ;
float distanceFromClick = - 1 ;
if ( resourceClickPos ) {
//printf("+++++++++ unit [%s - %d] pos = [%s] resourceClickPos [%s]\n",unit->getFullName().c_str(),unit->getId(),pos.getString().c_str(),resourceClickPos->getString().c_str());
}
2011-06-02 07:05:54 +02:00
for ( int i = - size ; i < = size ; + + i ) {
for ( int j = - size ; j < = size ; + + j ) {
2011-02-25 23:13:11 +01:00
Vec2i resPos = Vec2i ( pos . x + i , pos . y + j ) ;
2011-03-29 03:45:10 +02:00
if ( resourceClickPos ) {
resPos = Vec2i ( resourceClickPos - > x + i , resourceClickPos - > y + j ) ;
}
Vec2i surfCoords = toSurfCoords ( resPos ) ;
if ( isInside ( resPos ) & & isInsideSurface ( surfCoords ) ) {
Resource * r = getSurfaceCell ( surfCoords ) - > getResource ( ) ;
2010-10-20 22:40:29 +02:00
if ( r ! = NULL ) {
2010-10-17 10:50:27 +02:00
if ( r - > getType ( ) = = rt ) {
2011-03-29 03:45:10 +02:00
if ( resourceClickPos ) {
//printf("****** unit [%s - %d] resPos = [%s] resourceClickPos->dist(resPos) [%f] distanceFromClick [%f] unit->getCenteredPos().dist(resPos) [%f] distanceFromUnit [%f]\n",unit->getFullName().c_str(),unit->getId(),resPos.getString().c_str(),resourceClickPos->dist(resPos),distanceFromClick,unit->getCenteredPos().dist(resPos),distanceFromUnit);
}
if ( resourceClickPos = = NULL | |
( distanceFromClick < 0 | | resourceClickPos - > dist ( resPos ) < = distanceFromClick ) ) {
if ( unit = = NULL | |
( distanceFromUnit < 0 | | unit - > getCenteredPos ( ) . dist ( resPos ) < = distanceFromUnit ) ) {
bool isResourceNextToUnit = ( resourceClickPos = = NULL ) ;
2011-06-02 07:05:54 +02:00
for ( int i1 = - size ; isResourceNextToUnit = = false & & i1 < = size ; + + i1 ) {
for ( int j1 = - size ; j1 < = size ; + + j1 ) {
2011-03-29 03:45:10 +02:00
Vec2i resPos1 = Vec2i ( pos . x + i1 , pos . y + j1 ) ;
if ( resPos = = resPos1 ) {
isResourceNextToUnit = true ;
break ;
}
}
}
if ( isResourceNextToUnit = = true ) {
if ( resourceClickPos ! = NULL ) {
distanceFromClick = resourceClickPos - > dist ( resPos ) ;
}
if ( unit ! = NULL ) {
distanceFromUnit = unit - > getCenteredPos ( ) . dist ( resPos ) ;
}
resourcePos = pos + Vec2i ( i , j ) ;
if ( unit = = NULL | | unit - > isBadHarvestPos ( resourcePos ) = = false ) {
resourceNear = true ;
if ( resourceClickPos ) {
//printf("@@@@@@@@ unit [%s - %d] resPos = [%s] resourceClickPos->dist(resPos) [%f] distanceFromClick [%f] unit->getCenteredPos().dist(resPos) [%f] distanceFromUnit [%f]\n",unit->getFullName().c_str(),unit->getId(),resPos.getString().c_str(),resourceClickPos->dist(resPos),distanceFromClick,unit->getCenteredPos().dist(resPos),distanceFromUnit);
}
}
}
}
2010-10-17 10:50:27 +02:00
}
2010-07-21 20:21:40 +02:00
}
}
}
}
}
2010-10-20 00:26:49 +02:00
2011-03-29 03:45:10 +02:00
if ( resourceNear = = false ) {
if ( fallbackToPeersHarvestingSameResource = = true & & unit ! = NULL ) {
// Look for another unit that is currently harvesting the same resource
// type right now
// Check the faction cache for a known position where we can harvest
// this resource type
Vec2i result = unit - > getFaction ( ) - > getClosestResourceTypeTargetFromCache ( unit , rt ) ;
if ( result . x > = 0 ) {
resourcePos = result ;
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugWorldSynch ) . enabled = = true ) {
char szBuf [ 4096 ] = " " ;
sprintf ( szBuf , " [found peer harvest pos] pos [%s] resourcePos [%s] unit->getFaction()->getCacheResourceTargetListSize() [%d] " ,
pos . getString ( ) . c_str ( ) , resourcePos . getString ( ) . c_str ( ) , unit - > getFaction ( ) - > getCacheResourceTargetListSize ( ) ) ;
unit - > logSynchData ( __FILE__ , __LINE__ , szBuf ) ;
}
if ( unit - > getPos ( ) . dist ( resourcePos ) < = size ) {
resourceNear = true ;
if ( resourceClickPos ) {
//printf("###### unit [%s - %d]\n",unit->getFullName().c_str(),unit->getId());
}
}
2010-12-01 00:32:39 +01:00
}
2011-03-29 03:45:10 +02:00
}
}
2010-12-01 00:32:39 +01:00
2011-03-29 03:45:10 +02:00
if ( resourceNear = = false & & resourceClickPos ! = NULL ) {
2011-03-29 06:57:36 +02:00
std : : vector < FindBestPos > bestPosList ;
2011-08-31 21:44:19 +02:00
//if(resourceClickPos) {
2011-03-29 03:45:10 +02:00
//printf("^^^^^ unit [%s - %d]\n",unit->getFullName().c_str(),unit->getId());
2011-08-31 21:44:19 +02:00
//}
2011-03-29 03:45:10 +02:00
for ( int i = - 1 ; i < = 1 ; + + i ) {
for ( int j = - 1 ; j < = 1 ; + + j ) {
Vec2i resPos = Vec2i ( resourceClickPos - > x + i , resourceClickPos - > y + j ) ;
Vec2i surfCoords = toSurfCoords ( resPos ) ;
if ( isInside ( resPos ) & & isInsideSurface ( surfCoords ) ) {
Resource * r = getSurfaceCell ( surfCoords ) - > getResource ( ) ;
if ( r ! = NULL ) {
if ( r - > getType ( ) = = rt ) {
//printf("^^^^^^ unit [%s - %d] resPos = [%s] resourceClickPos->dist(resPos) [%f] distanceFromClick [%f] unit->getCenteredPos().dist(resPos) [%f] distanceFromUnit [%f]\n",unit->getFullName().c_str(),unit->getId(),resPos.getString().c_str(),resourceClickPos->dist(resPos),distanceFromClick,unit->getCenteredPos().dist(resPos),distanceFromUnit);
2011-03-29 06:57:36 +02:00
if ( unit = = NULL | |
( distanceFromUnit < 0 | | unit - > getCenteredPos ( ) . dist ( resPos ) < = ( distanceFromUnit + 2.0 ) ) ) {
if ( resourceClickPos - > dist ( resPos ) < = 1.0 ) {
FindBestPos bestPosItem ;
bestPosItem . distanceFromUnitNoAdjustment = unit - > getCenteredPos ( ) . dist ( resPos ) ;
bestPosItem . distanceFromClickNoAdjustment = distanceFromClick = resourceClickPos - > dist ( resPos ) ;
bestPosItem . resourcePosNoAdjustment = resPos ;
bestPosList . push_back ( bestPosItem ) ;
}
//printf("!!!! unit [%s - %d] resPos = [%s] resourceClickPos->dist(resPos) [%f] distanceFromClick [%f] unit->getCenteredPos().dist(resPos) [%f] distanceFromUnit [%f]\n",unit->getFullName().c_str(),unit->getId(),resPos.getString().c_str(),resourceClickPos->dist(resPos),distanceFromClick,unit->getCenteredPos().dist(resPos),distanceFromUnit);
if ( distanceFromClick < 0 | | resourceClickPos - > dist ( resPos ) < = distanceFromClick ) {
2011-03-29 03:45:10 +02:00
if ( resourceClickPos ! = NULL ) {
distanceFromClick = resourceClickPos - > dist ( resPos ) ;
}
if ( unit ! = NULL ) {
distanceFromUnit = unit - > getCenteredPos ( ) . dist ( resPos ) ;
}
* resourceClickPos = resPos ;
if ( unit = = NULL | | unit - > isBadHarvestPos ( * resourceClickPos ) = = false ) {
//resourceNear = true;
//printf("%%----------- unit [%s - %d] resPos = [%s] resourceClickPos->dist(resPos) [%f] distanceFromClick [%f] unit->getCenteredPos().dist(resPos) [%f] distanceFromUnit [%f]\n",unit->getFullName().c_str(),unit->getId(),resPos.getString().c_str(),resourceClickPos->dist(resPos),distanceFromClick,unit->getCenteredPos().dist(resPos),distanceFromUnit);
}
}
2011-03-29 06:57:36 +02:00
}
2011-03-29 03:45:10 +02:00
}
}
}
2010-10-20 09:28:27 +02:00
}
}
2011-03-29 06:57:36 +02:00
float bestUnitDist = distanceFromUnit ;
for ( unsigned int i = 0 ; i < bestPosList . size ( ) ; + + i ) {
FindBestPos & bestPosItem = bestPosList [ i ] ;
if ( bestPosItem . distanceFromUnitNoAdjustment < bestUnitDist ) {
bestUnitDist = bestPosItem . distanceFromUnitNoAdjustment ;
* resourceClickPos = bestPosItem . resourcePosNoAdjustment ;
if ( unit = = NULL | | unit - > isBadHarvestPos ( * resourceClickPos ) = = false ) {
//printf("%%----------- unit [%s - %d] resourceClickPos [%s] bestUnitDist [%f]\n",unit->getFullName().c_str(),unit->getId(),resourceClickPos->getString().c_str(),bestUnitDist);
}
}
}
2010-10-20 00:26:49 +02:00
}
2010-10-20 22:40:29 +02:00
2011-03-29 03:45:10 +02:00
return resourceNear ;
2010-07-21 20:21:40 +02:00
}
2010-03-13 23:00:01 +01:00
//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource
2010-07-11 20:31:02 +02:00
bool Map : : isResourceNear ( const Vec2i & pos , int size , const ResourceType * rt , Vec2i & resourcePos ) const {
2011-06-02 07:05:54 +02:00
Vec2i p1 = pos + Vec2i ( - size ) ;
2011-01-20 16:56:30 +01:00
Vec2i p2 = pos + Vec2i ( size ) ;
Util : : PerimeterIterator iter ( p1 , p2 ) ;
while ( iter . more ( ) ) {
Vec2i cur = iter . next ( ) ;
2011-02-25 23:13:11 +01:00
if ( isInside ( cur ) & & isInsideSurface ( toSurfCoords ( cur ) ) ) {
2011-01-20 16:56:30 +01:00
Resource * r = getSurfaceCell ( toSurfCoords ( cur ) ) - > getResource ( ) ;
if ( r & & r - > getType ( ) = = rt ) {
resourcePos = cur ;
return true ;
}
}
}
return false ;
2010-03-13 23:00:01 +01:00
}
// ==================== free cells ====================
2010-09-02 07:38:49 +02:00
bool Map : : isFreeCell ( const Vec2i & pos , Field field ) const {
2010-03-13 23:00:01 +01:00
return
isInside ( pos ) & &
2011-02-22 23:25:03 +01:00
isInsideSurface ( toSurfCoords ( pos ) ) & &
2010-03-13 23:00:01 +01:00
getCell ( pos ) - > isFree ( field ) & &
( field = = fAir | | getSurfaceCell ( toSurfCoords ( pos ) ) - > isFree ( ) ) & &
2010-09-02 07:38:49 +02:00
( field ! = fLand | | getDeepSubmerged ( getCell ( pos ) ) = = false ) ;
2010-03-13 23:00:01 +01:00
}
2011-09-27 01:55:18 +02:00
bool Map : : isFreeCellOrMightBeFreeSoon ( Vec2i originPos , const Vec2i & pos , Field field ) const {
return
isInside ( pos ) & &
isInsideSurface ( toSurfCoords ( pos ) ) & &
getCell ( pos ) - > isFreeOrMightBeFreeSoon ( originPos , pos , field ) & &
( field = = fAir | | getSurfaceCell ( toSurfCoords ( pos ) ) - > isFree ( ) ) & &
( field ! = fLand | | getDeepSubmerged ( getCell ( pos ) ) = = false ) ;
}
2010-10-30 06:49:49 +02:00
bool Map : : isFreeCellOrHasUnit ( const Vec2i & pos , Field field , const Unit * unit ) const {
2011-02-22 23:25:03 +01:00
if ( isInside ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
2011-09-07 01:12:05 +02:00
if ( unit - > getCurrField ( ) ! = field ) {
return isFreeCell ( pos , field ) ;
}
2010-03-13 23:00:01 +01:00
Cell * c = getCell ( pos ) ;
2010-10-30 06:49:49 +02:00
if ( c - > getUnit ( unit - > getCurrField ( ) ) = = unit ) {
if ( unit - > getCurrField ( ) = = fAir ) {
2011-09-07 01:12:05 +02:00
if ( field = = fAir ) {
return true ;
}
2010-10-30 06:49:49 +02:00
const SurfaceCell * sc = getSurfaceCell ( toSurfCoords ( pos ) ) ;
if ( sc ! = NULL ) {
if ( getDeepSubmerged ( sc ) = = true ) {
return false ;
}
else if ( field = = fLand ) {
2010-10-30 10:54:00 +02:00
if ( sc - > isFree ( ) = = false ) {
return false ;
}
else if ( c - > getUnit ( field ) ! = NULL ) {
return false ;
}
2010-10-30 06:49:49 +02:00
}
}
}
2010-03-13 23:00:01 +01:00
return true ;
}
else {
return isFreeCell ( pos , field ) ;
}
}
return false ;
}
2010-12-19 04:30:17 +01:00
bool Map : : isAproxFreeCell ( const Vec2i & pos , Field field , int teamIndex ) const {
2011-02-22 23:25:03 +01:00
if ( isInside ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
2010-03-13 23:00:01 +01:00
const SurfaceCell * sc = getSurfaceCell ( toSurfCoords ( pos ) ) ;
2010-12-19 04:30:17 +01:00
if ( sc - > isVisible ( teamIndex ) ) {
2010-03-13 23:00:01 +01:00
return isFreeCell ( pos , field ) ;
}
2010-12-19 04:30:17 +01:00
else if ( sc - > isExplored ( teamIndex ) ) {
2010-03-13 23:00:01 +01:00
return field = = fLand ? sc - > isFree ( ) & & ! getDeepSubmerged ( getCell ( pos ) ) : true ;
}
2010-12-19 04:30:17 +01:00
else {
2010-03-13 23:00:01 +01:00
return true ;
}
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
bool Map : : isAproxFreeCellOrMightBeFreeSoon ( Vec2i originPos , const Vec2i & pos , Field field , int teamIndex ) const {
if ( isInside ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
const SurfaceCell * sc = getSurfaceCell ( toSurfCoords ( pos ) ) ;
if ( sc - > isVisible ( teamIndex ) ) {
return isFreeCellOrMightBeFreeSoon ( originPos , pos , field ) ;
}
else if ( sc - > isExplored ( teamIndex ) ) {
return field = = fLand ? sc - > isFree ( ) & & ! getDeepSubmerged ( getCell ( pos ) ) : true ;
}
else {
return true ;
}
}
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
2010-12-19 04:30:17 +01:00
bool Map : : isFreeCells ( const Vec2i & pos , int size , Field field ) const {
2010-09-02 07:38:49 +02:00
for ( int i = pos . x ; i < pos . x + size ; + + i ) {
for ( int j = pos . y ; j < pos . y + size ; + + j ) {
Vec2i testPos ( i , j ) ;
2011-02-24 21:14:12 +01:00
if ( isFreeCell ( testPos , field ) = = false ) {
2011-02-23 00:59:21 +01:00
return false ;
2010-03-13 23:00:01 +01:00
}
}
}
return true ;
}
2011-02-06 19:33:49 +01:00
bool Map : : isFreeCellsOrHasUnit ( const Vec2i & pos , int size , Field field ,
const Unit * unit , const UnitType * munit ) const {
2011-02-11 08:39:58 +01:00
if ( unit = = NULL ) {
throw runtime_error ( " unit == NULL " ) ;
}
if ( munit = = NULL ) {
throw runtime_error ( " munit == NULL " ) ;
}
2011-02-20 01:04:57 +01:00
for ( int i = pos . x ; i < pos . x + size ; + + i ) {
for ( int j = pos . y ; j < pos . y + size ; + + j ) {
2011-02-19 23:36:59 +01:00
if ( isFreeCellOrHasUnit ( Vec2i ( i , j ) , field , unit ) = = false ) {
return false ;
2010-03-13 23:00:01 +01:00
}
}
}
2011-02-06 19:33:49 +01:00
return true ;
2010-03-13 23:00:01 +01:00
}
2010-12-19 04:30:17 +01:00
bool Map : : isAproxFreeCells ( const Vec2i & pos , int size , Field field , int teamIndex ) const {
for ( int i = pos . x ; i < pos . x + size ; + + i ) {
for ( int j = pos . y ; j < pos . y + size ; + + j ) {
if ( isAproxFreeCell ( Vec2i ( i , j ) , field , teamIndex ) = = false ) {
2010-03-13 23:00:01 +01:00
return false ;
}
}
}
return true ;
}
2011-01-20 16:56:30 +01:00
bool Map : : canOccupy ( const Vec2i & pos , Field field , const UnitType * ut , CardinalDir facing ) {
2011-02-22 23:25:03 +01:00
if ( ut - > hasCellMap ( ) & & isInside ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
2011-01-20 16:56:30 +01:00
for ( int y = 0 ; y < ut - > getSize ( ) ; + + y ) {
for ( int x = 0 ; x < ut - > getSize ( ) ; + + x ) {
2011-02-22 23:25:03 +01:00
Vec2i cellPos = pos + Vec2i ( x , y ) ;
if ( isInside ( cellPos ) & & isInsideSurface ( toSurfCoords ( cellPos ) ) ) {
if ( ut - > getCellMapCell ( x , y , facing ) ) {
if ( isFreeCell ( cellPos , field ) = = false ) {
return false ;
}
2011-01-20 16:56:30 +01:00
}
}
2011-02-22 23:25:03 +01:00
else {
false ;
}
2011-01-20 16:56:30 +01:00
}
}
return true ;
}
else {
return isFreeCells ( pos , ut - > getSize ( ) , field ) ;
2010-12-19 04:30:17 +01:00
}
2010-07-14 08:54:43 +02:00
}
2010-03-13 23:00:01 +01:00
// ==================== unit placement ====================
//checks if a unit can move from between 2 cells
2010-11-09 10:06:52 +01:00
bool Map : : canMove ( const Unit * unit , const Vec2i & pos1 , const Vec2i & pos2 , std : : map < Vec2i , std : : map < Vec2i , std : : map < int , std : : map < Field , bool > > > > * lookupCache ) const {
2010-03-13 23:00:01 +01:00
int size = unit - > getType ( ) - > getSize ( ) ;
2010-11-09 10:06:52 +01:00
Field field = unit - > getCurrField ( ) ;
if ( lookupCache ! = NULL ) {
std : : map < Vec2i , std : : map < Vec2i , std : : map < int , std : : map < Field , bool > > > > : : const_iterator iterFind1 = lookupCache - > find ( pos1 ) ;
if ( iterFind1 ! = lookupCache - > end ( ) ) {
std : : map < Vec2i , std : : map < int , std : : map < Field , bool > > > : : const_iterator iterFind2 = iterFind1 - > second . find ( pos2 ) ;
if ( iterFind2 ! = iterFind1 - > second . end ( ) ) {
std : : map < int , std : : map < Field , bool > > : : const_iterator iterFind3 = iterFind2 - > second . find ( size ) ;
if ( iterFind3 ! = iterFind2 - > second . end ( ) ) {
std : : map < Field , bool > : : const_iterator iterFind4 = iterFind3 - > second . find ( field ) ;
if ( iterFind4 ! = iterFind3 - > second . end ( ) ) {
// Found this result in the cache
return iterFind4 - > second ;
}
}
}
}
}
2010-03-13 23:00:01 +01:00
2010-10-20 00:26:49 +02:00
for ( int i = pos2 . x ; i < pos2 . x + size ; + + i ) {
for ( int j = pos2 . y ; j < pos2 . y + size ; + + j ) {
2011-02-25 23:13:11 +01:00
if ( isInside ( i , j ) & & isInsideSurface ( toSurfCoords ( Vec2i ( i , j ) ) ) ) {
2010-11-09 10:06:52 +01:00
if ( getCell ( i , j ) - > getUnit ( field ) ! = unit ) {
if ( isFreeCell ( Vec2i ( i , j ) , field ) = = false ) {
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ size ] [ field ] = false ;
}
2010-03-13 23:00:01 +01:00
return false ;
}
}
}
2010-10-20 00:26:49 +02:00
else {
2010-11-09 10:06:52 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ size ] [ field ] = false ;
}
2010-03-13 23:00:01 +01:00
return false ;
}
}
}
2011-04-26 23:51:18 +02:00
bool isBadHarvestPos = false ;
if ( unit ! = NULL ) {
Command * command = unit - > getCurrCommand ( ) ;
if ( command ! = NULL ) {
const HarvestCommandType * hct = dynamic_cast < const HarvestCommandType * > ( command - > getCommandType ( ) ) ;
if ( hct ! = NULL & & unit - > isBadHarvestPos ( pos2 ) = = true ) {
isBadHarvestPos = true ;
}
}
}
if ( unit = = NULL | | isBadHarvestPos = = true ) {
2010-11-09 10:06:52 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ size ] [ field ] = false ;
}
2010-10-20 00:26:49 +02:00
return false ;
}
2010-11-09 10:06:52 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ size ] [ field ] = true ;
}
2010-03-13 23:00:01 +01:00
return true ;
}
//checks if a unit can move from between 2 cells using only visible cells (for pathfinding)
2010-11-07 02:06:14 +01:00
bool Map : : aproxCanMove ( const Unit * unit , const Vec2i & pos1 , const Vec2i & pos2 , std : : map < Vec2i , std : : map < Vec2i , std : : map < int , std : : map < int , std : : map < Field , bool > > > > > * lookupCache ) const {
2011-02-23 08:03:38 +01:00
if ( isInside ( pos1 ) = = false | | isInsideSurface ( toSurfCoords ( pos1 ) ) = = false | |
isInside ( pos2 ) = = false | | isInsideSurface ( toSurfCoords ( pos2 ) ) = = false ) {
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2011-02-23 08:03:38 +01:00
return false ;
}
2010-03-13 23:00:01 +01:00
int size = unit - > getType ( ) - > getSize ( ) ;
int teamIndex = unit - > getTeam ( ) ;
Field field = unit - > getCurrField ( ) ;
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
std : : map < Vec2i , std : : map < Vec2i , std : : map < int , std : : map < int , std : : map < Field , bool > > > > > : : const_iterator iterFind1 = lookupCache - > find ( pos1 ) ;
if ( iterFind1 ! = lookupCache - > end ( ) ) {
std : : map < Vec2i , std : : map < int , std : : map < int , std : : map < Field , bool > > > > : : const_iterator iterFind2 = iterFind1 - > second . find ( pos2 ) ;
if ( iterFind2 ! = iterFind1 - > second . end ( ) ) {
std : : map < int , std : : map < int , std : : map < Field , bool > > > : : const_iterator iterFind3 = iterFind2 - > second . find ( teamIndex ) ;
if ( iterFind3 ! = iterFind2 - > second . end ( ) ) {
std : : map < int , std : : map < Field , bool > > : : const_iterator iterFind4 = iterFind3 - > second . find ( size ) ;
if ( iterFind4 ! = iterFind3 - > second . end ( ) ) {
std : : map < Field , bool > : : const_iterator iterFind5 = iterFind4 - > second . find ( field ) ;
if ( iterFind5 ! = iterFind4 - > second . end ( ) ) {
// Found this result in the cache
2011-09-27 01:55:18 +02:00
if ( iterFind5 - > second = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
}
2010-11-07 02:06:14 +01:00
return iterFind5 - > second ;
}
}
}
}
}
}
2010-03-13 23:00:01 +01:00
//single cell units
2010-11-07 02:06:14 +01:00
if ( size = = 1 ) {
if ( isAproxFreeCell ( pos2 , field , teamIndex ) = = false ) {
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
2010-11-07 02:06:14 +01:00
if ( pos1 . x ! = pos2 . x & & pos1 . y ! = pos2 . y ) {
2010-10-20 00:26:49 +02:00
if ( isAproxFreeCell ( Vec2i ( pos1 . x , pos2 . y ) , field , teamIndex ) = = false ) {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//Unit *cellUnit = getCell(Vec2i(pos1.x, pos2.y))->getUnit(field);
//Object * obj = getSurfaceCell(toSurfCoords(Vec2i(pos1.x, pos2.y)))->getObject();
//printf("[%s] Line: %d returning false cell [%s] free [%d] cell unitid = %d object class = %d\n",__FUNCTION__,__LINE__,Vec2i(pos1.x, pos2.y).getString().c_str(),this->isFreeCell(Vec2i(pos1.x, pos2.y),field),(cellUnit != NULL ? cellUnit->getId() : -1),(obj != NULL ? obj->getType()->getClass() : -1));
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
2010-10-20 00:26:49 +02:00
if ( isAproxFreeCell ( Vec2i ( pos2 . x , pos1 . y ) , field , teamIndex ) = = false ) {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
}
2010-10-20 00:26:49 +02:00
2011-04-26 23:51:18 +02:00
bool isBadHarvestPos = false ;
if ( unit ! = NULL ) {
Command * command = unit - > getCurrCommand ( ) ;
if ( command ! = NULL ) {
const HarvestCommandType * hct = dynamic_cast < const HarvestCommandType * > ( command - > getCommandType ( ) ) ;
if ( hct ! = NULL & & unit - > isBadHarvestPos ( pos2 ) = = true ) {
isBadHarvestPos = true ;
}
}
}
if ( unit = = NULL | | isBadHarvestPos = = true ) {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-10-20 00:26:49 +02:00
return false ;
}
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = true ;
}
2010-03-13 23:00:01 +01:00
return true ;
}
//multi cell units
2010-10-20 00:26:49 +02:00
else {
2010-11-07 02:06:14 +01:00
for ( int i = pos2 . x ; i < pos2 . x + size ; + + i ) {
for ( int j = pos2 . y ; j < pos2 . y + size ; + + j ) {
2011-02-23 08:03:38 +01:00
Vec2i cellPos = Vec2i ( i , j ) ;
if ( isInside ( cellPos ) & & isInsideSurface ( toSurfCoords ( cellPos ) ) ) {
if ( getCell ( cellPos ) - > getUnit ( unit - > getCurrField ( ) ) ! = unit ) {
if ( isAproxFreeCell ( cellPos , field , teamIndex ) = = false ) {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
}
}
2010-10-20 00:26:49 +02:00
else {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-03-13 23:00:01 +01:00
return false ;
}
}
}
2010-10-20 00:26:49 +02:00
2011-04-26 23:51:18 +02:00
bool isBadHarvestPos = false ;
if ( unit ! = NULL ) {
Command * command = unit - > getCurrCommand ( ) ;
if ( command ! = NULL ) {
const HarvestCommandType * hct = dynamic_cast < const HarvestCommandType * > ( command - > getCommandType ( ) ) ;
if ( hct ! = NULL & & unit - > isBadHarvestPos ( pos2 ) = = true ) {
isBadHarvestPos = true ;
}
}
}
if ( unit = = NULL | | isBadHarvestPos = = true ) {
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = false ;
}
2011-09-27 01:55:18 +02:00
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
2010-10-20 00:26:49 +02:00
return false ;
}
2010-11-07 02:06:14 +01:00
if ( lookupCache ! = NULL ) {
( * lookupCache ) [ pos1 ] [ pos2 ] [ teamIndex ] [ size ] [ field ] = true ;
}
2010-03-13 23:00:01 +01:00
}
2011-02-23 08:03:38 +01:00
return true ;
2010-03-13 23:00:01 +01:00
}
2011-09-27 01:55:18 +02:00
//checks if a unit can move from between 2 cells using only visible cells (for pathfinding)
bool Map : : aproxCanMoveSoon ( const Unit * unit , const Vec2i & pos1 , const Vec2i & pos2 ) const {
if ( isInside ( pos1 ) = = false | | isInsideSurface ( toSurfCoords ( pos1 ) ) = = false | |
isInside ( pos2 ) = = false | | isInsideSurface ( toSurfCoords ( pos2 ) ) = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
int size = unit - > getType ( ) - > getSize ( ) ;
int teamIndex = unit - > getTeam ( ) ;
Field field = unit - > getCurrField ( ) ;
//single cell units
if ( size = = 1 ) {
if ( isAproxFreeCellOrMightBeFreeSoon ( unit - > getPos ( ) , pos2 , field , teamIndex ) = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
if ( pos1 . x ! = pos2 . x & & pos1 . y ! = pos2 . y ) {
if ( isAproxFreeCellOrMightBeFreeSoon ( unit - > getPos ( ) , Vec2i ( pos1 . x , pos2 . y ) , field , teamIndex ) = = false ) {
//Unit *cellUnit = getCell(Vec2i(pos1.x, pos2.y))->getUnit(field);
//Object * obj = getSurfaceCell(toSurfCoords(Vec2i(pos1.x, pos2.y)))->getObject();
//printf("[%s] Line: %d returning false cell [%s] free [%d] cell unitid = %d object class = %d\n",__FUNCTION__,__LINE__,Vec2i(pos1.x, pos2.y).getString().c_str(),this->isFreeCell(Vec2i(pos1.x, pos2.y),field),(cellUnit != NULL ? cellUnit->getId() : -1),(obj != NULL ? obj->getType()->getClass() : -1));
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
if ( isAproxFreeCellOrMightBeFreeSoon ( unit - > getPos ( ) , Vec2i ( pos2 . x , pos1 . y ) , field , teamIndex ) = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
}
bool isBadHarvestPos = false ;
if ( unit ! = NULL ) {
Command * command = unit - > getCurrCommand ( ) ;
if ( command ! = NULL ) {
const HarvestCommandType * hct = dynamic_cast < const HarvestCommandType * > ( command - > getCommandType ( ) ) ;
if ( hct ! = NULL & & unit - > isBadHarvestPos ( pos2 ) = = true ) {
isBadHarvestPos = true ;
}
}
}
if ( unit = = NULL | | isBadHarvestPos = = true ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
return true ;
}
//multi cell units
else {
for ( int i = pos2 . x ; i < pos2 . x + size ; + + i ) {
for ( int j = pos2 . y ; j < pos2 . y + size ; + + j ) {
Vec2i cellPos = Vec2i ( i , j ) ;
if ( isInside ( cellPos ) & & isInsideSurface ( toSurfCoords ( cellPos ) ) ) {
if ( getCell ( cellPos ) - > getUnit ( unit - > getCurrField ( ) ) ! = unit ) {
if ( isAproxFreeCellOrMightBeFreeSoon ( unit - > getPos ( ) , cellPos , field , teamIndex ) = = false ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
}
}
else {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
}
}
bool isBadHarvestPos = false ;
if ( unit ! = NULL ) {
Command * command = unit - > getCurrCommand ( ) ;
if ( command ! = NULL ) {
const HarvestCommandType * hct = dynamic_cast < const HarvestCommandType * > ( command - > getCommandType ( ) ) ;
if ( hct ! = NULL & & unit - > isBadHarvestPos ( pos2 ) = = true ) {
isBadHarvestPos = true ;
}
}
}
if ( unit = = NULL | | isBadHarvestPos = = true ) {
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false ;
}
}
return true ;
}
2010-09-01 01:14:15 +02:00
Vec2i Map : : computeRefPos ( const Selection * selection ) const {
Vec2i total = Vec2i ( 0 ) ;
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
if ( selection = = NULL | | selection - > getUnit ( i ) = = NULL ) {
throw runtime_error ( " selection == NULL || selection->getUnit(i) = = NULL " ) ;
}
total = total + selection - > getUnit ( i ) - > getPos ( ) ;
}
return Vec2i ( total . x / selection - > getCount ( ) , total . y / selection - > getCount ( ) ) ;
}
Vec2i Map : : computeDestPos ( const Vec2i & refUnitPos , const Vec2i & unitPos ,
const Vec2i & commandPos ) const {
Vec2i pos ;
2011-03-29 23:44:36 +02:00
// no more random needed
// Vec2i posDiff = unitPos - refUnitPos;
//
// if(abs(posDiff.x) >= 3){
// posDiff.x = posDiff.x % 3;
// }
//
// if(abs(posDiff.y) >= 3){
// posDiff.y = posDiff.y % 3;
// }
2010-09-01 01:14:15 +02:00
2011-03-29 23:44:36 +02:00
pos = commandPos ; //+ posDiff;
2010-09-01 01:14:15 +02:00
clampPos ( pos ) ;
return pos ;
}
std : : pair < float , Vec2i > Map : : getUnitDistanceToPos ( const Unit * unit , Vec2i pos , const UnitType * ut ) {
if ( unit = = NULL ) {
throw runtime_error ( " unit == NULL " ) ;
}
std : : pair < float , Vec2i > result ( - 1 , Vec2i ( 0 ) ) ;
2011-09-01 03:11:23 +02:00
//int unitId= unit->getId();
2010-09-01 01:14:15 +02:00
Vec2i unitPos = computeDestPos ( unit - > getPos ( ) , unit - > getPos ( ) , pos ) ;
Vec2i start = pos - Vec2i ( 1 ) ;
int unitTypeSize = 0 ;
if ( ut ! = NULL ) {
unitTypeSize = ut - > getSize ( ) ;
}
Vec2i end = pos + Vec2i ( unitTypeSize ) ;
for ( int i = start . x ; i < = end . x ; + + i ) {
for ( int j = start . y ; j < = end . y ; + + j ) {
Vec2i testPos ( i , j ) ;
if ( ut = = NULL | | isInUnitTypeCells ( ut , pos , testPos ) = = false ) {
float distance = unitPos . dist ( testPos ) ;
if ( result . first < 0 | | result . first > distance ) {
result . first = distance ;
result . second = testPos ;
}
}
}
}
return result ;
}
const Unit * Map : : findClosestUnitToPos ( const Selection * selection , Vec2i originalBuildPos ,
const UnitType * ut ) const {
const Unit * closestUnit = NULL ;
Vec2i refPos = computeRefPos ( selection ) ;
Vec2i pos = originalBuildPos ;
float bestRange = - 1 ;
Vec2i start = pos - Vec2i ( 1 ) ;
int unitTypeSize = 0 ;
if ( ut ! = NULL ) {
unitTypeSize = ut - > getSize ( ) ;
}
Vec2i end = pos + Vec2i ( unitTypeSize ) ;
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
const Unit * unit = selection - > getUnit ( i ) ;
2011-09-01 03:11:23 +02:00
//int unitId= unit->getId();
2010-09-01 01:14:15 +02:00
Vec2i unitBuilderPos = computeDestPos ( refPos , unit - > getPos ( ) , pos ) ;
for ( int i = start . x ; i < = end . x ; + + i ) {
for ( int j = start . y ; j < = end . y ; + + j ) {
Vec2i testPos ( i , j ) ;
if ( isInUnitTypeCells ( ut , originalBuildPos , testPos ) = = false ) {
float distance = unitBuilderPos . dist ( testPos ) ;
if ( bestRange < 0 | | bestRange > distance ) {
bestRange = distance ;
pos = testPos ;
closestUnit = unit ;
}
}
}
}
}
return closestUnit ;
}
2010-12-26 05:38:03 +01:00
Vec2i Map : : findBestBuildApproach ( const Unit * unit , Vec2i originalBuildPos , const UnitType * ut ) const {
Vec2i unitBuilderPos = unit - > getPos ( ) ;
Vec2i pos = originalBuildPos ;
2010-08-29 08:30:41 +02:00
float bestRange = - 1 ;
2011-06-09 23:38:04 +02:00
Vec2i start = pos - Vec2i ( unit - > getType ( ) - > getSize ( ) ) ;
2010-08-29 08:30:41 +02:00
Vec2i end = pos + Vec2i ( ut - > getSize ( ) ) ;
for ( int i = start . x ; i < = end . x ; + + i ) {
2010-12-28 03:17:44 +01:00
for ( int j = start . y ; j < = end . y ; + + j ) {
2010-08-29 08:30:41 +02:00
Vec2i testPos ( i , j ) ;
if ( isInUnitTypeCells ( ut , originalBuildPos , testPos ) = = false ) {
float distance = unitBuilderPos . dist ( testPos ) ;
if ( bestRange < 0 | | bestRange > distance ) {
2010-12-26 05:38:03 +01:00
// Check if the cell is occupied by another unit
if ( isFreeCellOrHasUnit ( testPos , unit - > getType ( ) - > getField ( ) , unit ) = = true ) {
bestRange = distance ;
pos = testPos ;
}
2010-08-29 08:30:41 +02:00
}
}
}
}
2010-08-28 05:43:14 +02:00
2010-08-29 08:30:41 +02:00
return pos ;
}
bool Map : : isNextToUnitTypeCells ( const UnitType * ut , const Vec2i & pos ,
2010-09-01 01:14:15 +02:00
const Vec2i & testPos ) const {
2010-08-29 08:30:41 +02:00
bool isInsideDestUnitCells = isInUnitTypeCells ( ut , pos , testPos ) ;
if ( isInsideDestUnitCells = = false ) {
2011-09-01 03:11:23 +02:00
//Cell *testCell = getCell(testPos);
2010-08-29 08:30:41 +02:00
for ( int i = - 1 ; i < = ut - > getSize ( ) ; + + i ) {
for ( int j = - 1 ; j < = ut - > getSize ( ) ; + + j ) {
Vec2i currPos = pos + Vec2i ( i , j ) ;
2011-02-25 23:13:11 +01:00
if ( isInside ( currPos ) = = true & & isInsideSurface ( toSurfCoords ( currPos ) ) = = true ) {
2010-08-29 08:30:41 +02:00
//Cell *unitCell = getCell(currPos);
//if(unitCell == testCell) {
if ( isNextTo ( testPos , currPos ) = = true ) {
return true ;
}
}
}
}
}
return false ;
}
// is testPos in the cells of unitType where unitType's position is pos
bool Map : : isInUnitTypeCells ( const UnitType * ut , const Vec2i & pos ,
2010-09-01 01:14:15 +02:00
const Vec2i & testPos ) const {
2010-12-19 02:24:37 +01:00
assert ( ut ! = NULL ) ;
2010-11-11 09:02:50 +01:00
if ( ut = = NULL ) {
throw runtime_error ( " ut == NULL " ) ;
}
2010-08-28 05:43:14 +02:00
2011-02-22 23:25:03 +01:00
if ( isInside ( testPos ) & & isInsideSurface ( toSurfCoords ( testPos ) ) ) {
Cell * testCell = getCell ( testPos ) ;
for ( int i = 0 ; i < ut - > getSize ( ) ; + + i ) {
for ( int j = 0 ; j < ut - > getSize ( ) ; + + j ) {
Vec2i currPos = pos + Vec2i ( i , j ) ;
if ( isInside ( currPos ) & & isInsideSurface ( toSurfCoords ( currPos ) ) ) {
Cell * unitCell = getCell ( currPos ) ;
if ( unitCell = = testCell ) {
return true ;
}
2010-08-28 05:43:14 +02:00
}
}
}
}
return false ;
}
2010-03-13 23:00:01 +01:00
//put a units into the cells
2010-10-30 10:54:00 +02:00
void Map : : putUnitCells ( Unit * unit , const Vec2i & pos ) {
2010-12-19 02:24:37 +01:00
assert ( unit ! = NULL ) ;
2010-11-11 09:02:50 +01:00
if ( unit = = NULL ) {
throw runtime_error ( " ut == NULL " ) ;
}
2010-12-19 03:04:16 +01:00
bool canPutInCell = true ;
2010-03-13 23:00:01 +01:00
const UnitType * ut = unit - > getType ( ) ;
2010-10-30 10:54:00 +02:00
for ( int i = 0 ; i < ut - > getSize ( ) ; + + i ) {
for ( int j = 0 ; j < ut - > getSize ( ) ; + + j ) {
2010-03-13 23:00:01 +01:00
Vec2i currPos = pos + Vec2i ( i , j ) ;
assert ( isInside ( currPos ) ) ;
2010-11-11 09:02:50 +01:00
if ( isInside ( currPos ) = = false ) {
throw runtime_error ( " isInside(currPos) = = false " ) ;
}
2010-10-30 10:54:00 +02:00
if ( ut - > hasCellMap ( ) = = false | | ut - > getCellMapCell ( i , j , unit - > getModelFacing ( ) ) ) {
2010-12-19 03:04:16 +01:00
if ( getCell ( currPos ) - > getUnit ( unit - > getCurrField ( ) ) ! = NULL & &
getCell ( currPos ) - > getUnit ( unit - > getCurrField ( ) ) ! = unit ) {
2010-11-27 09:23:45 +01:00
2010-12-19 04:30:17 +01:00
// If unit tries to move into a cell where another unit resides
// cancel the move command
2010-12-19 03:04:16 +01:00
if ( unit - > getCurrSkill ( ) ! = NULL & &
2010-12-19 03:06:24 +01:00
unit - > getCurrSkill ( ) - > getClass ( ) = = scMove ) {
2010-12-19 03:04:16 +01:00
canPutInCell = false ;
2010-12-28 03:24:54 +01:00
//unit->setCurrSkill(scStop);
//unit->finishCommand();
2010-12-19 03:04:16 +01:00
2010-12-19 04:30:17 +01:00
//SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] POSSIBLE ERROR [getCell(currPos)->getUnit(unit->getCurrField()) != NULL] currPos [%s] unit [%s] cell unit [%s]\n",
// __FILE__,__FUNCTION__,__LINE__,
// currPos.getString().c_str(),
// unit->toString().c_str(),
// getCell(currPos)->getUnit(unit->getCurrField())->toString().c_str());
2010-12-19 03:04:16 +01:00
}
2010-12-19 04:30:17 +01:00
// If the unit trying to move into the cell is not in the moving state
// it is likely being created or morphed so we will will log the error
2010-12-19 03:04:16 +01:00
else {
canPutInCell = false ;
2010-12-19 04:30:17 +01:00
// throw runtime_error("getCell(currPos)->getUnit(unit->getCurrField()) != NULL");
2010-12-19 03:04:16 +01:00
SystemFlags : : OutputDebug ( SystemFlags : : debugError , " In [%s::%s Line: %d] ERROR [getCell(currPos)->getUnit(unit->getCurrField()) != NULL] currPos [%s] unit [%s] cell unit [%s] \n " ,
__FILE__ , __FUNCTION__ , __LINE__ ,
currPos . getString ( ) . c_str ( ) ,
unit - > toString ( ) . c_str ( ) ,
getCell ( currPos ) - > getUnit ( unit - > getCurrField ( ) ) - > toString ( ) . c_str ( ) ) ;
}
}
2010-10-30 10:54:00 +02:00
2010-12-19 03:04:16 +01:00
if ( canPutInCell = = true ) {
getCell ( currPos ) - > setUnit ( unit - > getCurrField ( ) , unit ) ;
}
2010-10-30 10:54:00 +02:00
}
else if ( ut - > hasCellMap ( ) = = true & &
2010-11-09 10:06:52 +01:00
ut - > getAllowEmptyCellMap ( ) = = true & &
ut - > hasEmptyCellMap ( ) = = true ) {
2010-10-30 10:54:00 +02:00
getCell ( currPos ) - > setUnitWithEmptyCellMap ( unit - > getCurrField ( ) , unit ) ;
2011-01-17 17:31:25 +01:00
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] currPos = %s unit = %s\n",
// __FILE__,__FUNCTION__,__LINE__,
// currPos.getString().c_str(),
// unit->toString().c_str());
2010-03-13 23:00:01 +01:00
}
}
}
2010-12-19 03:04:16 +01:00
if ( canPutInCell = = true ) {
unit - > setPos ( pos ) ;
}
2010-03-13 23:00:01 +01:00
}
//removes a unit from cells
2010-10-30 10:54:00 +02:00
void Map : : clearUnitCells ( Unit * unit , const Vec2i & pos ) {
2010-12-19 02:24:37 +01:00
assert ( unit ! = NULL ) ;
2010-11-11 09:02:50 +01:00
if ( unit = = NULL ) {
throw runtime_error ( " unit == NULL " ) ;
}
2010-03-13 23:00:01 +01:00
const UnitType * ut = unit - > getType ( ) ;
for ( int i = 0 ; i < ut - > getSize ( ) ; + + i ) {
for ( int j = 0 ; j < ut - > getSize ( ) ; + + j ) {
Vec2i currPos = pos + Vec2i ( i , j ) ;
assert ( isInside ( currPos ) ) ;
2010-11-11 09:02:50 +01:00
if ( isInside ( currPos ) = = false ) {
throw runtime_error ( " isInside(currPos) = = false " ) ;
}
2010-10-30 10:54:00 +02:00
if ( ut - > hasCellMap ( ) = = false | | ut - > getCellMapCell ( i , j , unit - > getModelFacing ( ) ) ) {
2010-11-27 08:11:54 +01:00
// This seems to be a bad assert since you can clear the cell
// for many reasons including a unit dieing.
2010-12-19 03:04:16 +01:00
//assert(getCell(currPos)->getUnit(unit->getCurrField()) == unit || getCell(currPos)->getUnit(unit->getCurrField()) == NULL);
2011-01-07 05:32:41 +01:00
//if(getCell(currPos)->getUnit(unit->getCurrField()) != unit && getCell(currPos)->getUnit(unit->getCurrField()) != NULL) {
2010-11-27 08:11:54 +01:00
// throw runtime_error("getCell(currPos)->getUnit(unit->getCurrField()) != unit");
2011-01-07 05:32:41 +01:00
//SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] ERROR [getCell(currPos)->getUnit(unit->getCurrField()) != unit] currPos [%s] unit [%s] cell unit [%s]\n",
// __FILE__,__FUNCTION__,__LINE__,
// currPos.getString().c_str(),
// unit->toString().c_str(),
// (getCell(currPos)->getUnit(unit->getCurrField()) != NULL ? getCell(currPos)->getUnit(unit->getCurrField())->toString().c_str() : "NULL"));
//}
// Only clear the cell if its the unit we expect to clear out of it
if ( getCell ( currPos ) - > getUnit ( unit - > getCurrField ( ) ) = = unit ) {
getCell ( currPos ) - > setUnit ( unit - > getCurrField ( ) , NULL ) ;
}
2010-10-30 10:54:00 +02:00
}
else if ( ut - > hasCellMap ( ) = = true & &
2010-11-09 10:06:52 +01:00
ut - > getAllowEmptyCellMap ( ) = = true & &
ut - > hasEmptyCellMap ( ) = = true ) {
2010-10-30 10:54:00 +02:00
getCell ( currPos ) - > setUnitWithEmptyCellMap ( unit - > getCurrField ( ) , NULL ) ;
2011-01-17 17:31:25 +01:00
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] currPos = %s unit = %s\n",
// __FILE__,__FUNCTION__,__LINE__,
// currPos.getString().c_str(),
// unit->toString().c_str());
2010-03-13 23:00:01 +01:00
}
}
}
}
// ==================== misc ====================
2010-08-28 03:46:26 +02:00
//return if unit is next to pos
2010-10-30 10:54:00 +02:00
bool Map : : isNextTo ( const Vec2i & pos , const Unit * unit ) const {
2010-03-13 23:00:01 +01:00
2010-10-30 10:54:00 +02:00
for ( int i = - 1 ; i < = 1 ; + + i ) {
for ( int j = - 1 ; j < = 1 ; + + j ) {
2011-02-25 23:13:11 +01:00
if ( isInside ( pos . x + i , pos . y + j ) & & isInsideSurface ( toSurfCoords ( Vec2i ( pos . x + i , pos . y + j ) ) ) ) {
2010-10-30 10:54:00 +02:00
if ( getCell ( pos . x + i , pos . y + j ) - > getUnit ( fLand ) = = unit ) {
return true ;
}
else if ( getCell ( pos . x + i , pos . y + j ) - > getUnitWithEmptyCellMap ( fLand ) = = unit ) {
2010-03-13 23:00:01 +01:00
return true ;
}
}
}
}
return false ;
}
2011-10-28 07:22:41 +02:00
//return if unit is next to pos
bool Map : : isNextTo ( const Unit * unit1 , const Unit * unit2 ) const {
Vec2i pos = unit1 - > getPos ( ) ;
const UnitType * ut = unit1 - > getType ( ) ;
for ( int y = - 1 ; y < ut - > getSize ( ) + 1 ; + + y ) {
for ( int x = - 1 ; x < ut - > getSize ( ) + 1 ; + + x ) {
Vec2i cellPos = pos + Vec2i ( x , y ) ;
if ( isInside ( cellPos ) & & isInsideSurface ( toSurfCoords ( cellPos ) ) ) {
if ( getCell ( cellPos ) - > getUnit ( fLand ) = = unit2 ) {
return true ;
}
else if ( getCell ( cellPos ) - > getUnitWithEmptyCellMap ( fLand ) = = unit2 ) {
return true ;
}
}
}
}
return false ;
}
2010-08-28 03:46:26 +02:00
//return if unit is next to pos
bool Map : : isNextTo ( const Vec2i & pos , const Vec2i & nextToPos ) const {
for ( int i = - 1 ; i < = 1 ; + + i ) {
for ( int j = - 1 ; j < = 1 ; + + j ) {
2011-02-25 23:13:11 +01:00
if ( isInside ( pos . x + i , pos . y + j ) & & isInsideSurface ( toSurfCoords ( Vec2i ( pos . x + i , pos . y + j ) ) ) ) {
2010-08-28 03:46:26 +02:00
if ( getCell ( pos . x + i , pos . y + j ) = = getCell ( nextToPos . x , nextToPos . y ) ) {
return true ;
}
}
}
}
return false ;
}
2010-03-13 23:00:01 +01:00
void Map : : clampPos ( Vec2i & pos ) const {
if ( pos . x < 0 ) {
pos . x = 0 ;
}
if ( pos . y < 0 ) {
pos . y = 0 ;
}
if ( pos . x > = w ) {
pos . x = w - 1 ;
}
if ( pos . y > = h ) {
pos . y = h - 1 ;
}
}
2010-11-09 10:06:52 +01:00
void Map : : prepareTerrain ( const Unit * unit ) {
Chrono chrono ;
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled ) chrono . start ( ) ;
2010-11-09 10:06:52 +01:00
2010-03-13 23:00:01 +01:00
flatternTerrain ( unit ) ;
2010-11-09 10:06:52 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took msecs: %lld \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-11-09 10:06:52 +01:00
2010-03-13 23:00:01 +01:00
computeNormals ( ) ;
2010-11-09 10:06:52 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took msecs: %lld \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-11-09 10:06:52 +01:00
2010-03-13 23:00:01 +01:00
computeInterpolatedHeights ( ) ;
2010-11-09 10:06:52 +01:00
2011-03-28 05:54:23 +02:00
if ( SystemFlags : : getSystemSettingType ( SystemFlags : : debugPerformance ) . enabled & & chrono . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] took msecs: %lld \n " , __FILE__ , __FUNCTION__ , __LINE__ , chrono . getMillis ( ) ) ;
2010-03-13 23:00:01 +01:00
}
// ==================== PRIVATE ====================
// ==================== compute ====================
void Map : : flatternTerrain ( const Unit * unit ) {
float refHeight = getSurfaceCell ( toSurfCoords ( unit - > getCenteredPos ( ) ) ) - > getHeight ( ) ;
for ( int i = - 1 ; i < = unit - > getType ( ) - > getSize ( ) ; + + i ) {
for ( int j = - 1 ; j < = unit - > getType ( ) - > getSize ( ) ; + + j ) {
Vec2i pos = unit - > getPos ( ) + Vec2i ( i , j ) ;
2011-02-23 00:59:21 +01:00
if ( isInside ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
Cell * c = getCell ( pos ) ;
SurfaceCell * sc = getSurfaceCell ( toSurfCoords ( pos ) ) ;
//we change height if pos is inside world, if its free or ocupied by the currenty building
if ( sc - > getObject ( ) = = NULL & & ( c - > getUnit ( fLand ) = = NULL | | c - > getUnit ( fLand ) = = unit ) ) {
sc - > setHeight ( refHeight ) ;
}
2010-03-13 23:00:01 +01:00
}
}
}
}
//compute normals
void Map : : computeNormals ( ) {
//compute center normals
for ( int i = 1 ; i < surfaceW - 1 ; + + i ) {
for ( int j = 1 ; j < surfaceH - 1 ; + + j ) {
getSurfaceCell ( i , j ) - > setNormal (
getSurfaceCell ( i , j ) - > getVertex ( ) . normal ( getSurfaceCell ( i , j - 1 ) - > getVertex ( ) ,
getSurfaceCell ( i + 1 , j ) - > getVertex ( ) ,
getSurfaceCell ( i , j + 1 ) - > getVertex ( ) ,
getSurfaceCell ( i - 1 , j ) - > getVertex ( ) ) ) ;
}
}
}
void Map : : computeInterpolatedHeights ( ) {
for ( int i = 0 ; i < w ; + + i ) {
for ( int j = 0 ; j < h ; + + j ) {
getCell ( i , j ) - > setHeight ( getSurfaceCell ( toSurfCoords ( Vec2i ( i , j ) ) ) - > getHeight ( ) ) ;
}
}
for ( int i = 1 ; i < surfaceW - 1 ; + + i ) {
for ( int j = 1 ; j < surfaceH - 1 ; + + j ) {
for ( int k = 0 ; k < cellScale ; + + k ) {
for ( int l = 0 ; l < cellScale ; + + l ) {
if ( k = = 0 & & l = = 0 ) {
getCell ( i * cellScale , j * cellScale ) - > setHeight ( getSurfaceCell ( i , j ) - > getHeight ( ) ) ;
}
else if ( k ! = 0 & & l = = 0 ) {
getCell ( i * cellScale + k , j * cellScale ) - > setHeight ( (
getSurfaceCell ( i , j ) - > getHeight ( ) +
getSurfaceCell ( i + 1 , j ) - > getHeight ( ) ) / 2.f ) ;
}
else if ( l ! = 0 & & k = = 0 ) {
getCell ( i * cellScale , j * cellScale + l ) - > setHeight ( (
getSurfaceCell ( i , j ) - > getHeight ( ) +
getSurfaceCell ( i , j + 1 ) - > getHeight ( ) ) / 2.f ) ;
}
else {
getCell ( i * cellScale + k , j * cellScale + l ) - > setHeight ( (
getSurfaceCell ( i , j ) - > getHeight ( ) +
getSurfaceCell ( i , j + 1 ) - > getHeight ( ) +
getSurfaceCell ( i + 1 , j ) - > getHeight ( ) +
getSurfaceCell ( i + 1 , j + 1 ) - > getHeight ( ) ) / 4.f ) ;
}
}
}
}
}
}
2011-02-06 02:36:55 +01:00
void Map : : smoothSurface ( Tileset * tileset ) {
float * oldHeights = new float [ getSurfaceCellArraySize ( ) ] ;
2011-09-01 03:11:23 +02:00
//int arraySize=getSurfaceCellArraySize();
2010-03-13 23:00:01 +01:00
2011-02-06 02:36:55 +01:00
for ( int i = 0 ; i < getSurfaceCellArraySize ( ) ; + + i ) {
oldHeights [ i ] = surfaceCells [ i ] . getHeight ( ) ;
2010-03-13 23:00:01 +01:00
}
2011-02-08 21:59:34 +01:00
2011-02-06 02:36:55 +01:00
for ( int i = 1 ; i < surfaceW - 1 ; + + i ) {
for ( int j = 1 ; j < surfaceH - 1 ; + + j ) {
float height = 0.f ;
float numUsedToSmooth = 0.f ;
for ( int k = - 1 ; k < = 1 ; + + k ) {
for ( int l = - 1 ; l < = 1 ; + + l ) {
2011-02-16 00:53:48 +01:00
# ifdef USE_STREFLOP
if ( cliffLevel < = 0.1f | | cliffLevel > streflop : : fabs ( oldHeights [ ( j ) * surfaceW + ( i ) ]
- oldHeights [ ( j + k ) * surfaceW + ( i + l ) ] ) ) {
# else
2011-02-11 20:16:06 +01:00
if ( cliffLevel < = 0.1f | | cliffLevel > fabs ( oldHeights [ ( j ) * surfaceW + ( i ) ]
2011-02-06 02:36:55 +01:00
- oldHeights [ ( j + k ) * surfaceW + ( i + l ) ] ) ) {
2011-02-16 00:53:48 +01:00
# endif
2011-02-06 02:36:55 +01:00
height + = oldHeights [ ( j + k ) * surfaceW + ( i + l ) ] ;
numUsedToSmooth + + ;
2011-02-11 20:16:06 +01:00
}
else {
2011-02-06 02:36:55 +01:00
// we have something which should not be smoothed!
// This is a cliff and must be textured -> set cliff texture
getSurfaceCell ( i , j ) - > setSurfaceType ( 5 ) ;
//set invisible blocking object and replace resource objects
//and non blocking objects with invisible blocker too
Object * formerObject =
getSurfaceCell ( i , j ) - > getObject ( ) ;
if ( formerObject ! = NULL ) {
if ( formerObject - > getWalkable ( )
| | formerObject - > getResource ( ) ! = NULL ) {
delete formerObject ;
formerObject = NULL ;
}
}
if ( formerObject = = NULL ) {
Object * o = new Object ( tileset - > getObjectType ( 9 ) ,
getSurfaceCell ( i , j ) - > getVertex ( ) , Vec2i ( i ,
j ) ) ;
getSurfaceCell ( i , j ) - > setObject ( o ) ;
}
}
2010-03-13 23:00:01 +01:00
}
}
2011-02-06 02:36:55 +01:00
height / = numUsedToSmooth ;
2011-02-10 01:14:21 +01:00
if ( maxMapHeight < height ) {
maxMapHeight = height ;
}
2010-03-13 23:00:01 +01:00
getSurfaceCell ( i , j ) - > setHeight ( height ) ;
2011-02-06 02:36:55 +01:00
Object * object = getSurfaceCell ( i , j ) - > getObject ( ) ;
if ( object ! = NULL ) {
2010-03-13 23:00:01 +01:00
object - > setHeight ( height ) ;
}
}
}
2011-02-06 02:36:55 +01:00
delete [ ] oldHeights ;
2010-03-13 23:00:01 +01:00
}
void Map : : computeNearSubmerged ( ) {
for ( int i = 0 ; i < surfaceW - 1 ; + + i ) {
for ( int j = 0 ; j < surfaceH - 1 ; + + j ) {
bool anySubmerged = false ;
for ( int k = - 1 ; k < = 2 ; + + k ) {
for ( int l = - 1 ; l < = 2 ; + + l ) {
Vec2i pos = Vec2i ( i + k , j + l ) ;
2011-02-25 23:13:11 +01:00
if ( isInsideSurface ( pos ) & & isInsideSurface ( toSurfCoords ( pos ) ) ) {
2010-03-13 23:00:01 +01:00
if ( getSubmerged ( getSurfaceCell ( pos ) ) )
anySubmerged = true ;
}
}
}
getSurfaceCell ( i , j ) - > setNearSubmerged ( anySubmerged ) ;
}
}
}
void Map : : computeCellColors ( ) {
for ( int i = 0 ; i < surfaceW ; + + i ) {
for ( int j = 0 ; j < surfaceH ; + + j ) {
SurfaceCell * sc = getSurfaceCell ( i , j ) ;
if ( getDeepSubmerged ( sc ) ) {
float factor = clamp ( waterLevel - sc - > getHeight ( ) * 1.5f , 1.f , 1.5f ) ;
sc - > setColor ( Vec3f ( 1.0f , 1.0f , 1.0f ) / factor ) ;
}
else {
sc - > setColor ( Vec3f ( 1.0f , 1.0f , 1.0f ) ) ;
}
}
}
}
2011-01-20 16:56:30 +01:00
// static
2010-04-29 09:59:44 +02:00
string Map : : getMapPath ( const string & mapName , string scenarioDir , bool errorOnNotFound ) {
2010-03-18 22:26:40 +01:00
Config & config = Config : : getInstance ( ) ;
2010-03-21 06:33:13 +01:00
vector < string > pathList = config . getPathListForType ( ptMaps , scenarioDir ) ;
2010-03-18 22:26:40 +01:00
for ( int idx = 0 ; idx < pathList . size ( ) ; idx + + ) {
2011-03-13 09:23:43 +01:00
string map_path = pathList [ idx ] ;
endPathWithSlash ( map_path ) ;
const string mega = map_path + mapName + " .mgm " ;
const string glest = map_path + mapName + " .gbm " ;
2011-01-20 16:56:30 +01:00
if ( fileExists ( mega ) ) {
return mega ;
2010-03-18 22:26:40 +01:00
}
2011-01-20 16:56:30 +01:00
else if ( fileExists ( glest ) ) {
return glest ;
2010-03-18 22:26:40 +01:00
}
}
2010-04-29 09:59:44 +02:00
if ( errorOnNotFound = = true ) {
2011-01-20 16:56:30 +01:00
throw runtime_error ( " Map [ " + mapName + " ] not found, scenarioDir [ " + scenarioDir + " ] " ) ;
}
return " " ;
2010-03-13 23:00:01 +01:00
}
// =====================================================
// class PosCircularIterator
// =====================================================
PosCircularIterator : : PosCircularIterator ( const Map * map , const Vec2i & center , int radius ) {
this - > map = map ;
this - > radius = radius ;
this - > center = center ;
pos = center - Vec2i ( radius , radius ) ;
pos . x - = 1 ;
}
bool PosCircularIterator : : next ( ) {
//iterate while dont find a cell that is inside the world
//and at less or equal distance that the radius
do {
pos . x + + ;
if ( pos . x > center . x + radius ) {
pos . x = center . x - radius ;
pos . y + + ;
}
if ( pos . y > center . y + radius )
return false ;
}
2010-05-01 22:14:25 +02:00
# ifdef USE_STREFLOP
2011-02-25 23:13:11 +01:00
while ( streflop : : floor ( pos . dist ( center ) ) > = ( radius + 1 ) | | ! map - > isInside ( pos ) | | ! map - > isInsideSurface ( map - > toSurfCoords ( pos ) ) ) ;
2010-05-01 22:14:25 +02:00
# else
2011-02-25 23:13:11 +01:00
while ( floor ( pos . dist ( center ) ) > = ( radius + 1 ) | | ! map - > isInside ( pos ) | | ! map - > isInsideSurface ( map - > toSurfCoords ( pos ) ) ) ;
2010-05-01 22:14:25 +02:00
# endif
2010-03-13 23:00:01 +01:00
//while(!(pos.dist(center) <= radius && map->isInside(pos)));
return true ;
}
const Vec2i & PosCircularIterator : : getPos ( ) {
return pos ;
}
// =====================================================
// class PosQuadIterator
// =====================================================
2011-02-25 23:13:11 +01:00
PosQuadIterator : : PosQuadIterator ( const Map * map , const Quad2i & quad , int step ) {
this - > map = map ;
2010-03-13 23:00:01 +01:00
this - > quad = quad ;
this - > boundingRect = quad . computeBoundingRect ( ) ;
this - > step = step ;
pos = boundingRect . p [ 0 ] ;
- - pos . x ;
pos . x = ( pos . x / step ) * step ;
pos . y = ( pos . y / step ) * step ;
2011-02-25 23:13:11 +01:00
//map->clampPos(pos);
2010-03-13 23:00:01 +01:00
}
2011-02-25 23:13:11 +01:00
bool PosQuadIterator : : next ( ) {
2010-03-13 23:00:01 +01:00
2011-02-25 23:13:11 +01:00
do {
pos . x + = step ;
if ( pos . x > boundingRect . p [ 1 ] . x ) {
pos . x = ( boundingRect . p [ 0 ] . x / step ) * step ;
pos . y + = step ;
2010-03-13 23:00:01 +01:00
}
2011-02-25 23:13:11 +01:00
if ( pos . y > boundingRect . p [ 1 ] . y ) {
2010-03-13 23:00:01 +01:00
return false ;
2011-02-25 23:13:11 +01:00
}
//printf("pos [%s] boundingRect.p[0] [%s] boundingRect.p[1] [%s]\n",pos.getString().c_str(),boundingRect.p[0].getString().c_str(),boundingRect.p[1].getString().c_str());
2010-03-13 23:00:01 +01:00
}
while ( ! quad . isInside ( pos ) ) ;
return true ;
}
2011-02-25 23:13:11 +01:00
void PosQuadIterator : : skipX ( ) {
2010-03-13 23:00:01 +01:00
pos . x + = step ;
}
const Vec2i & PosQuadIterator : : getPos ( ) {
return pos ;
}
} } //end namespace