2011-01-20 15:56:30 +00:00
// ==============================================================
// This file is part of Glest (www.glest.org)
//
2011-12-14 07:40:48 +00:00
// Copyright (C) 2001-2008 Martiño Figueroa
2011-01-20 15:56:30 +00: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
// ==============================================================
# ifndef _GLEST_GAME_MAP_H_
# define _GLEST_GAME_MAP_H_
# include "vec.h"
# include "math_util.h"
# include "command_type.h"
# include "logger.h"
# include "object.h"
# include "game_constants.h"
2010-08-31 23:14:15 +00:00
# include "selection.h"
2011-01-20 15:56:30 +00:00
# include <cassert>
# include "leak_dumper.h"
namespace Glest { namespace Game {
using Shared : : Graphics : : Vec4f ;
using Shared : : Graphics : : Quad2i ;
using Shared : : Graphics : : Rect2i ;
using Shared : : Graphics : : Vec4f ;
using Shared : : Graphics : : Vec2f ;
using Shared : : Graphics : : Vec2i ;
using Shared : : Graphics : : Texture2D ;
class Tileset ;
class Unit ;
class Resource ;
2010-03-21 05:33:13 +00:00
class TechTree ;
2011-01-20 15:56:30 +00:00
class GameSettings ;
2012-03-12 23:08:22 +00:00
class World ;
2011-01-20 15:56:30 +00:00
// =====================================================
// class Cell
//
/// A map cell that holds info about units present on it
// =====================================================
class Cell {
private :
Unit * units [ fieldCount ] ; //units on this cell
Unit * unitsWithEmptyCellMap [ fieldCount ] ; //units with an empty cellmap on this cell
float height ;
private :
Cell ( Cell & ) ;
void operator = ( Cell & ) ;
public :
Cell ( ) ;
//get
2012-04-14 21:21:09 +00:00
Unit * getUnit ( int field ) const { if ( field > = fieldCount ) { throw megaglest_runtime_error ( " Invalid field value " + intToStr ( field ) ) ; } return units [ field ] ; }
Unit * getUnitWithEmptyCellMap ( int field ) const { if ( field > = fieldCount ) { throw megaglest_runtime_error ( " Invalid field value " + intToStr ( field ) ) ; } return unitsWithEmptyCellMap [ field ] ; }
2011-01-20 15:56:30 +00:00
float getHeight ( ) const { return height ; }
2012-04-14 21:21:09 +00:00
void setUnit ( int field , Unit * unit ) { if ( field > = fieldCount ) { throw megaglest_runtime_error ( " Invalid field value " + intToStr ( field ) ) ; } units [ field ] = unit ; }
void setUnitWithEmptyCellMap ( int field , Unit * unit ) { if ( field > = fieldCount ) { throw megaglest_runtime_error ( " Invalid field value " + intToStr ( field ) ) ; } unitsWithEmptyCellMap [ field ] = unit ; }
2011-01-20 15:56:30 +00:00
void setHeight ( float height ) { this - > height = height ; }
bool isFree ( Field field ) const ;
2011-09-26 23:55:18 +00:00
bool isFreeOrMightBeFreeSoon ( Vec2i originPos , Vec2i cellPos , Field field ) const ;
2012-03-12 23:08:22 +00:00
void saveGame ( XmlNode * rootNode , int index ) const ;
void loadGame ( const XmlNode * rootNode , int index , World * world ) ;
2011-01-20 15:56:30 +00:00
} ;
// =====================================================
// class SurfaceCell
//
// A heightmap cell, each surface cell is composed by more than one Cell
// =====================================================
class SurfaceCell {
private :
//geometry
Vec3f vertex ;
Vec3f normal ;
Vec3f color ;
//tex coords
Vec2f fowTexCoord ; //tex coords for TEXTURE1 when multitexturing and fogOfWar
Vec2f surfTexCoord ; //tex coords for TEXTURE0
//surface
int surfaceType ;
const Texture2D * surfaceTexture ;
//object & resource
Object * object ;
//visibility
bool visible [ GameConstants : : maxPlayers + GameConstants : : specialFactions ] ;
bool explored [ GameConstants : : maxPlayers + GameConstants : : specialFactions ] ;
//cache
bool nearSubmerged ;
2012-03-13 15:21:25 +00:00
bool cellChangedFromOriginalMapLoad ;
2011-01-20 15:56:30 +00:00
public :
SurfaceCell ( ) ;
~ SurfaceCell ( ) ;
2011-03-06 22:50:04 +00:00
void end ( ) ; //to kill particles
2011-01-20 15:56:30 +00:00
//get
const Vec3f & getVertex ( ) const { return vertex ; }
float getHeight ( ) const { return vertex . y ; }
const Vec3f & getColor ( ) const { return color ; }
const Vec3f & getNormal ( ) const { return normal ; }
int getSurfaceType ( ) const { return surfaceType ; }
const Texture2D * getSurfaceTexture ( ) const { return surfaceTexture ; }
Object * getObject ( ) const { return object ; }
Resource * getResource ( ) const { return object = = NULL ? NULL : object - > getResource ( ) ; }
const Vec2f & getFowTexCoord ( ) const { return fowTexCoord ; }
const Vec2f & getSurfTexCoord ( ) const { return surfTexCoord ; }
bool getNearSubmerged ( ) const { return nearSubmerged ; }
bool isVisible ( int teamIndex ) const { return visible [ teamIndex ] ; }
bool isExplored ( int teamIndex ) const { return explored [ teamIndex ] ; }
//set
void setVertex ( const Vec3f & vertex ) { this - > vertex = vertex ; }
2012-03-17 20:59:03 +00:00
void setHeight ( float height , bool cellChangedFromOriginalMapLoadValue = false ) ;
2011-01-20 15:56:30 +00:00
void setNormal ( const Vec3f & normal ) { this - > normal = normal ; }
void setColor ( const Vec3f & color ) { this - > color = color ; }
void setSurfaceType ( int surfaceType ) { this - > surfaceType = surfaceType ; }
void setSurfaceTexture ( const Texture2D * st ) { this - > surfaceTexture = st ; }
void setObject ( Object * object ) { this - > object = object ; }
void setFowTexCoord ( const Vec2f & ftc ) { this - > fowTexCoord = ftc ; }
void setSurfTexCoord ( const Vec2f & stc ) { this - > surfTexCoord = stc ; }
void setExplored ( int teamIndex , bool explored ) ;
void setVisible ( int teamIndex , bool visible ) ;
void setNearSubmerged ( bool nearSubmerged ) { this - > nearSubmerged = nearSubmerged ; }
//misc
void deleteResource ( ) ;
2012-03-13 15:21:25 +00:00
bool decAmount ( int value ) ;
2011-01-20 15:56:30 +00:00
bool isFree ( ) const ;
2012-03-13 15:21:25 +00:00
bool getCellChangedFromOriginalMapLoad ( ) const { return cellChangedFromOriginalMapLoad ; }
2012-03-12 23:08:22 +00:00
void saveGame ( XmlNode * rootNode , int index ) const ;
void loadGame ( const XmlNode * rootNode , int index , World * world ) ;
2011-01-20 15:56:30 +00:00
} ;
// =====================================================
// class Map
//
/// Represents the game map (and loads it from a gbm file)
// =====================================================
class Map {
public :
static const int cellScale ; //number of cells per surfaceCell
static const int mapScale ; //horizontal scale of surface
private :
string title ;
float waterLevel ;
float heightFactor ;
2011-02-08 03:50:59 +00:00
float cliffLevel ;
2011-02-25 00:31:42 +00:00
int cameraHeight ;
2011-01-20 15:56:30 +00:00
int w ;
int h ;
int surfaceW ;
int surfaceH ;
int maxPlayers ;
Cell * cells ;
SurfaceCell * surfaceCells ;
2011-01-09 04:49:21 +00:00
Vec2i * startLocations ;
2011-01-20 15:56:30 +00:00
Checksum checksumValue ;
2011-02-10 00:14:21 +00:00
float maxMapHeight ;
2012-03-10 03:27:25 +00:00
string mapFile ;
2011-01-20 15:56:30 +00:00
private :
Map ( Map & ) ;
void operator = ( Map & ) ;
public :
Map ( ) ;
2011-01-09 04:49:21 +00:00
~ Map ( ) ;
2011-03-06 22:50:04 +00:00
void end ( ) ; //to kill particles
2011-01-20 15:56:30 +00:00
Checksum * getChecksumValue ( ) { return & checksumValue ; }
2011-02-06 01:36:55 +00:00
void init ( Tileset * tileset ) ;
2011-01-20 15:56:30 +00:00
Checksum load ( const string & path , TechTree * techTree , Tileset * tileset ) ;
//get
Cell * getCell ( int x , int y ) const ;
int getCellArraySize ( ) const ;
2011-02-23 07:03:38 +00:00
Cell * getCell ( const Vec2i & pos ) const ;
2011-01-20 15:56:30 +00:00
int getSurfaceCellArraySize ( ) const ;
SurfaceCell * getSurfaceCell ( int sx , int sy ) const ;
2011-02-23 07:03:38 +00:00
SurfaceCell * getSurfaceCell ( const Vec2i & sPos ) const ;
2011-01-20 15:56:30 +00:00
int getW ( ) const { return w ; }
int getH ( ) const { return h ; }
int getSurfaceW ( ) const { return surfaceW ; }
int getSurfaceH ( ) const { return surfaceH ; }
int getMaxPlayers ( ) const { return maxPlayers ; }
float getHeightFactor ( ) const { return heightFactor ; }
float getWaterLevel ( ) const { return waterLevel ; }
2011-02-08 03:50:59 +00:00
float getCliffLevel ( ) const { return cliffLevel ; }
2011-02-25 00:31:42 +00:00
int getCameraHeight ( ) const { return cameraHeight ; }
2011-02-10 00:14:21 +00:00
float getMaxMapHeight ( ) const { return maxMapHeight ; }
2011-01-20 15:56:30 +00:00
Vec2i getStartLocation ( int locationIndex ) const ;
bool getSubmerged ( const SurfaceCell * sc ) const { return sc - > getHeight ( ) < waterLevel ; }
bool getSubmerged ( const Cell * c ) const { return c - > getHeight ( ) < waterLevel ; }
bool getDeepSubmerged ( const SurfaceCell * sc ) const { return sc - > getHeight ( ) < waterLevel - ( 1.5f / heightFactor ) ; }
bool getDeepSubmerged ( const Cell * c ) const { return c - > getHeight ( ) < waterLevel - ( 1.5f / heightFactor ) ; }
float getSurfaceHeight ( const Vec2i & pos ) const ;
//is
bool isInside ( int x , int y ) const ;
bool isInside ( const Vec2i & pos ) const ;
bool isInsideSurface ( int sx , int sy ) const ;
bool isInsideSurface ( const Vec2i & sPos ) const ;
2011-03-29 01:45:10 +00:00
bool isResourceNear ( const Vec2i & pos , const ResourceType * rt , Vec2i & resourcePos , int size , Unit * unit = NULL , bool fallbackToPeersHarvestingSameResource = false , Vec2i * resourceClickPos = NULL ) const ;
2011-01-20 15:56:30 +00:00
bool isResourceNear ( const Vec2i & pos , int size , const ResourceType * rt , Vec2i & resourcePos ) const ;
//free cells
bool isFreeCell ( const Vec2i & pos , Field field ) const ;
bool isFreeCellOrHasUnit ( const Vec2i & pos , Field field , const Unit * unit ) const ;
bool isAproxFreeCell ( const Vec2i & pos , Field field , int teamIndex ) const ;
bool isFreeCells ( const Vec2i & pos , int size , Field field ) const ;
2011-02-06 18:33:49 +00:00
bool isFreeCellsOrHasUnit ( const Vec2i & pos , int size , Field field , const Unit * unit , const UnitType * munit ) const ;
2011-01-20 15:56:30 +00:00
bool isAproxFreeCells ( const Vec2i & pos , int size , Field field , int teamIndex ) const ;
bool canOccupy ( const Vec2i & pos , Field field , const UnitType * ut , CardinalDir facing ) ;
//unit placement
bool 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 = NULL ) const ;
bool canMove ( const Unit * unit , const Vec2i & pos1 , const Vec2i & pos2 , std : : map < Vec2i , std : : map < Vec2i , std : : map < int , std : : map < Field , bool > > > > * lookupCache = NULL ) const ;
void putUnitCells ( Unit * unit , const Vec2i & pos ) ;
void clearUnitCells ( Unit * unit , const Vec2i & pos ) ;
Vec2i computeRefPos ( const Selection * selection ) const ;
Vec2i computeDestPos ( const Vec2i & refUnitPos , const Vec2i & unitPos ,
const Vec2i & commandPos ) const ;
const Unit * findClosestUnitToPos ( const Selection * selection , Vec2i originalBuildPos ,
const UnitType * ut ) const ;
bool isInUnitTypeCells ( const UnitType * ut , const Vec2i & pos , const Vec2i & testPos ) const ;
bool isNextToUnitTypeCells ( const UnitType * ut , const Vec2i & pos , const Vec2i & testPos ) const ;
Vec2i findBestBuildApproach ( const Unit * unit , Vec2i originalBuildPos , const UnitType * ut ) const ;
std : : pair < float , Vec2i > getUnitDistanceToPos ( const Unit * unit , Vec2i pos , const UnitType * ut ) ;
//misc
bool isNextTo ( const Vec2i & pos , const Unit * unit ) const ;
bool isNextTo ( const Vec2i & pos , const Vec2i & nextToPos ) const ;
2011-10-28 05:22:41 +00:00
bool isNextTo ( const Unit * unit1 , const Unit * unit2 ) const ;
2011-01-20 15:56:30 +00:00
void clampPos ( Vec2i & pos ) const ;
void prepareTerrain ( const Unit * unit ) ;
void flatternTerrain ( const Unit * unit ) ;
void computeNormals ( ) ;
void computeInterpolatedHeights ( ) ;
//static
static Vec2i toSurfCoords ( const Vec2i & unitPos ) { return unitPos / cellScale ; }
static Vec2i toUnitCoords ( const Vec2i & surfPos ) { return surfPos * cellScale ; }
static string getMapPath ( const string & mapName , string scenarioDir = " " , bool errorOnNotFound = true ) ;
2011-09-26 23:55:18 +00:00
bool isFreeCellOrMightBeFreeSoon ( Vec2i originPos , const Vec2i & pos , Field field ) const ;
bool isAproxFreeCellOrMightBeFreeSoon ( Vec2i originPos , const Vec2i & pos , Field field , int teamIndex ) const ;
bool aproxCanMoveSoon ( const Unit * unit , const Vec2i & pos1 , const Vec2i & pos2 ) const ;
2012-03-10 03:27:25 +00:00
string getMapFile ( ) const { return mapFile ; }
2012-03-12 23:08:22 +00:00
void saveGame ( XmlNode * rootNode ) const ;
void loadGame ( const XmlNode * rootNode , World * world ) ;
2011-01-20 15:56:30 +00:00
private :
//compute
2011-02-06 01:36:55 +00:00
void smoothSurface ( Tileset * tileset ) ;
2011-01-20 15:56:30 +00:00
void computeNearSubmerged ( ) ;
void computeCellColors ( ) ;
} ;
// ===============================
// class PosCircularIterator
// ===============================
class PosCircularIterator {
private :
Vec2i center ;
int radius ;
const Map * map ;
Vec2i pos ;
public :
PosCircularIterator ( const Map * map , const Vec2i & center , int radius ) ;
bool next ( ) ;
const Vec2i & getPos ( ) ;
} ;
// ===============================
// class PosQuadIterator
// ===============================
class PosQuadIterator {
private :
Quad2i quad ;
Rect2i boundingRect ;
Vec2i pos ;
int step ;
2011-02-25 22:13:11 +00:00
const Map * map ;
2011-01-20 15:56:30 +00:00
public :
2011-02-25 22:13:11 +00:00
PosQuadIterator ( const Map * map , const Quad2i & quad , int step = 1 ) ;
2011-01-20 15:56:30 +00:00
bool next ( ) ;
void skipX ( ) ;
const Vec2i & getPos ( ) ;
} ;
} } //end namespace
# endif