- made the automap an object.

This simplifies handling a lot because it allows to make the level the owner of its map.
This commit is contained in:
Christoph Oelckers 2019-01-26 15:21:20 +01:00
parent 625e9f2525
commit 05830455e7
14 changed files with 830 additions and 782 deletions

File diff suppressed because it is too large Load diff

View file

@ -22,31 +22,44 @@
#ifndef __AMMAP_H__
#define __AMMAP_H__
#include "dobject.h"
struct event_t;
class FSerializer;
struct FLevelLocals;
class DAutomapBase : public DObject
{
DECLARE_ABSTRACT_CLASS(DAutomapBase, DObject);
public:
FLevelLocals *Level; // temporary location so that it can be set from the outside.
// Called by main loop.
virtual bool Responder(event_t* ev, bool last) = 0;
// Called by main loop.
virtual void Ticker(void) = 0;
// Called by main loop,
// called instead of view drawer if automap active.
virtual void Drawer(int bottom) = 0;
virtual void NewResolution() = 0;
virtual void LevelInit() = 0;
virtual void UpdateShowAllLines() = 0;
virtual void GoBig() = 0;
virtual void ResetFollowLocation() = 0;
virtual int addMark() = 0;
virtual bool clearMarks() = 0;
virtual DVector2 GetPosition() = 0;
virtual void startDisplay() = 0;
};
void AM_StaticInit();
void AM_ClearColorsets(); // reset data for a restart.
// Called by main loop.
bool AM_Responder (event_t* ev, bool last);
// Called by main loop.
void AM_Ticker (void);
// Called by main loop,
// called instead of view drawer if automap active.
void AM_Drawer (int bottom);
// Called to force the automap to quit
// if the level is completed while it is up.
void AM_Stop (void);
void AM_NewResolution ();
void AM_ToggleMap ();
void AM_LevelInit ();
void AM_SerializeMarkers(FSerializer &arc);
DAutomapBase *AM_Create(FLevelLocals *Level);
void AM_Stop();
void AM_ToggleMap();
#endif

View file

@ -758,7 +758,7 @@ void D_Display ()
screen->DrawBlend(viewsec);
if (automapactive)
{
AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
currentUILevel->automap->Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar());
}
// for timing the statusbar code.

View file

