mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
This commit is contained in:
commit
6fa7c9ee0c
13 changed files with 106 additions and 892 deletions
|
@ -886,7 +886,6 @@ set (PCH_SOURCES
|
|||
p_3dmidtex.cpp
|
||||
p_acs.cpp
|
||||
p_actionfunctions.cpp
|
||||
p_buildmap.cpp
|
||||
p_ceiling.cpp
|
||||
p_conversation.cpp
|
||||
p_doors.cpp
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
#include "events.h"
|
||||
#include "dobjgc.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
||||
|
@ -1019,7 +1020,7 @@ void G_DoLoadLevel (int position, bool autosave)
|
|||
level.starttime = gametic;
|
||||
|
||||
G_UnSnapshotLevel (!savegamerestore); // [RH] Restore the state of the level.
|
||||
G_FinishTravel ();
|
||||
int pnumerr = G_FinishTravel ();
|
||||
// For each player, if they are viewing through a player, make sure it is themselves.
|
||||
for (int ii = 0; ii < MAXPLAYERS; ++ii)
|
||||
{
|
||||
|
@ -1061,6 +1062,10 @@ void G_DoLoadLevel (int position, bool autosave)
|
|||
{
|
||||
DAutosaver GCCNOWARN *dummy = Create<DAutosaver>();
|
||||
}
|
||||
if (pnumerr > 0)
|
||||
{
|
||||
I_Error("no start for player %d found.", pnumerr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1224,13 +1229,14 @@ void G_StartTravel ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void G_FinishTravel ()
|
||||
int G_FinishTravel ()
|
||||
{
|
||||
TThinkerIterator<APlayerPawn> it (STAT_TRAVELLING);
|
||||
APlayerPawn *pawn, *pawndup, *oldpawn, *next;
|
||||
AInventory *inv;
|
||||
FPlayerStart *start;
|
||||
int pnum;
|
||||
int failnum = 0;
|
||||
|
||||
//
|
||||
APlayerPawn* pawns[MAXPLAYERS];
|
||||
|
@ -1257,8 +1263,7 @@ void G_FinishTravel ()
|
|||
else
|
||||
{
|
||||
// Could not find a start for this player at all. This really should never happen but if it does, let's better abort.
|
||||
DThinker::DestroyThinkersInList(STAT_TRAVELLING);
|
||||
I_Error ("No player %d start to travel to!\n", pnum + 1);
|
||||
if (failnum == 0) failnum = pnum + 1;
|
||||
}
|
||||
}
|
||||
oldpawn = pawndup;
|
||||
|
@ -1286,7 +1291,7 @@ void G_FinishTravel ()
|
|||
pawn->Floorclip = pawndup->Floorclip;
|
||||
pawn->waterlevel = pawndup->waterlevel;
|
||||
}
|
||||
else
|
||||
else if (failnum == 0) // In the failure case this may run into some undefined data.
|
||||
{
|
||||
P_FindFloorCeiling(pawn);
|
||||
}
|
||||
|
@ -1336,6 +1341,7 @@ void G_FinishTravel ()
|
|||
// Since this list is excluded from regular thinker cleaning, anything that may survive through here
|
||||
// will endlessly multiply and severely break the following savegames or just simply crash on broken pointers.
|
||||
DThinker::DestroyThinkersInList(STAT_TRAVELLING);
|
||||
return failnum;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -468,7 +468,7 @@ enum
|
|||
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill=-1);
|
||||
|
||||
void G_StartTravel ();
|
||||
void G_FinishTravel ();
|
||||
int G_FinishTravel ();
|
||||
|
||||
void G_DoLoadLevel (int position, bool autosave);
|
||||
|
||||
|
|
|
@ -1,855 +0,0 @@
|
|||
|
||||
//**************************************************************************
|
||||
//**
|
||||
//** TEMPLATE.C
|
||||
//**
|
||||
//**************************************************************************
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "p_local.h"
|
||||
#include "m_swap.h"
|
||||
#include "w_wad.h"
|
||||
#include "templates.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_defs.h"
|
||||
#include "p_setup.h"
|
||||
#include "g_level.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "gi.h"
|
||||
#include "p_spec.h"
|
||||
|
||||
#if 0
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
//#define SHADE2LIGHT(s) (160-2*(s))
|
||||
#define SHADE2LIGHT(s) (255-2*s)
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
//ceilingstat/floorstat:
|
||||
// bit 0: 1 = parallaxing, 0 = not "P"
|
||||
// bit 1: 1 = groudraw, 0 = not
|
||||
// bit 2: 1 = swap x&y, 0 = not "F"
|
||||
// bit 3: 1 = double smooshiness "E"
|
||||
// bit 4: 1 = x-flip "F"
|
||||
// bit 5: 1 = y-flip "F"
|
||||
// bit 6: 1 = Align texture to first wall of sector "R"
|
||||
// bits 7-8: "T"
|
||||
// 00 = normal floors
|
||||
// 01 = masked floors
|
||||
// 10 = transluscent masked floors
|
||||
// 11 = reverse transluscent masked floors
|
||||
// bits 9-15: reserved
|
||||
|
||||
//40 bytes
|
||||
struct sectortype
|
||||
{
|
||||
int16_t wallptr, wallnum;
|
||||
int32_t ceilingZ, floorZ;
|
||||
int16_t ceilingstat, floorstat;
|
||||
int16_t ceilingpicnum, ceilingheinum;
|
||||
int8_t ceilingshade;
|
||||
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
||||
int16_t floorpicnum, floorheinum;
|
||||
int8_t floorshade;
|
||||
uint8_t floorpal, floorxpanning, floorypanning;
|
||||
uint8_t visibility, filler;
|
||||
int16_t lotag, hitag, extra;
|
||||
};
|
||||
|
||||
//cstat:
|
||||
// bit 0: 1 = Blocking wall (use with clipmove, getzrange) "B"
|
||||
// bit 1: 1 = bottoms of invisible walls swapped, 0 = not "2"
|
||||
// bit 2: 1 = align picture on bottom (for doors), 0 = top "O"
|
||||
// bit 3: 1 = x-flipped, 0 = normal "F"
|
||||
// bit 4: 1 = masking wall, 0 = not "M"
|
||||
// bit 5: 1 = 1-way wall, 0 = not "1"
|
||||
// bit 6: 1 = Blocking wall (use with hitscan / cliptype 1) "H"
|
||||
// bit 7: 1 = Transluscence, 0 = not "T"
|
||||
// bit 8: 1 = y-flipped, 0 = normal "F"
|
||||
// bit 9: 1 = Transluscence reversing, 0 = normal "T"
|
||||
// bits 10-15: reserved
|
||||
|
||||
//32 bytes
|
||||
struct walltype
|
||||
{
|
||||
int32_t x, y;
|
||||
int16_t point2, nextwall, nextsector, cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
||||
int16_t lotag, hitag, extra;
|
||||
};
|
||||
|
||||
//cstat:
|
||||
// bit 0: 1 = Blocking sprite (use with clipmove, getzrange) "B"
|
||||
// bit 1: 1 = transluscence, 0 = normal "T"
|
||||
// bit 2: 1 = x-flipped, 0 = normal "F"
|
||||
// bit 3: 1 = y-flipped, 0 = normal "F"
|
||||
// bits 5-4: 00 = FACE sprite (default) "R"
|
||||
// 01 = WALL sprite (like masked walls)
|
||||
// 10 = FLOOR sprite (parallel to ceilings&floors)
|
||||
// bit 6: 1 = 1-sided sprite, 0 = normal "1"
|
||||
// bit 7: 1 = Real centered centering, 0 = foot center "C"
|
||||
// bit 8: 1 = Blocking sprite (use with hitscan / cliptype 1) "H"
|
||||
// bit 9: 1 = Transluscence reversing, 0 = normal "T"
|
||||
// bits 10-14: reserved
|
||||
// bit 15: 1 = Invisible sprite, 0 = not invisible
|
||||
|
||||
//44 bytes
|
||||
struct spritetype
|
||||
{
|
||||
int32_t x, y, z;
|
||||
int16_t cstat, picnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, clipdist, filler;
|
||||
uint8_t xrepeat, yrepeat;
|
||||
int8_t xoffset, yoffset;
|
||||
int16_t sectnum, statnum;
|
||||
int16_t ang, owner, xvel, yvel, zvel;
|
||||
int16_t lotag, hitag, extra;
|
||||
};
|
||||
|
||||
// I used to have all the Xobjects mapped out. Not anymore.
|
||||
// (Thanks for the great firmware, Seagate!)
|
||||
struct Xsprite
|
||||
{
|
||||
uint8_t NotReallyPadding[16];
|
||||
uint16_t Data1;
|
||||
uint16_t Data2;
|
||||
uint16_t Data3;
|
||||
uint16_t ThisIsntPaddingEither;
|
||||
uint32_t NorThis:2;
|
||||
uint32_t Data4:16;
|
||||
uint32_t WhatIsThisIDontEven:14;
|
||||
uint8_t ThisNeedsToBe56Bytes[28];
|
||||
};
|
||||
|
||||
struct SlopeWork
|
||||
{
|
||||
walltype *wal;
|
||||
walltype *wal2;
|
||||
long dx, dy, i, x[3], y[3], z[3];
|
||||
long heinum;
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
void P_AdjustLine (line_t *line);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static bool P_LoadBloodMap (uint8_t *data, size_t len, FMapThing **sprites, int *numsprites);
|
||||
static void LoadSectors (sectortype *bsectors, int count);
|
||||
static void LoadWalls (walltype *walls, int numwalls, sectortype *bsectors);
|
||||
static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites, sectortype *bsectors, FMapThing *mapthings);
|
||||
static vertex_t *FindVertex (int32_t x, int32_t y);
|
||||
static void CreateStartSpot (int32_t *pos, FMapThing *start);
|
||||
static void CalcPlane (SlopeWork &slope, secplane_t &plane);
|
||||
static void Decrypt (void *to, const void *from, int len, int key);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
bool P_IsBuildMap(MapData *map)
|
||||
{
|
||||
uint32_t len = map->Size(ML_LABEL);
|
||||
if (len < 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint8_t *data = new uint8_t[len];
|
||||
|
||||
map->Seek(ML_LABEL);
|
||||
map->Read(ML_LABEL, data);
|
||||
|
||||
// Check for a Blood map.
|
||||
if (*(uint32_t *)data == MAKE_ID('B','L','M','\x1a'))
|
||||
{
|
||||
delete[] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
const int numsec = LittleShort(*(uint16_t *)(data + 20));
|
||||
int numwalls;
|
||||
|
||||
if (len < 26 + numsec*sizeof(sectortype) ||
|
||||
(numwalls = LittleShort(*(uint16_t *)(data + 22 + numsec*sizeof(sectortype))),
|
||||
len < 24 + numsec*sizeof(sectortype) + numwalls*sizeof(walltype)) ||
|
||||
LittleLong(*(uint32_t *)data) != 7 ||
|
||||
LittleShort(*(uint16_t *)(data + 16)) >= 2048)
|
||||
{ // Can't possibly be a version 7 BUILD map
|
||||
delete[] data;
|
||||
return false;
|
||||
}
|
||||
delete[] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LoadBuildMap
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool P_LoadBuildMap (uint8_t *data, size_t len, FMapThing **sprites, int *numspr)
|
||||
{
|
||||
if (len < 26)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a Blood map.
|
||||
if (*(uint32_t *)data == MAKE_ID('B','L','M','\x1a'))
|
||||
{
|
||||
return P_LoadBloodMap (data, len, sprites, numspr);
|
||||
}
|
||||
|
||||
const int numsec = LittleShort(*(uint16_t *)(data + 20));
|
||||
int numwalls;
|
||||
int numsprites;
|
||||
|
||||
if (len < 26 + numsec*sizeof(sectortype) ||
|
||||
(numwalls = LittleShort(*(uint16_t *)(data + 22 + numsec*sizeof(sectortype))),
|
||||
len < 24 + numsec*sizeof(sectortype) + numwalls*sizeof(walltype)) ||
|
||||
LittleLong(*(uint32_t *)data) != 7 ||
|
||||
LittleShort(*(uint16_t *)(data + 16)) >= 2048)
|
||||
{ // Can't possibly be a version 7 BUILD map
|
||||
return false;
|
||||
}
|
||||
|
||||
LoadSectors ((sectortype *)(data + 22), numsec);
|
||||
LoadWalls ((walltype *)(data + 24 + numsec*sizeof(sectortype)), numwalls,
|
||||
(sectortype *)(data + 22));
|
||||
|
||||
numsprites = *(uint16_t *)(data + 24 + numsec*sizeof(sectortype) + numwalls*sizeof(walltype));
|
||||
*sprites = new FMapThing[numsprites + 1];
|
||||
CreateStartSpot ((int32_t *)(data + 4), *sprites);
|
||||
*numspr = 1 + LoadSprites ((spritetype *)(data + 26 + numsec*sizeof(sectortype) + numwalls*sizeof(walltype)),
|
||||
NULL, numsprites, (sectortype *)(data + 22), *sprites + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LoadBloodMap
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool P_LoadBloodMap (uint8_t *data, size_t len, FMapThing **mapthings, int *numspr)
|
||||
{
|
||||
uint8_t infoBlock[37];
|
||||
int mapver = data[5];
|
||||
uint32_t matt;
|
||||
int numRevisions, numWalls, numsprites, skyLen, visibility, parallaxType;
|
||||
int i;
|
||||
int k;
|
||||
|
||||
if (mapver != 6 && mapver != 7)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
matt = *(uint32_t *)(data + 28);
|
||||
if (matt != 0 &&
|
||||
matt != MAKE_ID('M','a','t','t') &&
|
||||
matt != MAKE_ID('t','t','a','M'))
|
||||
{
|
||||
Decrypt (infoBlock, data + 6, 37, 0x7474614d);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (infoBlock, data + 6, 37);
|
||||
}
|
||||
skyLen = 2 << LittleShort(*(uint16_t *)(infoBlock + 16));
|
||||
visibility = LittleLong(*(uint32_t *)(infoBlock + 18));
|
||||
parallaxType = infoBlock[26];
|
||||
numRevisions = LittleLong(*(uint32_t *)(infoBlock + 27));
|
||||
int numsectors = LittleShort(*(uint16_t *)(infoBlock + 31));
|
||||
numWalls = LittleShort(*(uint16_t *)(infoBlock + 33));
|
||||
numsprites = LittleShort(*(uint16_t *)(infoBlock + 35));
|
||||
Printf("Visibility: %d\n", visibility);
|
||||
|
||||
if (mapver == 7)
|
||||
{
|
||||
// Version 7 has some extra stuff after the info block. This
|
||||
// includes a copyright, and I have no idea what the rest of
|
||||
// it is.
|
||||
data += 171;
|
||||
}
|
||||
else
|
||||
{
|
||||
data += 43;
|
||||
}
|
||||
|
||||
// Skip the sky info.
|
||||
data += skyLen;
|
||||
|
||||
sectortype *bsec = new sectortype[numsectors];
|
||||
walltype *bwal = new walltype[numWalls];
|
||||
spritetype *bspr = new spritetype[numsprites];
|
||||
Xsprite *xspr = new Xsprite[numsprites];
|
||||
|
||||
// Read sectors
|
||||
k = numRevisions * sizeof(sectortype);
|
||||
for (i = 0; i < numsectors; ++i)
|
||||
{
|
||||
if (mapver == 7)
|
||||
{
|
||||
Decrypt (&bsec[i], data, sizeof(sectortype), k);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&bsec[i], data, sizeof(sectortype));
|
||||
}
|
||||
data += sizeof(sectortype);
|
||||
if (bsec[i].extra > 0) // skip Xsector
|
||||
{
|
||||
data += 60;
|
||||
}
|
||||
}
|
||||
|
||||
// Read walls
|
||||
k |= 0x7474614d;
|
||||
for (i = 0; i < numWalls; ++i)
|
||||
{
|
||||
if (mapver == 7)
|
||||
{
|
||||
Decrypt (&bwal[i], data, sizeof(walltype), k);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&bwal[i], data, sizeof(walltype));
|
||||
}
|
||||
data += sizeof(walltype);
|
||||
if (bwal[i].extra > 0) // skip Xwall
|
||||
{
|
||||
data += 24;
|
||||
}
|
||||
}
|
||||
|
||||
// Read sprites
|
||||
k = (numRevisions * sizeof(spritetype)) | 0x7474614d;
|
||||
for (i = 0; i < numsprites; ++i)
|
||||
{
|
||||
if (mapver == 7)
|
||||
{
|
||||
Decrypt (&bspr[i], data, sizeof(spritetype), k);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&bspr[i], data, sizeof(spritetype));
|
||||
}
|
||||
data += sizeof(spritetype);
|
||||
if (bspr[i].extra > 0) // copy Xsprite
|
||||
{
|
||||
assert(sizeof(Xsprite) == 56);
|
||||
memcpy(&xspr[i], data, sizeof(Xsprite));
|
||||
data += sizeof(Xsprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&xspr[i], 0, sizeof(Xsprite));
|
||||
}
|
||||
}
|
||||
|
||||
// Now convert to Doom format, since we've extracted all the standard
|
||||
// BUILD info from the map we need. (Sprites are ignored.)
|
||||
LoadSectors (bsec, numsectors);
|
||||
LoadWalls (bwal, numWalls, bsec);
|
||||
*mapthings = new FMapThing[numsprites];
|
||||
*numspr = LoadSprites (bspr, xspr, numsprites, bsec, *mapthings);
|
||||
|
||||
delete[] bsec;
|
||||
delete[] bwal;
|
||||
delete[] bspr;
|
||||
delete[] xspr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// LoadSectors
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void LoadSectors (sectortype *bsec, int count)
|
||||
{
|
||||
sector_t *sec;
|
||||
char tnam[9];
|
||||
|
||||
level.sectors.Alloc(count);
|
||||
sec = &level.sectors[0];
|
||||
memset (sec, 0, sizeof(sector_t)*count);
|
||||
|
||||
sec->e = new extsector_t[count];
|
||||
|
||||
for (int i = 0; i < count; ++i, ++bsec, ++sec)
|
||||
{
|
||||
bsec->wallptr = uint16_t(bsec->wallptr);
|
||||
bsec->wallnum = uint16_t(bsec->wallnum);
|
||||
bsec->ceilingstat = uint16_t(bsec->ceilingstat);
|
||||
bsec->floorstat = uint16_t(bsec->floorstat);
|
||||
|
||||
sec->e = &sec->e[i];
|
||||
double floorheight = -LittleLong(bsec->floorZ) / 256.;
|
||||
sec->SetPlaneTexZ(sector_t::floor, floorheight);
|
||||
sec->floorplane.SetAtHeight(floorheight, sector_t::floor);
|
||||
mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(bsec->floorpicnum));
|
||||
sec->SetTexture(sector_t::floor, TexMan.GetTexture (tnam, FTexture::TEX_Build));
|
||||
sec->SetXScale(sector_t::floor, (bsec->floorstat & 8) ? 2. : 1.);
|
||||
sec->SetYScale(sector_t::floor, (bsec->floorstat & 8) ? 2. : 1.);
|
||||
sec->SetXOffset(sector_t::floor, bsec->floorxpanning + 32.);
|
||||
sec->SetYOffset(sector_t::floor, bsec->floorypanning + 0.);
|
||||
sec->SetPlaneLight(sector_t::floor, SHADE2LIGHT (bsec->floorshade));
|
||||
sec->ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING);
|
||||
|
||||
double ceilingheight = -LittleLong(bsec->ceilingZ) / 256.;
|
||||
sec->SetPlaneTexZ(sector_t::ceiling, ceilingheight);
|
||||
sec->ceilingplane.SetAtHeight(ceilingheight, sector_t::ceiling);
|
||||
mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(bsec->ceilingpicnum));
|
||||
sec->SetTexture(sector_t::ceiling, TexMan.GetTexture (tnam, FTexture::TEX_Build));
|
||||
if (bsec->ceilingstat & 1)
|
||||
{
|
||||
sky1texture = sky2texture = sec->GetTexture(sector_t::ceiling);
|
||||
sec->SetTexture(sector_t::ceiling, skyflatnum);
|
||||
}
|
||||
sec->SetXScale(sector_t::ceiling, (bsec->ceilingstat & 8) ? 2. : 1.);
|
||||
sec->SetYScale(sector_t::ceiling, (bsec->ceilingstat & 8) ? 2. : 1.);
|
||||
sec->SetXOffset(sector_t::ceiling, bsec->ceilingxpanning + 32.);
|
||||
sec->SetYOffset(sector_t::ceiling, bsec->ceilingypanning + 0.);
|
||||
sec->SetPlaneLight(sector_t::ceiling, SHADE2LIGHT (bsec->ceilingshade));
|
||||
sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING);
|
||||
|
||||
sec->lightlevel = (sec->GetPlaneLight(sector_t::floor) + sec->GetPlaneLight(sector_t::ceiling)) / 2;
|
||||
|
||||
sec->seqType = -1;
|
||||
sec->SeqName = NAME_None;
|
||||
sec->nextsec = -1;
|
||||
sec->prevsec = -1;
|
||||
sec->gravity = 1.f;
|
||||
sec->friction = ORIG_FRICTION;
|
||||
sec->movefactor = ORIG_FRICTION_FACTOR;
|
||||
sec->ColorMap = map;
|
||||
sec->ZoneNumber = 0xFFFF;
|
||||
sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1;
|
||||
|
||||
if (bsec->floorstat & 4)
|
||||
{
|
||||
sec->SetAngle(sector_t::floor, DAngle(90.));
|
||||
sec->SetXScale(sector_t::floor, -sec->GetXScale(sector_t::floor));
|
||||
}
|
||||
if (bsec->floorstat & 16)
|
||||
{
|
||||
sec->SetXScale(sector_t::floor, -sec->GetXScale(sector_t::floor));
|
||||
}
|
||||
if (bsec->floorstat & 32)
|
||||
{
|
||||
sec->SetYScale(sector_t::floor, -sec->GetYScale(sector_t::floor));
|
||||
}
|
||||
|
||||
if (bsec->ceilingstat & 4)
|
||||
{
|
||||
sec->SetAngle(sector_t::ceiling, DAngle(90.));
|
||||
sec->SetYScale(sector_t::ceiling, -sec->GetYScale(sector_t::ceiling));
|
||||
}
|
||||
if (bsec->ceilingstat & 16)
|
||||
{
|
||||
sec->SetXScale(sector_t::ceiling, -sec->GetXScale(sector_t::ceiling));
|
||||
}
|
||||
if (bsec->ceilingstat & 32)
|
||||
{
|
||||
sec->SetYScale(sector_t::ceiling, -sec->GetYScale(sector_t::ceiling));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// LoadWalls
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
// Setting numvertexes to the same as numwalls is overly conservative,
|
||||
// but the extra vertices will be removed during the BSP building pass.
|
||||
numsides = numvertexes = numwalls;
|
||||
int numlines = 0;
|
||||
|
||||
sides = new side_t[numsides];
|
||||
memset (sides, 0, numsides*sizeof(side_t));
|
||||
|
||||
vertexes = new vertex_t[numvertexes];
|
||||
numvertexes = 0;
|
||||
|
||||
// First mark each sidedef with the sector it belongs to
|
||||
for (unsigned i = 0; i < level.sectors.Size(); i++)
|
||||
{
|
||||
if (bsec[i].wallptr >= 0)
|
||||
{
|
||||
for (j = 0; j < bsec[i].wallnum; ++j)
|
||||
{
|
||||
sides[j + bsec[i].wallptr].sector = &level.sectors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now copy wall properties to their matching sidedefs
|
||||
for (i = 0; i < numwalls; ++i)
|
||||
{
|
||||
char tnam[9];
|
||||
FTextureID overpic, pic;
|
||||
|
||||
mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(walls[i].picnum));
|
||||
pic = TexMan.GetTexture (tnam, FTexture::TEX_Build);
|
||||
mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(walls[i].overpicnum));
|
||||
overpic = TexMan.GetTexture (tnam, FTexture::TEX_Build);
|
||||
|
||||
walls[i].x = LittleLong(walls[i].x);
|
||||
walls[i].y = LittleLong(walls[i].y);
|
||||
walls[i].point2 = LittleShort(walls[i].point2);
|
||||
walls[i].cstat = LittleShort(walls[i].cstat);
|
||||
walls[i].nextwall = LittleShort(walls[i].nextwall);
|
||||
walls[i].nextsector = LittleShort(walls[i].nextsector);
|
||||
|
||||
sides[i].SetTextureXOffset((double)walls[i].xpanning);
|
||||
sides[i].SetTextureYOffset((double)walls[i].ypanning);
|
||||
|
||||
sides[i].SetTexture(side_t::top, pic);
|
||||
sides[i].SetTexture(side_t::bottom, pic);
|
||||
if (walls[i].nextsector < 0 || (walls[i].cstat & 32))
|
||||
{
|
||||
sides[i].SetTexture(side_t::mid, pic);
|
||||
}
|
||||
else if (walls[i].cstat & 16)
|
||||
{
|
||||
sides[i].SetTexture(side_t::mid, overpic);
|
||||
}
|
||||
else
|
||||
{
|
||||
sides[i].SetTexture(side_t::mid, FNullTextureID());
|
||||
}
|
||||
|
||||
sides[i].TexelLength = walls[i].xrepeat * 8;
|
||||
sides[i].SetTextureYScale(walls[i].yrepeat / 8.);
|
||||
sides[i].SetTextureXScale(1.);
|
||||
sides[i].SetLight(SHADE2LIGHT(walls[i].shade));
|
||||
sides[i].Flags = WALLF_ABSLIGHTING;
|
||||
sides[i].RightSide = walls[i].point2;
|
||||
sides[walls[i].point2].LeftSide = i;
|
||||
|
||||
if (walls[i].nextwall >= 0 && walls[i].nextwall <= i)
|
||||
{
|
||||
sides[i].linedef = sides[walls[i].nextwall].linedef;
|
||||
}
|
||||
else
|
||||
{
|
||||
sides[i].linedef = (line_t*)(intptr_t)(numlines++);
|
||||
}
|
||||
}
|
||||
|
||||
// Set line properties that Doom doesn't store per-sidedef
|
||||
level.lines.Alloc(numlines);
|
||||
memset (&level.lines[0], 0, numlines*sizeof(line_t));
|
||||
|
||||
for (i = 0, j = -1; i < numwalls; ++i)
|
||||
{
|
||||
if (walls[i].nextwall >= 0 && walls[i].nextwall <= i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
j = int(intptr_t(sides[i].linedef));
|
||||
auto &lines = level.lines;
|
||||
lines[j].sidedef[0] = (side_t*)(intptr_t)i;
|
||||
lines[j].sidedef[1] = (side_t*)(intptr_t)walls[i].nextwall;
|
||||
lines[j].v1 = FindVertex (walls[i].x, walls[i].y);
|
||||
lines[j].v2 = FindVertex (walls[walls[i].point2].x, walls[walls[i].point2].y);
|
||||
lines[j].frontsector = sides[i].sector;
|
||||
lines[j].flags |= ML_WRAP_MIDTEX;
|
||||
if (walls[i].nextsector >= 0)
|
||||
{
|
||||
lines[j].backsector = &level.sectors[walls[i].nextsector];
|
||||
lines[j].flags |= ML_TWOSIDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[j].backsector = NULL;
|
||||
}
|
||||
P_AdjustLine (&lines[j]);
|
||||
if (walls[i].cstat & 128)
|
||||
{
|
||||
if (walls[i].cstat & 512)
|
||||
{
|
||||
lines[j].alpha = 1/3.;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[j].alpha = 2/3.;
|
||||
}
|
||||
}
|
||||
if (walls[i].cstat & 1)
|
||||
{
|
||||
lines[j].flags |= ML_BLOCKING;
|
||||
}
|
||||
if (walls[i].nextwall < 0)
|
||||
{
|
||||
if (walls[i].cstat & 4)
|
||||
{
|
||||
lines[j].flags |= ML_DONTPEGBOTTOM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (walls[i].cstat & 4)
|
||||
{
|
||||
lines[j].flags |= ML_DONTPEGTOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[j].flags |= ML_DONTPEGBOTTOM;
|
||||
}
|
||||
}
|
||||
if (walls[i].cstat & 64)
|
||||
{
|
||||
lines[j].flags |= ML_BLOCKEVERYTHING;
|
||||
}
|
||||
}
|
||||
|
||||
// Finish setting sector properties that depend on walls
|
||||
for (auto &sec : level.sectors)
|
||||
{
|
||||
SlopeWork slope;
|
||||
|
||||
slope.wal = &walls[bsec->wallptr];
|
||||
slope.wal2 = &walls[slope.wal->point2];
|
||||
slope.dx = slope.wal2->x - slope.wal->x;
|
||||
slope.dy = slope.wal2->y - slope.wal->y;
|
||||
slope.i = long (g_sqrt ((double)(slope.dx*slope.dx+slope.dy*slope.dy))) << 5;
|
||||
if (slope.i == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((bsec->floorstat & 2) && (bsec->floorheinum != 0))
|
||||
{ // floor is sloped
|
||||
slope.heinum = -LittleShort(bsec->floorheinum);
|
||||
slope.z[0] = slope.z[1] = slope.z[2] = -bsec->floorZ;
|
||||
CalcPlane (slope, sec.floorplane);
|
||||
}
|
||||
if ((bsec->ceilingstat & 2) && (bsec->ceilingheinum != 0))
|
||||
{ // ceiling is sloped
|
||||
slope.heinum = -LittleShort(bsec->ceilingheinum);
|
||||
slope.z[0] = slope.z[1] = slope.z[2] = -bsec->ceilingZ;
|
||||
CalcPlane (slope, sec.ceilingplane);
|
||||
}
|
||||
int linenum = sides[bsec->wallptr].linedef->Index();
|
||||
int sidenum = int(intptr_t(level.lines[linenum].sidedef[1] - sides));
|
||||
if (bsec->floorstat & 64)
|
||||
{ // floor is aligned to first wall
|
||||
P_AlignFlat (linenum, sidenum == bsec->wallptr, 0);
|
||||
}
|
||||
if (bsec->ceilingstat & 64)
|
||||
{ // ceiling is aligned to first wall
|
||||
P_AlignFlat (linenum, sidenum == bsec->wallptr, 0);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
intptr_t front = intptr_t(level.lines[i].sidedef[0]-sides);
|
||||
intptr_t back = intptr_t(level.lines[i].sidedef[1]-sides);
|
||||
lines[i].sidedef[0] = front >= 0 ? &sides[front] : NULL;
|
||||
lines[i].sidedef[1] = back >= 0 ? &sides[back] : NULL;
|
||||
}
|
||||
for (i = 0; i < numsides; i++)
|
||||
{
|
||||
assert(sides[i].sector != NULL);
|
||||
sides[i].linedef = &lines[intptr_t(sides[i].linedef)];
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// LoadSprites
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int LoadSprites (spritetype *sprites, Xsprite *xsprites, int numsprites,
|
||||
sectortype *bsectors, FMapThing *mapthings)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
memset(mapthings, 0, sizeof(*mapthings)*numsprites);
|
||||
|
||||
for (int i = 0; i < numsprites; ++i)
|
||||
{
|
||||
mapthings[count].thingid = 0;
|
||||
mapthings[count].pos.X = sprites[i].x / 16.;
|
||||
mapthings[count].pos.Y = -sprites[i].y / 16.;
|
||||
mapthings[count].pos.Z = (bsectors[sprites[i].sectnum].floorZ - sprites[i].z) / 256.;
|
||||
mapthings[count].angle = (((2048-sprites[i].ang) & 2047) * 360) >> 11;
|
||||
mapthings[count].ClassFilter = 0xffff;
|
||||
mapthings[count].SkillFilter = 0xffff;
|
||||
mapthings[count].flags = MTF_SINGLE|MTF_COOPERATIVE|MTF_DEATHMATCH;
|
||||
mapthings[count].special = 0;
|
||||
mapthings[count].Gravity = 1.;
|
||||
mapthings[count].RenderStyle = STYLE_Count;
|
||||
mapthings[count].Alpha = -1;
|
||||
mapthings[count].health = -1;
|
||||
mapthings[count].FloatbobPhase = -1;
|
||||
|
||||
if (xsprites != NULL && sprites[i].lotag == 710)
|
||||
{ // Blood ambient sound
|
||||
mapthings[count].args[0] = xsprites[i].Data3;
|
||||
// I am totally guessing about the volume level. 50 seems to be a pretty
|
||||
// typical value for Blood's standard maps, so I assume it's 100-based.
|
||||
mapthings[count].args[1] = xsprites[i].Data4;
|
||||
mapthings[count].args[2] = xsprites[i].Data1;
|
||||
mapthings[count].args[3] = xsprites[i].Data2;
|
||||
mapthings[count].EdNum = 14065;
|
||||
}
|
||||
else if (xsprites != NULL && sprites[i].lotag == 1)
|
||||
{ // Blood player start
|
||||
if (xsprites[i].Data1 < 4)
|
||||
mapthings[count].EdNum= 1 + xsprites[i].Data1;
|
||||
else
|
||||
mapthings[count].EdNum = 4001 + xsprites[i].Data1 - 4;
|
||||
}
|
||||
else if (xsprites != NULL && sprites[i].lotag == 2)
|
||||
{ // Bloodbath start
|
||||
mapthings[count].EdNum = 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprites[i].cstat & 32768) continue;
|
||||
if (sprites[i].xrepeat == 0 || sprites[i].yrepeat == 0) continue;
|
||||
|
||||
mapthings[count].EdNum = 9988;
|
||||
mapthings[count].args[0] = sprites[i].picnum;
|
||||
mapthings[count].args[2] = sprites[i].xrepeat;
|
||||
mapthings[count].args[3] = sprites[i].yrepeat;
|
||||
mapthings[count].args[4] = sprites[i].cstat;
|
||||
}
|
||||
mapthings[count].info = DoomEdMap.CheckKey(mapthings[count].EdNum);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FindVertex
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
vertex_t *FindVertex (int32_t xx, int32_t yy)
|
||||
{
|
||||
int i;
|
||||
|
||||
double x = xx / 64.;
|
||||
double y = -yy / 64.;
|
||||
|
||||
for (i = 0; i < numvertexes; ++i)
|
||||
{
|
||||
if (vertexes[i].fX() == x && vertexes[i].fY() == y)
|
||||
{
|
||||
return &vertexes[i];
|
||||
}
|
||||
}
|
||||
vertexes[i].set(x, y);
|
||||
numvertexes++;
|
||||
return &vertexes[i];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CreateStartSpot
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void CreateStartSpot (int32_t *pos, FMapThing *start)
|
||||
{
|
||||
short angle = LittleShort(*(uint16_t *)(&pos[3]));
|
||||
FMapThing mt = { 0, };
|
||||
|
||||
mt.pos.X = LittleLong(pos[0]) / 16.;
|
||||
mt.pos.Y = -LittleLong(pos[1]) / 16.;
|
||||
mt.angle = short(Scale((2048-angle)&2047, 360, 2048));
|
||||
mt.info = DoomEdMap.CheckKey(1);
|
||||
mt.EdNum = 1;
|
||||
mt.flags = 7|MTF_SINGLE|224;
|
||||
|
||||
*start = mt;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CalcPlane
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void CalcPlane (SlopeWork &slope, secplane_t &plane)
|
||||
{
|
||||
DVector3 pt[3];
|
||||
long j;
|
||||
|
||||
slope.x[0] = slope.wal->x; slope.y[0] = slope.wal->y;
|
||||
slope.x[1] = slope.wal2->x; slope.y[1] = slope.wal2->y;
|
||||
if (slope.dx == 0)
|
||||
{
|
||||
slope.x[2] = slope.x[0] + 64;
|
||||
slope.y[2] = slope.y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
slope.x[2] = slope.x[0];
|
||||
slope.y[2] = slope.y[0] + 64;
|
||||
}
|
||||
j = DMulScale3 (slope.dx, slope.y[2]-slope.wal->y, -slope.dy, slope.x[2]-slope.wal->x);
|
||||
slope.z[2] += Scale (slope.heinum, j, slope.i);
|
||||
|
||||
pt[0] = DVector3(slope.dx, -slope.dy, 0);
|
||||
pt[1] = DVector3(slope.x[2] - slope.x[0], slope.y[0] - slope.y[2], (slope.z[2] - slope.z[0]) / 16);
|
||||
pt[2] = (pt[0] ^ pt[1]).Unit();
|
||||
|
||||
if ((pt[2][2] < 0 && plane.fC() > 0) || (pt[2][2] > 0 && plane.fC() < 0))
|
||||
{
|
||||
pt[2] = -pt[2];
|
||||
}
|
||||
|
||||
double dist = -pt[2][0] * slope.x[0] * 16 + pt[2][1] * slope.y[0] * 16 - pt[2][2] * slope.z[0];
|
||||
plane.set(pt[2][0], pt[2][1], pt[2][2], dist);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Decrypt
|
||||
//
|
||||
// Note that this is different from the general RFF encryption.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void Decrypt (void *to_, const void *from_, int len, int key)
|
||||
{
|
||||
uint8_t *to = (uint8_t *)to_;
|
||||
const uint8_t *from = (const uint8_t *)from_;
|
||||
|
||||
for (int i = 0; i < len; ++i, ++key)
|
||||
{
|
||||
to[i] = from[i] ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1934,10 +1934,17 @@ public:
|
|||
P_AdjustLine(&lines[line]);
|
||||
P_FinishLoadingLineDef(&lines[line], tempalpha[0]);
|
||||
}
|
||||
assert((unsigned)side <= level.sides.Size());
|
||||
if ((unsigned)side > level.sides.Size())
|
||||
|
||||
const int sideDelta = level.sides.Size() - side;
|
||||
assert(sideDelta >= 0);
|
||||
|
||||
if (sideDelta < 0)
|
||||
{
|
||||
Printf("Map had %d invalid side references\n", (int)level.sides.Size() - side);
|
||||
Printf("Map had %d invalid side references\n", abs(sideDelta));
|
||||
}
|
||||
else if (sideDelta > 0)
|
||||
{
|
||||
level.sides.Resize(side);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2066,6 +2073,7 @@ public:
|
|||
else if (sc.Compare("sector"))
|
||||
{
|
||||
sector_t sec;
|
||||
memset(&sec, 0, sizeof(sector_t));
|
||||
ParseSector(&sec, ParsedSectors.Size());
|
||||
ParsedSectors.Push(sec);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ struct SoundDecoder
|
|||
|
||||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||
virtual TArray<char> readAll();
|
||||
virtual bool seek(size_t ms_offset, bool ms) = 0;
|
||||
virtual bool seek(size_t ms_offset, bool ms, bool mayrestart) = 0;
|
||||
virtual size_t getSampleOffset() = 0;
|
||||
virtual size_t getSampleLength() { return 0; }
|
||||
|
||||
|
|
|
@ -190,23 +190,38 @@ size_t MPG123Decoder::read(char *buffer, size_t bytes)
|
|||
return amt;
|
||||
}
|
||||
|
||||
bool MPG123Decoder::seek(size_t ms_offset, bool ms)
|
||||
bool MPG123Decoder::seek(size_t ms_offset, bool ms, bool mayrestart)
|
||||
{
|
||||
int enc, channels;
|
||||
long srate;
|
||||
int enc, channels;
|
||||
long srate;
|
||||
|
||||
if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
|
||||
{
|
||||
size_t smp_offset = ms? (size_t)((double)ms_offset / 1000. * srate) : ms_offset;
|
||||
if(mpg123_seek(MPG123, (off_t)smp_offset, SEEK_SET) >= 0)
|
||||
{
|
||||
Done = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!mayrestart || ms_offset > 0)
|
||||
{
|
||||
if (mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK)
|
||||
{
|
||||
size_t smp_offset = ms ? (size_t)((double)ms_offset / 1000. * srate) : ms_offset;
|
||||
if (mpg123_seek(MPG123, (off_t)smp_offset, SEEK_SET) >= 0)
|
||||
{
|
||||
Done = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restart the song instead of rewinding. A rewind seems to cause distortion when done repeatedly.
|
||||
// offset is intentionally ignored here.
|
||||
if (MPG123)
|
||||
{
|
||||
mpg123_close(MPG123);
|
||||
mpg123_delete(MPG123);
|
||||
MPG123 = 0;
|
||||
}
|
||||
Reader->Seek(0, SEEK_SET);
|
||||
return open(Reader);
|
||||
}
|
||||
}
|
||||
|
||||
size_t MPG123Decoder::getSampleOffset()
|
||||
{
|
||||
return mpg123_tell(MPG123);
|
||||
|
|
|
@ -21,7 +21,7 @@ struct MPG123Decoder : public SoundDecoder
|
|||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes);
|
||||
virtual bool seek(size_t ms_offset, bool ms);
|
||||
virtual bool seek(size_t ms_offset, bool ms, bool mayrestart);
|
||||
virtual size_t getSampleOffset();
|
||||
virtual size_t getSampleLength();
|
||||
|
||||
|
|
|
@ -326,16 +326,39 @@ bool SndFileSong::Read(SoundStream *stream, void *vbuff, int ilen, void *userdat
|
|||
}
|
||||
else
|
||||
{
|
||||
// This looks a bit more complicated than necessary because libmpg123 will not read the full requested length for the last block in the file.
|
||||
if (currentpos + framestoread > song->Loop_End)
|
||||
{
|
||||
size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2;
|
||||
err = (song->Decoder->read(buff, endblock) != endblock);
|
||||
buff = buff + endblock;
|
||||
len -= endblock;
|
||||
song->Decoder->seek(song->Loop_Start, false);
|
||||
size_t endlen = song->Decoder->read(buff, endblock);
|
||||
if (endlen != 0)
|
||||
{
|
||||
buff = buff + endblock;
|
||||
len -= endblock;
|
||||
song->Decoder->seek(song->Loop_Start, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
song->CritSec.Leave();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (len > 0)
|
||||
{
|
||||
size_t readlen = song->Decoder->read(buff, len);
|
||||
if (readlen == 0)
|
||||
{
|
||||
song->CritSec.Leave();
|
||||
return false;
|
||||
}
|
||||
buff += readlen;
|
||||
len -= readlen;
|
||||
if (len > 0)
|
||||
{
|
||||
song->Decoder->seek(song->Loop_Start, false, true);
|
||||
}
|
||||
}
|
||||
err |= song->Decoder->read(buff, len) != len;
|
||||
}
|
||||
song->CritSec.Leave();
|
||||
return !err;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ class OpenALSoundStream : public SoundStream
|
|||
size_t got = self->Decoder->read((char*)ptr, length);
|
||||
if(got < (unsigned int)length)
|
||||
{
|
||||
if(!self->Looping || !self->Decoder->seek(0, false))
|
||||
if(!self->Looping || !self->Decoder->seek(0, false, true))
|
||||
return false;
|
||||
got += self->Decoder->read((char*)ptr+got, length-got);
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ public:
|
|||
virtual bool SetPosition(unsigned int ms_pos)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(Renderer->StreamLock);
|
||||
if(!Decoder->seek(ms_pos, true))
|
||||
if(!Decoder->seek(ms_pos, true, false))
|
||||
return false;
|
||||
|
||||
if(!Playing.load())
|
||||
|
|
|
@ -190,7 +190,7 @@ TArray<char> SndFileDecoder::readAll()
|
|||
return output;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::seek(size_t ms_offset, bool ms)
|
||||
bool SndFileDecoder::seek(size_t ms_offset, bool ms, bool /*mayrestart*/)
|
||||
{
|
||||
size_t smp_offset = ms? (size_t)((double)ms_offset / 1000. * SndInfo.samplerate) : ms_offset;
|
||||
if(sf_seek(SndFile, smp_offset, SEEK_SET) < 0)
|
||||
|
|
|
@ -17,8 +17,8 @@ struct SndFileDecoder : public SoundDecoder
|
|||
|
||||
virtual size_t read(char *buffer, size_t bytes);
|
||||
virtual TArray<char> readAll();
|
||||
virtual bool seek(size_t ms_offset, bool ms);
|
||||
virtual size_t getSampleOffset();
|
||||
virtual bool seek(size_t ms_offset, bool ms, bool mayrestart);
|
||||
virtual size_t getSampleOffset();
|
||||
virtual size_t getSampleLength();
|
||||
|
||||
SndFileDecoder() : SndFile(0) { }
|
||||
|
|
|
@ -500,6 +500,24 @@ class SaveMenu : LoadSaveMenu
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
if (mSaveName.Length() > 0)
|
||||
{
|
||||
// Do not process events when saving is in progress to avoid update of the current index,
|
||||
// i.e. Selected member variable must remain unchanged
|
||||
return true;
|
||||
}
|
||||
|
||||
return Super.MouseEvent(type, x, y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
override bool OnUIEvent(UIEvent ev)
|
||||
{
|
||||
if (ev.Type == UIEvent.Type_KeyDown)
|
||||
|
|
Loading…
Reference in a new issue