Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

222 lines
7.9 KiB

#ifndef TILEGEN_MAPLAYOUT_H
#define TILEGEN_MAPLAYOUT_H
#ifdef _WIN32
#pragma once
#endif
#include "Utlvector.h"
#include "UtlSortvector.h"
#include "ChunkFile.h"
#include "RoomTemplate.h"
#include "tilegen_core.h"
#include "missionchooser/iasw_spawn_selection.h"
class CRoom;
class CRoomTemplate;
class CASW_Spawn_Definition;
#define MAP_LAYOUT_TILES_WIDE 120 // giving a max map size of 30720
#define ASW_TILE_SIZE 256.0f
class CExit
{
public:
CExit() { }
CExit(int iX, int iY, ExitDirection_t direction, const char *szExitTag, CRoom *pRoom, bool bChokeGrow )
{
X = iX;
Y = iY;
ExitDirection = direction;
pSourceRoom = pRoom;
m_bChokepointGrowSource = bChokeGrow;
if ( szExitTag )
{
Q_strncpy( m_szExitTag, szExitTag, sizeof( m_szExitTag ) );
}
else
{
m_szExitTag[0] = 0;
}
}
int X;
int Y;
ExitDirection_t ExitDirection;
CRoom *pSourceRoom;
char m_szExitTag[MAX_EXIT_TAG_LENGTH];
bool m_bChokepointGrowSource;
};
class CRoomCandidate
{
public:
CRoomCandidate( const CRoomTemplate *pRoomTemplate, int x, int y, const CExit *pExit )
{
m_pRoomTemplate = pRoomTemplate;
m_iXPos = x;
m_iYPos = y;
m_pExit = pExit;
m_flCandidateChance = 0;
}
// The room template which is to be placed at a particular location.
const CRoomTemplate *m_pRoomTemplate;
// The grid square of the lower-left corner of the room template.
int m_iXPos, m_iYPos;
// This exit is located in a grid square within the bounds of this room candidate, pointing inwards
// (i.e. away from the source room). This exit is NOT in a grid square contained within
// the source room.
// NOTE: this value can be NULL. If so, the room candidate is not attached to an existing exit.
const CExit *m_pExit;
float m_flCandidateChance;
};
//-----------------------------------------------------------------------------
// String replacements for values in a child/instance map, specified by
// "replaceNN" keys in the parent map's func_instance entity.
//-----------------------------------------------------------------------------
struct KeyValue_t
{
char m_Key[MAX_TILEGEN_IDENTIFIER_LENGTH];
char m_Value[MAX_TILEGEN_IDENTIFIER_LENGTH];
};
//-----------------------------------------------------------------------------
// One of several modes which can be used to pick an instance
enum InstanceSpawningMethod_t
{
ISM_INVALID = 0,
ISM_ADD_AT_RANDOM_NODE,
// @TODO: add support for swapping
};
//-----------------------------------------------------------------------------
// An instance to be added to a map during VMF -> BSP compilation.
// This class is copy-able for convenience.
//-----------------------------------------------------------------------------
class CInstanceSpawn
{
public:
CInstanceSpawn();
bool LoadFromKeyValues( KeyValues *pKeyValues );
void SaveToKeyValues( KeyValues *pKeyValues ) const;
void FixupValues( const char *pFindValue, const char *pReplaceValue );
const char *GetInstanceFilename() const { return m_InstanceFilename; }
const KeyValue_t *GetAdditionalKeyValues() const { return m_AdditionalKeyValues.Base(); }
int GetAdditionalKeyValueCount() const { return m_AdditionalKeyValues.Count(); }
InstanceSpawningMethod_t GetInstanceSpawningMethod() const { return m_InstanceSpawningMethod; }
// Gets/Sets the index of the room in the layout that this instance modifies.
// If set to -1, this instance spawn is not actually in use.
int GetPlacedRoomIndex() const { return m_nPlacedRoomIndex; }
void SetPlacedRoomIndex( int nIndex ) { m_nPlacedRoomIndex = nIndex; }
int GetRandomSeed() const { return m_nRandomSeed; }
void SetRandomSeed( int nSeed ) { m_nRandomSeed = nSeed; }
private:
char m_InstanceFilename[MAX_PATH];
CCopyableUtlVector< KeyValue_t > m_AdditionalKeyValues;
InstanceSpawningMethod_t m_InstanceSpawningMethod;
int m_nPlacedRoomIndex;
// Used so that any randomness in placing this instance is deterministic
int m_nRandomSeed;
};
//-----------------------------------------------------------------------------
// An NPC spawn encounter in the mission
//-----------------------------------------------------------------------------
class CASW_Encounter : public IASW_Encounter
{
public:
virtual const Vector& GetEncounterPosition() { return m_vecPosition; }
virtual int GetNumSpawnDefs() { return m_SpawnDefs.Count(); }
virtual IASWSpawnDefinition* GetSpawnDef( int i ) { return ( i >= 0 && i < m_SpawnDefs.Count() ) ? (IASWSpawnDefinition*) m_SpawnDefs[ i ] : NULL; }
virtual float GetEncounterRadius() { return m_flEncounterRadius; }
virtual void SetEncounterPosition( const Vector &vecSrc ) { m_vecPosition = vecSrc; }
virtual void AddSpawnDef( CASW_Spawn_Definition *pSpawnDef );
virtual void SetEncounterRadius( float flRadius ) { m_flEncounterRadius = flRadius; }
void LoadFromKeyValues( KeyValues *pKeys );
void SaveToKeyValues( KeyValues *pKeys );
private:
CUtlVector<CASW_Spawn_Definition*> m_SpawnDefs;
Vector m_vecPosition;
float m_flEncounterRadius;
};
class CMapLayout
{
public:
CMapLayout( KeyValues *pGenerationOptions = NULL );
virtual ~CMapLayout();
// add room to the placed list and the room grid
void PlaceRoom( CRoom *pRoom );
void RemoveRoom( CRoom *pRoom );
const CRoom *GetLastPlacedRoom() const { Assert( m_PlacedRooms.Count() > 0 ); return m_PlacedRooms[m_PlacedRooms.Count() - 1]; }
void Clear(); // wipes all rooms
KeyValues *GetGenerationOptions() { return m_pGenerationOptions; }
void SetGenerationOptions( KeyValues *pNewGenerationOptions );
void AddLogicalRoom( CRoomTemplate *pRoomTemplate );
// Describes instances to be spawned during map creation
CUtlVector< CInstanceSpawn > m_InstanceSpawns; // Instances to be spawned during VMF -> BSP process
// all the placed rooms
CUtlVector<CRoom*> m_PlacedRooms;
CUtlVector<CRoomTemplate*> m_LogicalRooms; // rooms that are being placed down just for entity logic
bool SaveMapLayout(const char *filename);
bool LoadMapLayout(const char *filename);
bool LoadLogicalRoom( KeyValues *pRoomKeys );
// holds pointer to the CRoom at that location on the grid
CRoom* m_pRoomGrid[MAP_LAYOUT_TILES_WIDE][MAP_LAYOUT_TILES_WIDE];
// returns the min/max coords of the placed rooms
void GetExtents(int &iTileX_Min, int &iTileX_Max, int &iTileY_Min, int &iTileY_Max);
// returns true if the specified template fits in the map layout at that point (i.e. doesn't overlap any other rooms and has exits matching)
CRoom *GetRoom( int nX, int nY ) const { Assert( nX >= 0 && nX < MAP_LAYOUT_TILES_WIDE && nY >= 0 && nY < MAP_LAYOUT_TILES_WIDE ); return m_pRoomGrid[nX][nY]; }
CRoom *GetRoom( const Vector &vecPos );
bool TemplateFits( const CRoomTemplate *pTemplate, int x, int y, bool bAllowNoExits = true ) const;
bool RoomsOverlap( int x, int y, int w, int h, int x2, int y2, int w2, int h2 ) const;
bool CheckExits( const CRoomTemplate *pTemplate, int x, int y, CUtlVector<CRoomTemplateExit*> *pMatchingExits = NULL ) const;
bool CheckExitsOnSquares( const CRoomTemplate *pTemplate1, int offset_x, int offset_y, ExitDirection_t Direction, int x2, int y2, bool bRequireConnection = false, CUtlVector<CRoomTemplateExit*> *pMatchingExits = NULL ) const;
// coords of the player starts (todo: support multiple tile player starts? deal better with players putting them in geometry, etc?)
int m_iPlayerStartTileX;
int m_iPlayerStartTileY;
// last filename this layout was saved/loaded as
void SetCurrentFilename(const char *szFilename);
const char* GetCurrentFilename() { return m_szFilename; }
char m_szFilename[MAX_PATH];
bool SaveMiscMapProperties(CChunkFile *pFile);
static ChunkFileResult_t LoadMiscMapProperties(CChunkFile *pFile, CMapLayout *pMapLayout);
static ChunkFileResult_t LoadMiscMapKeyCallback(const char *szKey, const char *szValue, CMapLayout *pMapLayout);
// fixed NPC spawns
void MarkEncounterRooms(); // flags all CRooms that have an alien encounter on them
CUtlVector<CASW_Encounter*> m_Encounters;
private:
KeyValues* m_pGenerationOptions; // keyvalues for the mission we used to generate this layout
};
#endif TILEGEN_MAPLAYOUT_H