@ -955,7 +955,7 @@ bool G_Responder (event_t *ev)
{
if (ST_Responder (ev))
return true; // status window ate it
if (!viewactive && AM_Responder (ev, false))
if (!viewactive && currentUILevel->automap->Responder (ev, false))
return true; // automap ate it
}
else if (gamestate == GS_FINALE)
@ -986,7 +986,7 @@ bool G_Responder (event_t *ev)
// the events *last* so that any bound keys get precedence.
if (gamestate == GS_LEVEL && viewactive)
return AM_Responder (ev, true);
return currentUILevel->automap->Responder (ev, true);
return (ev->type == EV_KeyDown ||
ev->type == EV_Mouse);
@ -1179,7 +1179,7 @@ void G_Ticker ()
{
case GS_LEVEL:
P_Ticker ();
AM_Ticker ();
currentUILevel->automap->Ticker ();
break;
case GS_TITLELEVEL:

View file

@ -1019,9 +1019,8 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame)
E_NewGame(EventHandlerType::Global);
}
P_SetupLevel (level.MapName, position, newGame);
P_SetupLevel (&level, position, newGame);
AM_LevelInit();
// [RH] Start lightning, if MAPINFO tells us to
if (level.flags & LEVEL_STARTLIGHTNING)
@ -1126,6 +1125,7 @@ void G_DoLoadLevel (int position, bool autosave, bool newGame)
{
I_Error("no start for player %d found.", pnumerr);
}
P_ResetSightCounters(true);
}
@ -1452,8 +1452,6 @@ int G_FinishTravel ()
void FLevelLocals::Init()
{
level_info_t *info;
BaseBlendA = 0.0f; // Remove underwater blend effect, if any
gravity = sv_gravity * 35/TICRATE;
@ -1465,7 +1463,6 @@ void FLevelLocals::Init()
info = FindLevelInfo (MapName);
info = info;
skyspeed1 = info->skyspeed1;
skyspeed2 = info->skyspeed2;
skytexture1 = TexMan.GetTextureID(info->SkyPic1, ETextureType::Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst);
@ -1976,6 +1973,7 @@ void FLevelLocals::Mark()
GC::Mark(SpotState);
GC::Mark(FraggleScriptThinker);
GC::Mark(ACSThinker);
GC::Mark(automap);
canvasTextureInfo.Mark();
for (auto &c : CorpseQueue)
{

View file

@ -87,6 +87,7 @@ class DACSThinker;
class DFraggleThinker;
class DSpotState;
struct FStrifeDialogueNode;
class DAutomapBase;
typedef TMap<int, int> FDialogueIDMap; // maps dialogue IDs to dialogue array index (for ACS)
typedef TMap<FName, int> FDialogueMap; // maps actor class names to dialogue array index
@ -235,10 +236,10 @@ public:
{
return FLineIdIterator(tagManager, tag);
}
template<class T> TThinkerIterator<T> GetThinkerIterator(FName subtype = NAME_None)
template<class T> TThinkerIterator<T> GetThinkerIterator(FName subtype = NAME_None, int statnum = MAX_STATNUM+1)
{
if (subtype == NAME_None) return TThinkerIterator<T>();
else return TThinkerIterator<T>(subtype);
if (subtype == NAME_None) return TThinkerIterator<T>(statnum);
else return TThinkerIterator<T>(subtype, statnum);
}
FActorIterator GetActorIterator(int tid)
{
@ -357,6 +358,7 @@ public:
static const int BODYQUESIZE = 32;
TObjPtr<AActor*> bodyque[BODYQUESIZE];
TObjPtr<DAutomapBase*> automap;
int bodyqueslot;
int NumMapSections;

View file

@ -1075,3 +1075,4 @@ xx(lightflags)
xx(lighttype)
xx(InternalDynamicLight)
xx(_a_chase_default)
xx(MapMarker)

View file

@ -965,7 +965,8 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
("fragglethinker", Level->FraggleScriptThinker)
("acsthinker", Level->ACSThinker)
("impactdecalcount", Level->ImpactDecalCount)
("scrolls", Level->Scrolls);
("scrolls", Level->Scrolls)
("automap", Level->automap);
// Hub transitions must keep the current total time
@ -988,7 +989,10 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
arc("zones", Level->Zones);
arc("lineportals", Level->linePortals);
arc("sectorportals", Level->sectorPortals);
if (arc.isReading()) Level->FinalizePortals();
if (arc.isReading())
{
Level->FinalizePortals();
}
// [ZZ] serialize health groups
P_SerializeHealthGroups(arc);
@ -998,12 +1002,12 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
arc("polyobjs", Level->Polyobjects);
SerializeSubsectors(arc, "subsectors");
StatusBar->SerializeMessages(arc);
AM_SerializeMarkers(arc);
FRemapTable::StaticSerializeTranslations(arc);
Level->canvasTextureInfo.Serialize(arc);
P_SerializePlayers(Level, arc, hubload);
P_SerializeSounds(arc);
// Regenerate some data that wasn't saved
if (arc.isReading())
{
for (auto &sec : Level->sectors)
@ -1012,12 +1016,17 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
}
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].mo != NULL)
if (playeringame[i] && players[i].mo != nullptr)
{
FWeaponSlots::SetupWeaponSlots(players[i].mo);
}
}
AActor::RecreateAllAttachedLights();
InitPortalGroups(Level);
Level->automap->Level = Level; // Temporary workaround. At the moment this cannot be deserialized yet.
Level->automap->UpdateShowAllLines();
}
AActor::RecreateAllAttachedLights();
InitPortalGroups(Level);
}

View file

@ -71,6 +71,7 @@
#include "a_specialspot.h"
#include "maploader/maploader.h"
#include "p_acs.h"
#include "am_map.h"
#include "fragglescript/t_script.h"
void P_ClearUDMFKeys();
@ -260,6 +261,8 @@ void FLevelLocals::ClearPortals()
void FLevelLocals::ClearLevelData()
{
ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
total_monsters = total_items = total_secrets =
killed_monsters = found_items = found_secrets =
wminfo.maxfrags = 0;
@ -348,7 +351,6 @@ void P_FreeLevelData ()
P_ClearUDMFKeys();
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
level.ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
SN_StopAllSequences ();
DThinker::DestroyAllThinkers ();
@ -363,20 +365,20 @@ void P_FreeLevelData ()
//
//===========================================================================
void P_SetupLevel(const char *lumpname, int position, bool newGame)
void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
{
int i;
level.ShaderStartTime = I_msTimeFS(); // indicate to the shader system that the level just started
Level->ShaderStartTime = I_msTimeFS(); // indicate to the shader system that the level just started
// This is motivated as follows:
level.maptype = MAPTYPE_UNKNOWN;
Level->maptype = MAPTYPE_UNKNOWN;
wminfo.partime = 180;
if (!savegamerestore)
{
level.SetMusicVolume(level.MusicVolume);
Level->SetMusicVolume(Level->MusicVolume);
for (i = 0; i < MAXPLAYERS; ++i)
{
players[i].killcount = players[i].secretcount
@ -411,10 +413,10 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
// Free all level data from the previous map
P_FreeLevelData();
MapData *map = P_OpenMapData(lumpname, true);
MapData *map = P_OpenMapData(Level->MapName, true);
if (map == nullptr)
{
I_Error("Unable to open map '%s'\n", lumpname);
I_Error("Unable to open map '%s'\n", Level->MapName.GetChars());
}
// [ZZ] init per-map static handlers. we need to call this before everything is set up because otherwise scripts don't receive PlayerEntered event
@ -422,17 +424,17 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
E_InitStaticHandlers(true);
// generate a checksum for the level, to be included and checked with savegames.
map->GetChecksum(level.md5);
map->GetChecksum(Level->md5);
// find map num
level.lumpnum = map->lumpnum;
Level->lumpnum = map->lumpnum;
if (newGame)
{
E_NewGame(EventHandlerType::PerMap);
}
MapLoader loader(&level);
loader.LoadLevel(map, lumpname, position);
MapLoader loader(Level);
loader.LoadLevel(map, Level->MapName.GetChars(), position);
delete map;
// if deathmatch, randomly spawn the active players
@ -448,7 +450,7 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
}
}
// the same, but for random single/coop player starts
else if (level.flags2 & LEVEL2_RANDOMPLAYERSTARTS)
else if (Level->flags2 & LEVEL2_RANDOMPLAYERSTARTS)
{
for (i = 0; i < MAXPLAYERS; ++i)
{
@ -456,14 +458,14 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
{
players[i].mo = nullptr;
FPlayerStart *mthing = G_PickPlayerStart(i);
P_SpawnPlayer(mthing, i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
P_SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
}
}
}
// [SP] move unfriendly players around
// horribly hacky - yes, this needs rewritten.
if (level.deathmatchstarts.Size() > 0)
if (Level->deathmatchstarts.Size() > 0)
{
for (i = 0; i < MAXPLAYERS; ++i)
{
@ -522,7 +524,7 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
// This check was previously done at run time each time the heightsec was checked.
// However, since 3D floors are static data, we can easily precalculate this and store it in the sector's flags for quick access.
for (auto &s : level.sectors)
for (auto &s : Level->sectors)
{
if (s.heightsec != nullptr)
{
@ -537,17 +539,18 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
}
}
P_ResetSightCounters(true);
// Create a backup of the map data so the savegame code can toss out all fields that haven't changed in order to reduce processing time and file size.
// Note that we want binary identity here, so assignment is not sufficient because it won't initialize any padding bytes.
// Note that none of these structures may contain non POD fields anyway.
level.loadsectors.Resize(level.sectors.Size());
memcpy(&level.loadsectors[0], &level.sectors[0], level.sectors.Size() * sizeof(level.sectors[0]));
level.loadlines.Resize(level.lines.Size());
memcpy(&level.loadlines[0], &level.lines[0], level.lines.Size() * sizeof(level.lines[0]));
level.loadsides.Resize(level.sides.Size());
memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0]));
Level->loadsectors.Resize(Level->sectors.Size());
memcpy(&Level->loadsectors[0], &Level->sectors[0], Level->sectors.Size() * sizeof(Level->sectors[0]));
Level->loadlines.Resize(Level->lines.Size());
memcpy(&Level->loadlines[0], &Level->lines[0], Level->lines.Size() * sizeof(Level->lines[0]));
Level->loadsides.Resize(Level->sides.Size());
memcpy(&Level->loadsides[0], &Level->sides[0], Level->sides.Size() * sizeof(Level->sides[0]));
Level->automap = AM_Create(Level);
Level->automap->LevelInit();
}
//

View file

@ -146,7 +146,7 @@ bool P_CheckMapData(const char * mapname);
// [RH] The only parameter used is mapname, so I removed playermask and skill.
// On September 1, 1998, I added the position to indicate which set
// of single-player start spots should be spawned in the level.
void P_SetupLevel (const char *mapname, int position, bool newGame);
void P_SetupLevel (FLevelLocals *Level, int position, bool newGame);
void P_FreeLevelData();

View file

@ -46,6 +46,7 @@
#include "d_player.h"
#include "p_setup.h"
#include "i_music.h"
#include "am_map.h"
DVector2 AM_GetPosition();
int Net_GetLatency(int *ld, int *ad);
@ -2529,15 +2530,17 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, FormatMapName, FormatMapName)
ACTION_RETURN_STRING(rets);
}
static void GetAutomapPosition(DVector2 *pos)
static void GetAutomapPosition(FLevelLocals *self, DVector2 *pos)
{
*pos = AM_GetPosition();
*pos = self->automap->GetPosition();
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetAutomapPosition, GetAutomapPosition)
{
PARAM_PROLOGUE;
ACTION_RETURN_VEC2(AM_GetPosition());
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
DVector2 result;
GetAutomapPosition(self, &result);
ACTION_RETURN_VEC2(result);
}
static int ZGetUDMFInt(FLevelLocals *self, int type, int index, int key)

View file

@ -66,6 +66,8 @@
#include "r_videoscale.h"
#include "i_time.h"
#include "version.h"
#include "g_levellocals.h"
#include "am_map.h"
EXTERN_CVAR(Bool, cl_capfps)
EXTERN_CVAR(Int, menu_resolution_custom_width)
@ -592,7 +594,8 @@ void V_OutputResized (int width, int height)
C_NewModeAdjust();
// Reload crosshair if transitioned to a different size
ST_LoadCrosshair(true);
AM_NewResolution();
if (currentUILevel && currentUILevel->automap)
currentUILevel->automap->NewResolution();
}
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2)

View file

@ -687,7 +687,7 @@ struct LevelLocals native
native static void StartSlideshow(Name whichone = 'none');
native static void WorldDone();
native static void RemoveAllBots(bool fromlist);
native static Vector2 GetAutomapPosition();
native ui Vector2 GetAutomapPosition();
native void SetInterMusic(String nextmap);
native String FormatMapName(int mapnamecolor);
native bool IsJumpingAllowed() const;
@ -722,8 +722,8 @@ struct LevelLocals native
return String.Format("%02d:%02d:%02d", sec / 3600, (sec % 3600) / 60, sec % 60);
}
native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = crushDoom);
native bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false);
native bool CreateCeiling(sector sec, int type, line ln, double speed, double speed2, double height = 0, int crush = -1, int silent = 0, int change = 0, int crushmode = 0 /*Floor.crushDoom*/);
native bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false);
}
@ -926,7 +926,7 @@ class Floor : MovingFloor native
genFloorChg
};
deprecated("3.8") static bool CreateFloor(sector sec, EFloor floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false)
deprecated("3.8") static bool CreateFloor(sector sec, int floortype, line ln, double speed, double height = 0, int crush = -1, int change = 0, bool crushmode = false, bool hereticlower = false)
{
return level.CreateFloor(sec, floortype, ln, speed, height, crush, change, crushmode, hereticlower);
}

View file

@ -31,11 +31,6 @@
**
*/
/*
DVector2 AM_GetPosition();
*/
class AltHud ui
{
TextureID tnt1a0;