Merge remote-tracking branch 'gzdoom/master' into newmaster

# Conflicts:
#	wadsrc/static/zscript/actors/actor.zs
This commit is contained in:
Major Cooke 2020-03-17 11:24:59 -05:00
commit 79321939de
74 changed files with 739 additions and 463 deletions

View file

@ -491,6 +491,9 @@ void DObject::StaticPointerSubstitution (AActor *old, AActor *notOld)
if (old == nullptr) return;
// This is only allowed to replace players. For everything else the results are undefined.
if (!old->IsKindOf(NAME_PlayerPawn) || (notOld != nullptr && !notOld->IsKindOf(NAME_PlayerPawn))) return;
// Go through all objects.
i = 0;DObject *last=0;
for (probe = GC::Root; probe != NULL; probe = probe->ObjNext)

View file

@ -313,6 +313,13 @@ CCMD (slot)
VMCall(func, param, 3, &ret, 1);
}
}
// [Nash] Option to display the name of the weapon being switched to.
if (SendItemUse != players[consoleplayer].ReadyWeapon && (displaynametags & 2) && StatusBar && SmallFont && SendItemUse)
{
StatusBar->AttachMessage(Create<DHUDMessageFadeOut>(nullptr, SendItemUse->GetTag(),
1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('W', 'E', 'P', 'N'));
}
}
}

View file

@ -666,7 +666,7 @@ void FFont::SetDefaultTranslation(uint32_t *othercolors)
}
}
}
Ranges[CR_UNTRANSLATED] = remap;
Translations[CR_UNTRANSLATED] = remap.StoreTranslation(TRANSLATION_Font);
forceremap = true;
}
@ -769,7 +769,7 @@ int FFont::SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_
//==========================================================================
void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity,
const void *ranges, int total_colors, const PalEntry *palette)
const void *ranges, int total_colors, const PalEntry *palette, std::function<void(FRemapTable*)> post)
{
int i, j;
const TranslationParm *parmstart = (const TranslationParm *)ranges;
@ -777,32 +777,32 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
FRemapTable remap(total_colors);
// Create different translations for different color ranges
Ranges.Clear();
Translations.Clear();
for (i = 0; i < NumTextColors; i++)
{
if (i == CR_UNTRANSLATED)
{
if (identity != nullptr)
{
memcpy (remap.Remap, identity, ActiveColors);
memcpy(remap.Remap, identity, ActiveColors);
if (palette != nullptr)
{
memcpy (remap.Palette, palette, ActiveColors*sizeof(PalEntry));
memcpy(remap.Palette, palette, ActiveColors * sizeof(PalEntry));
}
else
{
remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0,255,255,255);
remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0, 255, 255, 255);
for (j = 1; j < ActiveColors; ++j)
{
remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255,0,0,0);
remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255, 0, 0, 0);
}
}
Translations.Push(remap.StoreTranslation(TRANSLATION_Font));
}
else
{
remap = Ranges[0];
Translations.Push(Translations[0]);
}
Ranges.Push(remap);
continue;
}
@ -836,7 +836,8 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
remap.Remap[j] = ColorMatcher.Pick(r, g, b);
remap.Palette[j] = PalEntry(255,r,g,b);
}
Ranges.Push(remap);
if (post) post(&remap);
Translations.Push(remap.StoreTranslation(TRANSLATION_Font));
// Advance to the next color range.
while (parmstart[1].RangeStart > parmstart[0].RangeEnd)
@ -853,7 +854,7 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
//
//==========================================================================
FRemapTable *FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
{
if (noTranslate)
{
@ -866,11 +867,11 @@ FRemapTable *FFont::GetColorTranslation (EColorRange range, PalEntry *color) con
if (color != nullptr) *color = retcolor;
}
if (ActiveColors == 0)
return nullptr;
return -1;
else if (range >= NumTextColors)
range = CR_UNTRANSLATED;
//if (range == CR_UNTRANSLATED && !translateUntranslated) return nullptr;
return &Ranges[range];
return Translations[range];
}
//==========================================================================

View file

@ -417,7 +417,7 @@ public:
}
}
}
Ranges[CR_UNTRANSLATED] = remap;
Translations[CR_UNTRANSLATED] = remap.StoreTranslation(TRANSLATION_Font);
forceremap = true;
}

View file

@ -160,7 +160,7 @@ void FSpecialFont::LoadTranslations()
uint8_t identity[256];
TArray<double> Luminosity;
int TotalColors;
int i, j;
int i;
for (i = 0; i < count; i++)
{
@ -199,22 +199,20 @@ void FSpecialFont::LoadTranslations()
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
}
BuildTranslations (Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr);
// add the untranslated colors to the Ranges tables
if (ActiveColors < TotalColors)
{
for (i = 0; i < NumTextColors; i++)
BuildTranslations(Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr, [=](FRemapTable* remap)
{
FRemapTable *remap = &Ranges[i];
for (j = ActiveColors; j < TotalColors; ++j)
// add the untranslated colors to the Ranges tables
if (ActiveColors < TotalColors)
{
remap->Remap[j] = identity[j];
remap->Palette[j] = GPalette.BaseColors[identity[j]];
remap->Palette[j].a = 0xff;
for (int j = ActiveColors; j < TotalColors; ++j)
{
remap->Remap[j] = identity[j];
remap->Palette[j] = GPalette.BaseColors[identity[j]];
remap->Palette[j].a = 0xff;
}
}
}
}
});
ActiveColors = TotalColors;
}

View file

@ -39,8 +39,8 @@
#include "vectors.h"
class DCanvas;
struct FRemapTable;
class FTexture;
struct FRemapTable;
enum EColorRange : int
{
@ -98,7 +98,7 @@ public:
virtual FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const;
virtual int GetCharWidth (int code) const;
FRemapTable *GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
int GetLump() const { return Lump; }
int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; }
@ -137,7 +137,7 @@ protected:
FFont (int lump);
void BuildTranslations (const double *luminosity, const uint8_t *identity,
const void *ranges, int total_colors, const PalEntry *palette);
const void *ranges, int total_colors, const PalEntry *palette, std::function<void(FRemapTable*)> post = nullptr);
void FixXMoves();
static int SimpleTranslation (uint32_t *colorsused, uint8_t *translation,
@ -166,7 +166,7 @@ protected:
};
TArray<CharData> Chars;
int ActiveColors;
TArray<FRemapTable> Ranges;
TArray<int> Translations;
uint8_t PatchRemap[256];
int Lump;

View file

@ -116,6 +116,7 @@ const char* GameInfoBorders[] =
NULL
};
#define GAMEINFOKEY_CSTRING(key, variable, length) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
@ -382,6 +383,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_INT(fullscreenautoaspect, "fullscreenautoaspect")
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")

View file

@ -204,6 +204,7 @@ struct gameinfo_t
int berserkpic;
double normforwardmove[2];
double normsidemove[2];
int fullscreenautoaspect = 0;
const char *GetFinalePage(unsigned int num) const;
};

View file

@ -270,6 +270,7 @@ static void MakeDefaultTerrain ()
def.Name = "Solid";
def.Splash = -1;
def.DamageTimeMask = 31;
Terrains.Push (def);
}
@ -432,6 +433,7 @@ void ParseTerrain (FScanner &sc)
memset (&def, 0, sizeof(def));
def.Splash = -1;
def.Name = name;
def.DamageTimeMask = 31;
terrainnum = (int)Terrains.Push (def);
}
@ -443,6 +445,7 @@ void ParseTerrain (FScanner &sc)
memset (&Terrains[terrainnum], 0, sizeof(FTerrainDef));
Terrains[terrainnum].Splash = -1;
Terrains[terrainnum].Name = name;
Terrains[terrainnum].DamageTimeMask = 31;
}
else
{

View file

@ -1549,7 +1549,7 @@ void FTextureManager::GenerateGlobalBrightmapFromColormap()
if (lump == -1) return;
FMemLump cmap = Wads.ReadLump(lump);
uint8_t palbuffer[768];
ReadPalette(Wads.CheckNumForName("PLAYPAL"), palbuffer);
ReadPalette(Wads.GetNumForName("PLAYPAL"), palbuffer);
const unsigned char *cmapdata = (const unsigned char *)cmap.GetMem();
const uint8_t *paldata = palbuffer;

View file

@ -500,7 +500,7 @@ int FWadCollection::GetNumForName (const char *name, int space)
i = CheckNumForName (name, space);
if (i == -1)
I_Error ("W_GetNumForName: %s not found!", name);
I_Error ("GetNumForName: %s not found!", name);
return i;
}

View file

@ -231,7 +231,6 @@ void DIntermissionScreen::Drawer ()
if (CheckOverlay(i))
screen->DrawTexture (TexMan.GetTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE);
}
if (!mFlatfill) screen->FillBorder (NULL);
if (mSubtitle)
{
const char *sub = mSubtitle.GetChars();
@ -293,7 +292,6 @@ void DIntermissionScreenFader::Drawer ()
if (CheckOverlay(i))
screen->DrawTexture (TexMan.GetTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
}
screen->FillBorder (NULL);
}
}
@ -370,7 +368,6 @@ void DIntermissionScreenText::Drawer ()
int w;
size_t count;
int c;
const FRemapTable *range;
const uint8_t *ch = (const uint8_t*)mText.GetChars();
// Count number of rows in this text. Since it does not word-wrap, we just count
@ -424,7 +421,6 @@ void DIntermissionScreenText::Drawer ()
// draw some of the text onto the screen
count = (mTicker - mTextDelay) / mTextSpeed;
range = font->GetColorTranslation (mTextColor);
for ( ; count > 0 ; count-- )
{
@ -758,7 +754,6 @@ void DIntermissionScreenScroller::Drawer ()
DTA_Masked, false,
TAG_DONE);
screen->FillBorder (NULL);
mBackground = mSecondPic;
}
else
@ -923,6 +918,7 @@ void DIntermissionController::Drawer ()
{
if (mScreen != NULL)
{
screen->FillBorder(nullptr);
mScreen->Drawer();
}
}

View file

@ -232,7 +232,8 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, FindPSprite) // the underscore is needed to
void P_SetPsprite(player_t *player, PSPLayers id, FState *state, bool pending)
{
if (player == nullptr) return;
player->GetPSprite(id)->SetState(state, pending);
auto psp = player->GetPSprite(id);
if (psp) psp->SetState(state, pending);
}
DEFINE_ACTION_FUNCTION(_PlayerInfo, SetPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit)
@ -266,8 +267,8 @@ DPSprite *player_t::GetPSprite(PSPLayers layer)
newcaller = ReadyWeapon;
}
assert(newcaller != nullptr);
if (newcaller == nullptr) return nullptr; // Error case was not handled properly. This function cannot give a guarantee to always succeed!
DPSprite *pspr = FindPSprite(layer);
if (pspr == nullptr)
{

View file

@ -770,6 +770,35 @@ bool FRemapTable::AddToTranslation(const char *range)
}
}
//----------------------------------------------------------------------------
//
// Adds raw colors to a given translation
//
//----------------------------------------------------------------------------
bool FRemapTable::AddColors(int start, int count, const uint8_t*colors)
{
int end = start + count;
if (IndexOutOfRange(start, end))
{
return false;
}
for (int i = start; i < end; ++i)
{
auto br = colors[0];
auto bg = colors[1];
auto bb = colors[2];
colors += 3;
int j = GPalette.Remap[i];
Palette[j] = PalEntry(j == 0 ? 0 : 255, br, bg, bb);
Remap[j] = ColorMatcher.Pick(Palette[j]);
}
return true;
}
//----------------------------------------------------------------------------
//
// Stores a copy of this translation in the DECORATE translation table
@ -1521,16 +1550,30 @@ void R_ParseTrnslate()
do
{
sc.MustGetToken(TK_StringConst);
try
int pallump = Wads.CheckNumForFullName(sc.String, true, ns_global);
if (pallump >= 0) //
{
NewTranslation.AddToTranslation(sc.String);
int start = 0;
if (sc.CheckToken(','))
{
sc.MustGetValue(false);
start = sc.Number;
}
uint8_t palette[768];
int numcolors = ReadPalette(pallump, palette);
NewTranslation.AddColors(start, numcolors, palette);
}
catch (CRecoverableError &err)
else
{
sc.ScriptMessage("Error in translation '%s':\n" TEXTCOLOR_YELLOW "%s\n", sc.String, err.GetMessage());
try
{
NewTranslation.AddToTranslation(sc.String);
}
catch (CRecoverableError & err)
{
sc.ScriptMessage("Error in translation '%s':\n" TEXTCOLOR_YELLOW "%s\n", sc.String, err.GetMessage());
}
}
} while (sc.CheckToken(','));
int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom);

View file

@ -19,6 +19,7 @@ enum
TRANSLATION_Blood,
TRANSLATION_RainPillar,
TRANSLATION_Custom,
TRANSLATION_Font,
NUM_TRANSLATION_TABLES
};
@ -78,6 +79,7 @@ struct FRemapTable
bool AddColourisation(int start, int end, int r, int g, int b);
bool AddTint(int start, int end, int r, int g, int b, int amount);
bool AddToTranslation(const char * range);
bool AddColors(int start, int count, const uint8_t*);
int StoreTranslation(int slot);
int GetUniqueIndex();

View file

@ -48,6 +48,7 @@
#include "st_stuff.h"
#include "x86.h"
#include "g_levellocals.h"
#include "m_png.h"
uint32_t Col2RGB8[65][256];
uint32_t *Col2RGB8_LessPrecision[65];
@ -277,20 +278,45 @@ static int sortforremap2 (const void *a, const void *b)
}
}
void ReadPalette(int lumpnum, uint8_t *buffer)
int ReadPalette(int lumpnum, uint8_t *buffer)
{
if (lumpnum < 0)
{
I_FatalError("Palette not found");
return 0;
}
FMemLump lump = Wads.ReadLump(lumpnum);
uint8_t *lumpmem = (uint8_t*)lump.GetMem();
memset(buffer, 0, 768);
if (memcmp(lumpmem, "JASC-PAL", 8))
FileReader fr;
fr.OpenMemory(lumpmem, lump.GetSize());
auto png = M_VerifyPNG(fr);
if (png)
{
memcpy(buffer, lumpmem, MIN<size_t>(768, lump.GetSize()));
uint32_t id, len;
fr.Seek(33, FileReader::SeekSet);
fr.Read(&len, 4);
fr.Read(&id, 4);
bool succeeded = false;
while (id != MAKE_ID('I', 'D', 'A', 'T') && id != MAKE_ID('I', 'E', 'N', 'D'))
{
len = BigLong((unsigned int)len);
if (id != MAKE_ID('P', 'L', 'T', 'E'))
fr.Seek(len, FileReader::SeekCur);
else
{
int PaletteSize = MIN<int>(len, 768);
fr.Read(buffer, PaletteSize);
return PaletteSize / 3;
}
fr.Seek(4, FileReader::SeekCur); // Skip CRC
fr.Read(&len, 4);
id = MAKE_ID('I', 'E', 'N', 'D');
fr.Read(&id, 4);
}
I_Error("%s contains no palette", Wads.GetLumpFullName(lumpnum));
}
else
if (memcmp(lumpmem, "JASC-PAL", 8) == 0)
{
FScanner sc;
@ -308,6 +334,12 @@ void ReadPalette(int lumpnum, uint8_t *buffer)
}
buffer[i] = sc.Number;
}
return colors / 3;
}
else
{
memcpy(buffer, lumpmem, MIN<size_t>(768, lump.GetSize()));
return 256;
}
}
@ -371,7 +403,7 @@ void InitPalette ()
{
uint8_t pal[768];
ReadPalette(Wads.CheckNumForName("PLAYPAL"), pal);
ReadPalette(Wads.GetNumForName("PLAYPAL"), pal);
GPalette.SetPalette (pal);
GPalette.MakeGoodRemap ();

View file

@ -63,7 +63,7 @@ extern FPalette GPalette;
// The color overlay to use for depleted items
#define DIM_OVERLAY MAKEARGB(170,0,0,0)
void ReadPalette(int lumpnum, uint8_t *buffer);
int ReadPalette(int lumpnum, uint8_t *buffer);
void InitPalette ();
EXTERN_CVAR (Int, paletteflash)

View file

@ -393,12 +393,12 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
dg.mTexture = img;
if (img->isWarped()) dg.mFlags |= DTF_Wrap;
dg.mTranslation = 0;
dg.mTranslationId = 0;
SetStyle(img, parms, vertexcolor, dg);
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
if (!img->isHardwareCanvas() && parms.TranslationId != -1)
{
dg.mTranslation = parms.remap;
dg.mTranslationId = parms.TranslationId;
}
u1 = parms.srcx;
v1 = parms.srcy;
@ -472,11 +472,11 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
dg.mFlags |= DTF_Wrap;
dg.mTexture = img;
dg.mTranslation = 0;
dg.mTranslationId = 0;
SetStyle(img, parms, vertexcolor, dg);
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
dg.mTranslation = parms.remap;
if (!img->isHardwareCanvas() && parms.TranslationId != -1)
dg.mTranslationId = parms.TranslationId;
if (shape->dirty) {
if (shape->mVertices.Size() != shape->mTransformedVertices.Size())

View file

@ -109,7 +109,7 @@ public:
int mIndexCount;
FTexture *mTexture;
FRemapTable *mTranslation;
int mTranslationId;
PalEntry mSpecialColormap[2];
int mScissor[4];
int mDesaturate;
@ -128,7 +128,7 @@ public:
{
return mTexture == other.mTexture &&
mType == other.mType &&
mTranslation == other.mTranslation &&
mTranslationId == other.mTranslationId &&
mSpecialColormap[0].d == other.mSpecialColormap[0].d &&
mSpecialColormap[1].d == other.mSpecialColormap[1].d &&
!memcmp(mScissor, other.mScissor, sizeof(mScissor)) &&

View file

@ -375,8 +375,48 @@ bool DFrameBuffer::SetTextureParms(DrawParms *parms, FTexture *img, double xx, d
break;
case DTA_Fullscreen:
case DTA_FullscreenEx:
{
double aspect;
double srcwidth = img->GetDisplayWidthDouble();
double srcheight = img->GetDisplayHeightDouble();
int autoaspect = parms->fsscalemode;
aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 400)? 1.333 : srcwidth / srcheight;
parms->x = parms->y = 0;
break;
parms->keepratio = true;
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
if (autoaspect == 3)
{
if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxes if the screen is taller than the image
else if (screenratio > 1.32) autoaspect = 2; // on anything 4:3 and wider crop the sides of the image.
else
{
// special case: Crop image to 4:3 and then letterbox this. This avoids too much cropping on narrow windows.
double width4_3 = srcheight * (4. / 3.);
parms->destwidth = (double)GetWidth() * srcwidth / width4_3;
parms->destheight = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image
parms->y = (GetHeight() - parms->destheight) / 2;
parms->x = -(srcwidth - width4_3) / 2;
return false; // Do not call VirtualToRealCoords for this!
}
}
if ((screenratio > aspect) ^ (autoaspect == 2))
{
// pillarboxed or vertically cropped (i.e. scale to height)
parms->destheight = GetHeight();
parms->destwidth =GetWidth() * aspect / screenratio;
parms->x = (GetWidth() - parms->destwidth) / 2;
}
else
{
// letterboxed or horizontally cropped (i.e. scale to width)
parms->destwidth = GetWidth();
parms->destheight = GetHeight() * screenratio / aspect;
parms->y = (GetHeight() - parms->destheight) / 2;
}
return false; // Do not call VirtualToRealCoords for this!
}
case DTA_HUDRules:
case DTA_HUDRulesC:
@ -518,7 +558,7 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
parms->destheight = INT_MAX;
parms->Alpha = 1.f;
parms->fillcolor = -1;
parms->remap = NULL;
parms->TranslationId = -1;
parms->colorOverlay = 0;
parms->alphaChannel = false;
parms->flipX = false;
@ -667,12 +707,28 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
break;
case DTA_Fullscreen:
boolval = ListGetInt(tags);
if (boolval)
{
assert(fortext == false);
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)gameinfo.fullscreenautoaspect;
parms->virtWidth = img->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
}
break;
case DTA_FullscreenEx:
intval = ListGetInt(tags);
if (intval >= 0 && intval <= 3)
{
assert(fortext == false);
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)intval;
parms->virtWidth = img->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
}
@ -700,7 +756,7 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
break;
case DTA_TranslationIndex:
parms->remap = TranslationToTable(ListGetInt(tags));
parms->TranslationId = ListGetInt(tags);
break;
case DTA_ColorOverlay:
@ -915,11 +971,6 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
}
ListEnd(tags);
if (parms->remap != nullptr && parms->remap->Inactive)
{ // If it's inactive, pretend we were passed NULL instead.
parms->remap = nullptr;
}
// intersect with the canvas's clipping rectangle.
if (clipwidth >= 0 && clipheight >= 0)
{

View file

@ -59,14 +59,14 @@ int ListGetInt(VMVa_List &tags);
// Create a texture from a text in a given font.
//
//==========================================================================
#if 0
FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
{
int w;
const uint8_t *ch;
int cx;
int cy;
FRemapTable *range;
int trans = -1;
int kerning;
FTexture *pic;
@ -122,7 +122,7 @@ FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
EColorRange newcolor = V_ParseFontColor(ch, textcolor, textcolor);
if (newcolor != CR_UNDEFINED)
{
range = font->GetColorTranslation(newcolor);
trans = font->GetColorTranslation(newcolor);
textcolor = newcolor;
}
continue;
@ -158,7 +158,7 @@ FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor)
TexMan.AddTexture(tex);
return tex;
}
#endif
//==========================================================================
@ -193,7 +193,7 @@ void DFrameBuffer::DrawChar (FFont *font, int normalcolor, double x, double y, i
return;
}
PalEntry color = 0xffffffff;
parms.remap = redirected? nullptr : font->GetColorTranslation((EColorRange)normalcolor, &color);
parms.TranslationId = redirected? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color);
parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
DrawTextureParms(pic, parms);
}
@ -218,7 +218,7 @@ void DFrameBuffer::DrawChar(FFont *font, int normalcolor, double x, double y, in
bool res = ParseDrawTextureTags(pic, x, y, tag, args, &parms, false);
if (!res) return;
PalEntry color = 0xffffffff;
parms.remap = redirected ? nullptr : font->GetColorTranslation((EColorRange)normalcolor, &color);
parms.TranslationId = redirected ? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color);
parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
DrawTextureParms(pic, parms);
}
@ -261,7 +261,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
double cx;
double cy;
int boldcolor;
FRemapTable *range;
int trans = -1;
int kerning;
FTexture *pic;
@ -274,7 +274,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
PalEntry colorparm = parms.color;
PalEntry color = 0xffffffff;
range = font->GetColorTranslation((EColorRange)normalcolor, &color);
trans = font->GetColorTranslation((EColorRange)normalcolor, &color);
parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255);
kerning = font->GetDefaultKerning();
@ -301,7 +301,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
EColorRange newcolor = V_ParseFontColor(ch, normalcolor, boldcolor);
if (newcolor != CR_UNDEFINED)
{
range = font->GetColorTranslation(newcolor, &color);
trans = font->GetColorTranslation(newcolor, &color);
parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255);
currentcolor = newcolor;
}
@ -318,7 +318,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
bool redirected = false;
if (NULL != (pic = font->GetChar(c, currentcolor, &w, &redirected)))
{
parms.remap = redirected? nullptr : range;
parms.TranslationId = redirected? -1 : trans;
SetTextureParms(&parms, pic, cx, cy);
if (parms.cellx)
{

View file

@ -317,15 +317,8 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i
{
int usebright = false;
if (translation <= 0)
{
translation = -translation;
}
else
{
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
}
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
bool needmipmap = (clampmode <= CLAMP_XY);

View file

@ -124,15 +124,8 @@ public:
static int TranslationToIndex(int translation)
{
if (translation <= 0)
{
return -translation;
}
else
{
auto remap = TranslationToTable(translation);
return remap == nullptr ? 0 : remap->GetUniqueIndex();
}
auto remap = TranslationToTable(translation);
return remap == nullptr ? 0 : remap->GetUniqueIndex();
}
template<class T>

View file

@ -167,8 +167,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
auto mat = FMaterial::ValidateTexture(cmd.mTexture, false);
if (mat == nullptr) continue;
if (gltrans == -1 && cmd.mTranslation != nullptr) gltrans = cmd.mTranslation->GetUniqueIndex();
state.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, -gltrans, -1);
state.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, cmd.mTranslationId, -1);
state.EnableTexture(true);
// Canvas textures are stored upside down

View file

@ -167,15 +167,8 @@ void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
if (!tex->isHardwareCanvas())
{
if (translation <= 0)
{
translation = -translation;
}
else
{
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
}
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
mCanvas->Resize(texbuffer.mWidth, texbuffer.mHeight, false);

View file

@ -218,14 +218,6 @@ namespace swrenderer
}
}
// Clip sprite to drawseg
x1 = MAX<int>(clipper->x1, x1);
x2 = MIN<int>(clipper->x2, x2);
if (x1 >= x2)
{
return;
}
// Prepare lighting
ProjectedWallLight light;
light.SetColormap(lightsector, curline);
@ -250,7 +242,7 @@ namespace swrenderer
if (visible)
{
thread->PrepareTexture(WallSpriteTile, decal->RenderStyle);
drawerargs.DrawMasked(thread, zpos + WallSpriteTile->GetTopOffset(0) * decal->ScaleY, decal->ScaleY, decal->RenderFlags & RF_XFLIP, decal->RenderFlags & RF_YFLIP, WallC, light, WallSpriteTile, mfloorclip, mceilingclip, decal->RenderStyle);
drawerargs.DrawMasked(thread, zpos + WallSpriteTile->GetTopOffset(0) * decal->ScaleY, decal->ScaleY, decal->RenderFlags & RF_XFLIP, decal->RenderFlags & RF_YFLIP, WallC, clipper->x1, clipper->x2, light, WallSpriteTile, mfloorclip, mceilingclip, decal->RenderStyle);
}
// If this sprite is RF_CLIPFULL on a two-sided line, needrepeat will

View file

@ -277,7 +277,7 @@ namespace swrenderer
mlight.SetSpriteLight();
drawerargs.SetBaseColormap(Light.BaseColormap);
drawerargs.DrawMasked(thread, gzt - floorclip, SpriteScale, renderflags & RF_XFLIP, renderflags & RF_YFLIP, wallc, mlight, pic, portalfloorclip, mceilingclip, RenderStyle);
drawerargs.DrawMasked(thread, gzt - floorclip, SpriteScale, renderflags & RF_XFLIP, renderflags & RF_YFLIP, wallc, x1, x2, mlight, pic, portalfloorclip, mceilingclip, RenderStyle);
}
}
}

View file

@ -199,6 +199,6 @@ namespace swrenderer
}
drawerargs.SetBaseColormap(spr->Light.BaseColormap);
drawerargs.DrawMasked(thread, spr->gzt, spr->yscale, spr->renderflags & RF_XFLIP, spr->renderflags & RF_YFLIP, spr->wallc, mlight, WallSpriteTile, floorclip, mceilingclip, spr->RenderStyle);
drawerargs.DrawMasked(thread, spr->gzt, spr->yscale, spr->renderflags & RF_XFLIP, spr->renderflags & RF_YFLIP, spr->wallc, x1, x2, mlight, WallSpriteTile, floorclip, mceilingclip, spr->RenderStyle);
}
}

View file

@ -43,7 +43,7 @@ namespace swrenderer
colfunc = &SWPixelFormatDrawers::DrawColumn;
}
void SpriteDrawerArgs::DrawMasked(RenderThread* thread, double topZ, double scale, bool flipX, bool flipY, const FWallCoords& WallC, const ProjectedWallLight& light, FSoftwareTexture* tex, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
void SpriteDrawerArgs::DrawMasked(RenderThread* thread, double topZ, double scale, bool flipX, bool flipY, const FWallCoords& WallC, int clipx1, int clipx2, const ProjectedWallLight& light, FSoftwareTexture* tex, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
{
auto viewport = thread->Viewport.get();
auto cameraLight = CameraLight::Instance();
@ -73,8 +73,10 @@ namespace swrenderer
wpos += wstepX * 0.5f;
upos += ustepX * 0.5f;
int x1 = WallC.sx1;
int x2 = WallC.sx2;
int x1 = MAX<int>(WallC.sx1, clipx1);
int x2 = MIN<int>(WallC.sx2, clipx2);
if (x1 >= x2)
return;
float centerY = thread->Viewport->CenterY;
topZ -= thread->Viewport->viewpoint.Pos.Z;
@ -88,6 +90,14 @@ namespace swrenderer
float lightpos = light.GetLightPos(x1);
float lightstep = light.GetLightStep();
if (x1 > WallC.sx1)
{
int dx = x1 - WallC.sx1;
upos += ustepX * dx;
wpos += wstepX * dx;
lightpos += lightstep * dx;
}
dc_viewport = viewport;
dc_textureheight = texheight;

View file

@ -33,7 +33,7 @@ namespace swrenderer
void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; }
void SetDynamicLight(uint32_t color) { dynlightcolor = color; }
void DrawMasked(RenderThread* thread, double topZ, double scale, bool flipX, bool flipY, const FWallCoords& WallC, const ProjectedWallLight& light, FSoftwareTexture* texture, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
void DrawMasked(RenderThread* thread, double topZ, double scale, bool flipX, bool flipY, const FWallCoords& WallC, int clipx1, int clipx2, const ProjectedWallLight& light, FSoftwareTexture* texture, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
void DrawMasked2D(RenderThread *thread, double x0, double x1, double y0, double y1, FSoftwareTexture* texture, FRenderStyle style);
void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount);

View file

@ -702,51 +702,6 @@ DEFINE_ACTION_FUNCTION(_Screen, GetAspectRatio)
ACTION_RETURN_FLOAT(ActiveRatio(screen->GetWidth(), screen->GetHeight(), nullptr));
}
// Tries to guess the physical dimensions of the screen based on the
// screen's pixel dimensions. Can return:
// 0: 4:3
// 1: 16:9
// 2: 16:10
// 3: 17:10
// 4: 5:4
// 5: 17:10 (redundant, never returned)
// 6: 21:9
int CheckRatio (int width, int height, int *trueratio)
{
float aspect = width / (float)height;
static std::pair<float, int> ratioTypes[] =
{
{ 21 / 9.0f , 6 },
{ 16 / 9.0f , 1 },
{ 17 / 10.0f , 3 },
{ 16 / 10.0f , 2 },
{ 4 / 3.0f , 0 },
{ 5 / 4.0f , 4 },
{ 0.0f, 0 }
};
int ratio = ratioTypes[0].second;
float distance = fabs(ratioTypes[0].first - aspect);
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
{
float d = fabs(ratioTypes[i].first - aspect);
if (d < distance)
{
ratio = ratioTypes[i].second;
distance = d;
}
}
int fakeratio = ActiveFakeRatio(width, height);
if (fakeratio == -1)
fakeratio = ratio;
if (trueratio)
*trueratio = ratio;
return fakeratio;
}
int AspectBaseWidth(float aspect)
{
return (int)round(240.0f * aspect * 3.0f);
@ -781,32 +736,6 @@ bool AspectTallerThanWide(float aspect)
return aspect < 1.333f;
}
void ScaleWithAspect (int &w, int &h, int Width, int Height)
{
int resRatio = CheckRatio (Width, Height);
int screenRatio;
CheckRatio (w, h, &screenRatio);
if (resRatio == screenRatio)
return;
double yratio;
switch(resRatio)
{
case 0: yratio = 4./3.; break;
case 1: yratio = 16./9.; break;
case 2: yratio = 16./10.; break;
case 3: yratio = 17./10.; break;
case 4: yratio = 5./4.; break;
case 6: yratio = 21./9.; break;
default: return;
}
double y = w/yratio;
if (y > h)
w = static_cast<int>(h * yratio);
else
h = static_cast<int>(y);
}
CCMD(vid_setsize)
{
if (argv.argc() < 3)

View file

@ -240,6 +240,8 @@ enum
DTA_Burn, // activates the burn shader for this element
DTA_Spacing, // Strings only: Additional spacing between characters
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
DTA_FullscreenEx,
};
enum EMonospacing : int
@ -282,7 +284,7 @@ struct DrawParms
double left;
float Alpha;
PalEntry fillcolor;
FRemapTable *remap;
int TranslationId;
PalEntry colorOverlay;
PalEntry color;
INTBOOL alphaChannel;
@ -303,9 +305,10 @@ struct DrawParms
int maxstrlen;
bool fortext;
bool virtBottom;
bool burn;
uint8_t fsscalemode;
double srcx, srcy;
double srcwidth, srcheight;
bool burn;
};
struct Va_List
@ -621,8 +624,6 @@ FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr)
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
int V_GetColor(const uint32_t *palette, FScanner &sc);
int CheckRatio (int width, int height, int *trueratio=NULL);
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }
float ActiveRatio (int width, int height, float *trueratio = NULL);
@ -633,7 +634,6 @@ int AspectBaseHeight(float aspect);
double AspectPspriteOffset(float aspect);
int AspectMultiplier(float aspect);
bool AspectTallerThanWide(float aspect);
void ScaleWithAspect(int &w, int &h, int Width, int Height);
int GetUIScale(int altval);
int GetConScale(int altval);

View file

@ -207,15 +207,8 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
{
if (!tex->isHardwareCanvas())
{
if (translation <= 0)
{
translation = -translation;
}
else
{
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
}
auto remap = TranslationToTable(translation);
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer);

View file

@ -47,6 +47,7 @@
#include "gstrings.h"
#include "g_levellocals.h"
#include "p_checkposition.h"
#include "p_linetracedata.h"
#include "v_font.h"
#include "menu/menu.h"
#include "teaminfo.h"
@ -844,21 +845,6 @@ void InitThingdef()
wbplayerstruct->Size = sizeof(wbplayerstruct_t);
wbplayerstruct->Align = alignof(wbplayerstruct_t);
auto dictionarystruct = NewStruct("Dictionary", nullptr, true);
dictionarystruct->Size = sizeof(Dictionary);
dictionarystruct->Align = alignof(Dictionary);
NewPointer(dictionarystruct, false)->InstallHandlers(
[](FSerializer &ar, const char *key, const void *addr)
{
ar(key, *(Dictionary **)addr);
},
[](FSerializer &ar, const char *key, void *addr)
{
Serialize<Dictionary>(ar, key, *(Dictionary **)addr, nullptr);
return true;
}
);
FAutoSegIterator probe(CRegHead, CRegTail);
while (*++probe != NULL)
@ -919,6 +905,9 @@ void InitThingdef()
frp->Size = sizeof(FRailParams);
frp->Align = alignof(FRailParams);
auto fltd = NewStruct("FLineTraceData", nullptr);
fltd->Size = sizeof(FLineTraceData);
fltd->Align = alignof(FLineTraceData);
FieldTable.Clear();
if (FieldTable.Size() == 0)

View file

@ -192,7 +192,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound)
PARAM_FLOAT(volume);
PARAM_FLOAT(attenuation);
PARAM_FLOAT(pitch);
A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch);
PARAM_FLOAT(startTime);
A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime);
return 0;
}
@ -1960,6 +1961,7 @@ DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitSector);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Hit3DFloor);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitTexture);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitLocation);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, HitDir);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, Distance);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, NumPortals);
DEFINE_FIELD_X(FLineTraceData, FLineTraceData, LineSide);

View file

@ -1559,9 +1559,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
Error(field, "Cannot declare non-native global variables. Tried to declare %s", FName(name->Name).GetChars());
}
assert(f != nullptr);
if (field->Flags & (ZCC_Version | ZCC_Deprecated))
if ((field->Flags & (ZCC_Version | ZCC_Deprecated)) && f != nullptr)
{
f->mVersion = field->Version;
@ -3407,7 +3405,6 @@ void ZCCCompiler::CompileStates()
if (!statedef.SetWait())
{
Error(st, "%s before first state", st->NodeType == AST_StateFail ? "Fail" : "Wait");
continue;
}
break;
@ -3415,7 +3412,6 @@ void ZCCCompiler::CompileStates()
if (!statedef.SetLoop())
{
Error(st, "LOOP before first state");
continue;
}
break;

View file

@ -2165,7 +2165,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&fon
FString DictionaryToString(const Dictionary &dict)
{
Dictionary::ConstPair *pair;
Dictionary::ConstIterator i { dict };
Dictionary::ConstIterator i { dict.Map };
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
@ -2190,7 +2190,7 @@ Dictionary *DictionaryFromString(const FString &string)
return nullptr;
}
Dictionary *const dict = new Dictionary;
Dictionary *const dict = Create<Dictionary>();
if (string.IsEmpty())
{
@ -2214,7 +2214,7 @@ Dictionary *DictionaryFromString(const FString &string)
return dict;
}
dict->Insert(i->name.GetString(), i->value.GetString());
dict->Map.Insert(i->name.GetString(), i->value.GetString());
}
return dict;

View file

@ -171,17 +171,17 @@ public:
}
// Starts a sound.
FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan)
FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime)
{
return NULL;
}
FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan)
FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime)
{
return NULL;
}
// Marks a channel's start time without actually playing it.
void MarkStartTime (FISoundChannel *chan)
void MarkStartTime (FISoundChannel *chan, float startTime)
{
}

View file

@ -109,8 +109,8 @@ public:
virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0;
// Starts a sound.
virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0;
virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) = 0;
virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0;
virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0;
// Stops a sound channel.
virtual void StopChannel (FISoundChannel *chan) = 0;
@ -122,7 +122,7 @@ public:
virtual void ChannelPitch(FISoundChannel *chan, float volume) = 0;
// Marks a channel's start time without actually playing it.
virtual void MarkStartTime (FISoundChannel *chan) = 0;
virtual void MarkStartTime (FISoundChannel *chan, float startTime = 0.f) = 0;
// Returns position of sound on this channel, in samples.
virtual unsigned int GetPosition(FISoundChannel *chan) = 0;

View file

@ -1167,7 +1167,7 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int
return stream;
}
FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan)
FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime)
{
if(FreeSfx.Size() == 0)
{
@ -1218,7 +1218,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan || reuse_chan->StartTime == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f);
{
float st = (chanflags&SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp<float>(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f);
alSourcef(source, AL_SEC_OFFSET, st);
}
else
{
if((chanflags&SNDF_ABSTIME))
@ -1267,7 +1270,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol,
FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel,
int channum, int chanflags, FISoundChannel *reuse_chan)
int channum, int chanflags, FISoundChannel *reuse_chan, float startTime)
{
float dist_sqr = (float)(pos - listener->position).LengthSquared();
@ -1411,7 +1414,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan || reuse_chan->StartTime == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f);
{
float st = (chanflags & SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp<float>(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f);
alSourcef(source, AL_SEC_OFFSET, st);
}
else
{
if((chanflags&SNDF_ABSTIME))
@ -1791,11 +1797,14 @@ bool OpenALSoundRenderer::IsValid()
return Device != NULL;
}
void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan)
void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan, float startTime)
{
// FIXME: Get current time (preferably from the audio clock, but the system
// time will have to do)
chan->StartTime = std::chrono::steady_clock::now().time_since_epoch().count();
using namespace std::chrono;
auto startTimeDuration = duration<double>(startTime);
auto diff = steady_clock::now().time_since_epoch() - startTimeDuration;
chan->StartTime = static_cast<uint64_t>(duration_cast<nanoseconds>(diff).count());
}
float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan)

View file

@ -136,8 +136,8 @@ public:
virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata);
// Starts a sound.
virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan);
virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan);
virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime);
virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime);
// Changes a channel's volume.
virtual void ChannelVolume(FISoundChannel *chan, float volume);
@ -166,7 +166,7 @@ public:
virtual void UpdateListener(SoundListener *);
virtual void UpdateSounds();
virtual void MarkStartTime(FISoundChannel*);
virtual void MarkStartTime(FISoundChannel*, float startTime);
virtual float GetAudibility(FISoundChannel*);

View file

@ -174,7 +174,7 @@ static void SetupGenMidi()
auto lump = Wads.CheckNumForName("GENMIDI", ns_global);
if (lump < 0)
{
Printf("No GENMIDI lump found. OPL playback not available.");
Printf("No GENMIDI lump found. OPL playback not available.\n");
return;
}
auto data = Wads.OpenLumpReader(lump);

View file

@ -278,7 +278,7 @@ void S_InitData()
//
//==========================================================================
void S_SoundPitch(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch)
void S_SoundPitch(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch, float startTime)
{
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch);
}
@ -296,7 +296,8 @@ DEFINE_ACTION_FUNCTION(DObject, S_Sound)
PARAM_FLOAT(volume);
PARAM_FLOAT(attn);
PARAM_FLOAT(pitch);
S_SoundPitch(channel & 7, EChanFlags::FromInt(channel & ~7), id, static_cast<float>(volume), static_cast<float>(attn), static_cast<float>(pitch));
PARAM_FLOAT(startTime);
S_SoundPitch(channel & 7, EChanFlags::FromInt(channel & ~7), id, static_cast<float>(volume), static_cast<float>(attn), static_cast<float>(pitch), static_cast<float>(startTime));
return 0;
}
@ -309,7 +310,8 @@ DEFINE_ACTION_FUNCTION(DObject, S_StartSound)
PARAM_FLOAT(volume);
PARAM_FLOAT(attn);
PARAM_FLOAT(pitch);
S_SoundPitch(channel, EChanFlags::FromInt(flags), id, static_cast<float>(volume), static_cast<float>(attn), static_cast<float>(pitch));
PARAM_FLOAT(startTime);
S_SoundPitch(channel, EChanFlags::FromInt(flags), id, static_cast<float>(volume), static_cast<float>(attn), static_cast<float>(pitch), static_cast<float>(startTime));
return 0;
}
@ -365,10 +367,10 @@ static bool VerifyActorSound(AActor* ent, FSoundID& sound_id, int& channel, ECha
//
//==========================================================================
void S_SoundPitchActor(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch)
void S_SoundPitchActor(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch, float startTime)
{
if (VerifyActorSound(ent, sound_id, channel, flags))
soundEngine->StartSound (SOURCE_Actor, ent, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch);
soundEngine->StartSound (SOURCE_Actor, ent, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch, startTime);
}
void S_Sound(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation)
@ -443,7 +445,7 @@ void S_Sound (const sector_t *sec, int channel, EChanFlags flags, FSoundID sfxid
//
//==========================================================================
void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten, float pitch)
void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten, float pitch, float startTime = 0.f)
{
if (a == nullptr || a->Sector->Flags & SECF_SILENT || a->Level != primaryLevel)
return;
@ -452,7 +454,7 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float
{
if (!(flags & CHANF_NOSTOP) || !S_IsActorPlayingSomething(a, chan, sid))
{
S_SoundPitchActor(a, chan, flags, sid, vol, atten, pitch);
S_SoundPitchActor(a, chan, flags, sid, vol, atten, pitch, startTime);
}
}
else
@ -461,7 +463,7 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float
{
if (!(flags & CHANF_NOSTOP) || !soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, chan, sid))
{
S_SoundPitch(chan, flags, sid, vol, ATTN_NONE, pitch);
S_SoundPitch(chan, flags, sid, vol, ATTN_NONE, pitch, startTime);
}
}
}
@ -469,19 +471,19 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float
void S_PlaySound(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten)
{
S_PlaySoundPitch(a, chan, flags, sid, vol, atten, 0.f);
S_PlaySoundPitch(a, chan, flags, sid, vol, atten, 0.f, 0.f);
}
void A_StartSound(AActor *self, int soundid, int channel, int flags, double volume, double attenuation, double pitch)
void A_StartSound(AActor *self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime)
{
S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, (float)pitch);
S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, (float)pitch, (float)startTime);
}
void A_PlaySound(AActor* self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch)
{
if (looping) channel |= CHANF_LOOP | CHANF_NOSTOP;
if (local) channel |= CHANF_LOCAL;
A_StartSound(self, soundid, channel & 7, channel & ~7, volume, attenuation, pitch);
A_StartSound(self, soundid, channel & 7, channel & ~7, volume, attenuation, pitch, 0.0f);
}

View file

@ -17,7 +17,7 @@ void S_PrecacheLevel(FLevelLocals* l);
// Start sound for thing at <ent>
void S_Sound(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation);
void S_SoundPitch(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch);
void S_SoundPitch(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch, float startTime = 0.f);
void S_Sound (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation);
@ -26,7 +26,7 @@ void S_Sound (const FPolyObj *poly, int channel, EChanFlags flags, FSoundID sfxi
void S_Sound (const sector_t *sec, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation);
void S_Sound(FLevelLocals *Level, const DVector3 &pos, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation);
void S_SoundPitchActor (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch);
void S_SoundPitchActor (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch, float startTime = 0.f);
// [Nash] Used by ACS and DECORATE
void S_PlaySound(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten);
@ -57,7 +57,7 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch);
void S_SerializeSounds(FSerializer &arc);
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch);
void A_StartSound(AActor* self, int soundid, int channel, int flags, double volume, double attenuation, double pitch);
void A_StartSound(AActor* self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime = 0.);
static void S_SetListener(AActor *listenactor);
void S_SoundReset();
void S_ResumeSound(bool state);

View file

@ -36,6 +36,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "templates.h"
#include "s_soundinternal.h"
#include "m_swap.h"
#include "superfasthash.h"
@ -368,7 +369,7 @@ FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &a
FSoundChan *SoundEngine::StartSound(int type, const void *source,
const FVector3 *pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation,
FRolloffInfo *forcedrolloff, float spitch)
FRolloffInfo *forcedrolloff, float spitch, float startTime)
{
sfxinfo_t *sfx;
EChanFlags chanflags = flags;
@ -566,13 +567,17 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
if (chanflags & (CHANF_UI|CHANF_NOPAUSE)) startflags |= SNDF_NOPAUSE;
if (chanflags & CHANF_UI) startflags |= SNDF_NOREVERB;
startTime = (startflags & SNDF_LOOP)
? fmod(startTime, (float)GSnd->GetMSLength(sfx->data) / 1000.f)
: clamp<float>(startTime, 0.f, (float)GSnd->GetMSLength(sfx->data) / 1000.f);
if (attenuation > 0 && type != SOURCE_None)
{
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL);
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL, startTime);
}
else
{
chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL);
chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL, startTime);
}
}
if (chan == NULL && (chanflags & CHANF_LOOP))

View file

@ -301,7 +301,7 @@ public:
void UpdateSounds(int time);
FSoundChan* StartSound(int sourcetype, const void* source,
const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f);
const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f, float startTime = 0.0f);
// Stops an origin-less sound from playing from this channel.
void StopSoundID(int sound_id);

View file

@ -3,20 +3,87 @@
#include "scripting/vm/vm.h"
#include "serializer.h"
#include <cassert>
//=====================================================================================
//
// DObject implementations for Dictionary and DictionaryIterator
//
//=====================================================================================
IMPLEMENT_CLASS(Dictionary, false, false);
IMPLEMENT_CLASS(DictionaryIterator, false, true);
IMPLEMENT_POINTERS_START(DictionaryIterator)
IMPLEMENT_POINTER(Dict)
IMPLEMENT_POINTERS_END
//=====================================================================================
//
// Dictionary functions
//
//=====================================================================================
void Dictionary::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
constexpr char key[] { "dictionary" };
if (arc.isWriting())
{
// Pass this instance to serializer.
Dictionary *pointerToThis = this;
arc(key, pointerToThis);
}
else
{
// Receive new Dictionary, copy contents, clean up.
Dictionary *pointerToDeserializedDictionary;
arc(key, pointerToDeserializedDictionary);
Map.TransferFrom(pointerToDeserializedDictionary->Map);
delete pointerToDeserializedDictionary;
}
}
static Dictionary *DictCreate()
{
Dictionary *dict { Create<Dictionary>() };
return dict;
}
static void DictInsert(Dictionary *dict, const FString &key, const FString &value)
{
dict->Map.Insert(key, value);
}
static void DictAt(const Dictionary *dict, const FString &key, FString *result)
{
const FString *value = dict->Map.CheckKey(key);
*result = value ? *value : "";
}
static void DictToString(const Dictionary *dict, FString *result)
{
*result = DictionaryToString(*dict);
}
static void DictRemove(Dictionary *dict, const FString &key)
{
dict->Map.Remove(key);
}
//=====================================================================================
//
// Dictionary exports
//
//=====================================================================================
DEFINE_ACTION_FUNCTION(_Dictionary, Create)
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Create, DictCreate)
{
ACTION_RETURN_POINTER(new Dictionary);
}
static void DictInsert(Dictionary *dict, const FString &key, const FString &value)
{
dict->Insert(key, value);
ACTION_RETURN_POINTER(DictCreate());
}
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Insert, DictInsert)
@ -28,12 +95,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Insert, DictInsert)
return 0;
}
static void DictAt(const Dictionary *dict, const FString &key, FString *result)
{
const FString *value = dict->CheckKey(key);
*result = value ? *value : "";
}
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, At, DictAt)
{
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
@ -43,11 +104,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, At, DictAt)
ACTION_RETURN_STRING(result);
}
static void DictToString(const Dictionary *dict, FString *result)
{
*result = DictionaryToString(*dict);
}
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, ToString, DictToString)
{
PARAM_SELF_STRUCT_PROLOGUE(Dictionary);
@ -56,21 +112,11 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, ToString, DictToString)
ACTION_RETURN_STRING(result);
}
static Dictionary *DictFromString(const FString& string)
{
return DictionaryFromString(string);
}
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, FromString, DictFromString)
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, FromString, DictionaryFromString)
{
PARAM_PROLOGUE;
PARAM_STRING(string);
ACTION_RETURN_POINTER(DictFromString(string));
}
static void DictRemove(Dictionary *dict, const FString &key)
{
dict->Remove(key);
ACTION_RETURN_POINTER(DictionaryFromString(string));
}
DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Remove, DictRemove)
@ -83,21 +129,65 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Remove, DictRemove)
//=====================================================================================
//
// DictionaryIterator exports
// DictionaryIterator functions
//
//=====================================================================================
DictionaryIterator::DictionaryIterator(const Dictionary &dict)
: Iterator(dict)
DictionaryIterator::DictionaryIterator()
: Iterator(nullptr)
, Pair(nullptr)
, Dict(nullptr)
{
}
static DictionaryIterator *DictIteratorCreate(const Dictionary *dict)
void DictionaryIterator::Serialize(FSerializer &arc)
{
return new DictionaryIterator(*dict);
if (arc.isWriting())
{
I_Error("Attempt to save pointer to unhandled type DictionaryIterator");
}
}
void DictionaryIterator::init(Dictionary *dict)
{
Iterator = std::make_unique<Dictionary::ConstIterator>(dict->Map);
Dict = dict;
GC::WriteBarrier(this, Dict);
}
static DictionaryIterator *DictIteratorCreate(Dictionary *dict)
{
DictionaryIterator *iterator = Create<DictionaryIterator>();
iterator->init(dict);
return iterator;
}
static int DictIteratorNext(DictionaryIterator *self)
{
assert(self->Iterator != nullptr);
const bool hasNext { self->Iterator->NextPair(self->Pair) };
return hasNext;
}
static void DictIteratorKey(const DictionaryIterator *self, FString *result)
{
*result = self->Pair ? self->Pair->Key : FString {};
}
static void DictIteratorValue(const DictionaryIterator *self, FString *result)
{
*result = self->Pair ? self->Pair->Value : FString {};
}
//=====================================================================================
//
// DictionaryIterator exports
//
//=====================================================================================
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Create, DictIteratorCreate)
{
PARAM_PROLOGUE;
@ -105,22 +195,12 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Create, DictIteratorCreate)
ACTION_RETURN_POINTER(DictIteratorCreate(dict));
}
static int DictIteratorNext(DictionaryIterator *self)
{
return self->Iterator.NextPair(self->Pair);
}
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Next, DictIteratorNext)
{
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);
ACTION_RETURN_BOOL(DictIteratorNext(self));
}
static void DictIteratorKey(const DictionaryIterator *self, FString *result)
{
*result = self->Pair ? self->Pair->Key : FString {};
}
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Key, DictIteratorKey)
{
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);
@ -129,11 +209,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Key, DictIteratorKey)
ACTION_RETURN_STRING(result);
}
static void DictIteratorValue(const DictionaryIterator *self, FString *result)
{
*result = self->Pair ? self->Pair->Value : FString {};
}
DEFINE_ACTION_FUNCTION_NATIVE(_DictionaryIterator, Value, DictIteratorValue)
{
PARAM_SELF_STRUCT_PROLOGUE(DictionaryIterator);

View file

@ -2,13 +2,69 @@
#include "tarray.h"
#include "zstring.h"
#include "dobject.h"
using Dictionary = TMap<FString, FString>;
#include <memory>
struct DictionaryIterator
/**
* @brief The Dictionary class exists to be exported to ZScript.
*
* It is a string-to-string map.
*
* It is derived from DObject to be a part of normal GC process.
*/
class Dictionary final : public DObject
{
explicit DictionaryIterator(const Dictionary &dict);
DECLARE_CLASS(Dictionary, DObject)
Dictionary::ConstIterator Iterator;
Dictionary::ConstPair *Pair;
public:
using StringMap = TMap<FString, FString>;
using ConstIterator = StringMap::ConstIterator;
using ConstPair = StringMap::ConstPair;
void Serialize(FSerializer &arc) override;
StringMap Map;
};
/**
* @brief The DictionaryIterator class exists to be exported to ZScript.
*
* It provides iterating over a Dictionary. The order is not specified.
*
* It is derived from DObject to be a part of normal GC process.
*/
class DictionaryIterator final : public DObject
{
DECLARE_CLASS(DictionaryIterator, DObject)
HAS_OBJECT_POINTERS
public:
~DictionaryIterator() override = default;
/**
* IMPLEMENT_CLASS macro needs a constructor without parameters.
*
* @see init().
*/
DictionaryIterator();
void Serialize(FSerializer &arc) override;
/**
* @brief init function complements constructor.
* @attention always call init after constructing DictionaryIterator.
*/
void init(Dictionary *dict);
std::unique_ptr<Dictionary::ConstIterator> Iterator;
Dictionary::ConstPair *Pair;
/**
* @brief Dictionary attribute exists for holding a pointer to iterated
* dictionary, so it is known by GC.
*/
Dictionary *Dict;
};

View file

@ -84,11 +84,11 @@ const char *GetVersionString();
#define SAVEGAME_EXT "zds"
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 4556
#define MINSAVEVER 4556
// Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got.
#define SAVEVER 4557
#define SAVEVER 4558
// This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "QZDOOM"

View file

@ -599,7 +599,6 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
// placing the animations precisely where they belong on the base pic
animwidth = background->GetDisplayWidthDouble();
animheight = background->GetDisplayHeightDouble();
screen->FillBorder(NULL);
screen->DrawTexture(background, 0, 0, DTA_Fullscreen, true, TAG_DONE);
}
else
@ -724,6 +723,7 @@ void WI_Drawer()
ScaleOverrider s;
IFVIRTUALPTRNAME(WI_Screen, "StatusScreen", Drawer)
{
screen->FillBorder(nullptr);
VMValue self = WI_Screen;
VMCall(func, &self, 1, nullptr, 0);
screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind.

View file

@ -1031,7 +1031,7 @@ void ST_Util_BitmapColorsFromPlaypal(BitmapInfo* bitmap_info)
{
uint8_t playpal[768];
ReadPalette(Wads.CheckNumForName("PLAYPAL"), playpal);
ReadPalette(Wads.GetNumForName("PLAYPAL"), playpal);
for (int i = 0; i < 256; ++i)
{
bitmap_info->bmiColors[i].rgbBlue = playpal[i * 3 + 2];

View file

@ -46,19 +46,19 @@ struct FLineTraceData
TRACE_HasHitSky
};
Actor HitActor;
Line HitLine;
Sector HitSector;
F3DFloor Hit3DFloor;
TextureID HitTexture;
Vector3 HitLocation;
Vector3 HitDir;
double Distance;
int NumPortals;
int LineSide;
int LinePart;
int SectorPlane;
int HitType;
native Actor HitActor;
native Line HitLine;
native Sector HitSector;
native F3DFloor Hit3DFloor;
native TextureID HitTexture;
native Vector3 HitLocation;
native Vector3 HitDir;
native double Distance;
native int NumPortals;
native int LineSide;
native int LinePart;
native int SectorPlane;
native int HitType;
}
struct LinkContext
@ -341,17 +341,17 @@ class Actor : Thinker native
//int ConversationRoot; // THe root of the current dialogue
// deprecated things.
native readonly deprecated("2.3") double X;
native readonly deprecated("2.3") double Y;
native readonly deprecated("2.3") double Z;
native readonly deprecated("2.3") double VelX;
native readonly deprecated("2.3") double VelY;
native readonly deprecated("2.3") double VelZ;
native readonly deprecated("2.3") double MomX;
native readonly deprecated("2.3") double MomY;
native readonly deprecated("2.3") double MomZ;
native deprecated("2.3") double ScaleX;
native deprecated("2.3") double ScaleY;
native readonly deprecated("2.3", "Use Pos.X instead") double X;
native readonly deprecated("2.3", "Use Pos.Y instead") double Y;
native readonly deprecated("2.3", "Use Pos.Z instead") double Z;
native readonly deprecated("2.3", "Use Vel.X instead") double VelX;
native readonly deprecated("2.3", "Use Vel.Y instead") double VelY;
native readonly deprecated("2.3", "Use Vel.Z instead") double VelZ;
native readonly deprecated("2.3", "Use Vel.X instead") double MomX;
native readonly deprecated("2.3", "Use Vel.Y instead") double MomY;
native readonly deprecated("2.3", "Use Vel.Z instead") double MomZ;
native deprecated("2.3", "Use Scale.X instead") double ScaleX;
native deprecated("2.3", "Use Scale.Y instead") double ScaleY;
//FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is used.;
@ -598,7 +598,7 @@ class Actor : Thinker native
native static int ApplyDamageFactors(class<Inventory> itemcls, Name damagetype, int damage, int defdamage);
native void RemoveFromHash();
native void ChangeTid(int newtid);
deprecated("3.8") static int FindUniqueTid(int start = 0, int limit = 0)
deprecated("3.8", "Use Level.FindUniqueTid() instead") static int FindUniqueTid(int start = 0, int limit = 0)
{
return level.FindUniqueTid(start, limit);
}
@ -908,7 +908,7 @@ class Actor : Thinker native
return true;
}
deprecated("2.3") void A_FaceConsolePlayer(double MaxTurnAngle = 0) {}
deprecated("2.3", "This function does nothing and is only for Zandronum compatibility") void A_FaceConsolePlayer(double MaxTurnAngle = 0) {}
void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0)
{
@ -1054,18 +1054,18 @@ class Actor : Thinker native
native void A_Wander(int flags = 0);
native void A_Look2();
deprecated("2.3") native void A_BulletAttack();
deprecated("2.3", "Use A_CustomBulletAttack() instead") native void A_BulletAttack();
native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
deprecated("4.3") native clearscope void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false, double pitch = 0.0);
native clearscope void A_StartSound(sound whattoplay, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0);
deprecated("4.3", "Use A_StartSound() instead") native clearscope void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false, double pitch = 0.0);
native clearscope void A_StartSound(sound whattoplay, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0, double startTime = 0.0);
native void A_SoundVolume(int slot, double volume);
native void A_SoundPitch(int slot, double pitch);
deprecated("2.3") void A_PlayWeaponSound(sound whattoplay) { A_StartSound(whattoplay, CHAN_WEAPON); }
deprecated("2.3", "Use A_StartSound(<sound>, CHAN_WEAPON) instead") void A_PlayWeaponSound(sound whattoplay) { A_StartSound(whattoplay, CHAN_WEAPON); }
native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
void A_StopAllSounds() { A_StopSounds(0,0); }
native void A_StopSounds(int chanmin, int chanmax);
deprecated("2.3") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
deprecated("2.3") native void A_StopSoundEx(name slot);
deprecated("2.3", "Use A_StartSound() instead") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
deprecated("2.3", "Use A_StopSound() instead") native void A_StopSoundEx(name slot);
native clearscope bool IsActorPlayingSound(int channel, Sound snd = 0);
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
native action state A_Jump(int chance, statelabel label, ...);
@ -1086,7 +1086,7 @@ class Actor : Thinker native
native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
native void A_DropInventory(class<Inventory> itemtype, int amount = -1);
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);
deprecated("2.3") native void A_ChangeFlag(string flagname, bool value);
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
native void A_RaiseMaster(int flags = 0);
native void A_RaiseChildren(int flags = 0);
@ -1125,10 +1125,10 @@ class Actor : Thinker native
native void A_SetViewAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetViewPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetViewRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
deprecated("2.3") native void A_SetUserVar(name varname, int value);
deprecated("2.3") native void A_SetUserArray(name varname, int index, int value);
deprecated("2.3") native void A_SetUserVarFloat(name varname, double value);
deprecated("2.3") native void A_SetUserArrayFloat(name varname, int index, double value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVar(name varname, int value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArray(name varname, int index, int value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVarFloat(name varname, double value);
deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArrayFloat(name varname, int index, double value);
native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake");
native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0);
action native void A_SetTics(int tics);

View file

@ -686,18 +686,18 @@ extend class Actor
}
}
deprecated("2.3") void A_MeleeAttack()
deprecated("2.3", "Use CustomMeleeAttack() instead") void A_MeleeAttack()
{
DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0);
}
deprecated("2.3") void A_MissileAttack()
deprecated("2.3", "Use A_SpawnProjectile() instead") void A_MissileAttack()
{
Class<Actor> MissileType = MissileName;
DoAttack(false, true, 0, 0, MissileType, MissileHeight);
}
deprecated("2.3") void A_ComboAttack()
deprecated("2.3", "Use A_BasicAttack() instead") void A_ComboAttack()
{
Class<Actor> MissileType = MissileName;
DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);

View file

@ -168,7 +168,7 @@ extend class Actor
private native bool CheckFlag(string flagname, int check_pointer = AAPTR_DEFAULT);
deprecated("2.3") action state A_CheckFlag(string flagname, statelabel label, int check_pointer = AAPTR_DEFAULT)
deprecated("2.3", "Use a combination of direct flag access and SetStateLabel()") action state A_CheckFlag(string flagname, statelabel label, int check_pointer = AAPTR_DEFAULT)
{
return CheckFlag(flagname, check_pointer)? ResolveState(label) : null;
}

View file

@ -70,9 +70,13 @@ extend class StateProvider
{
// Removed most of the mess that was here in the C++ code because SetSafeFlash already does some thorough validation.
State atk = weap.FindState('Fire');
State cur = player.GetPSprite(PSP_WEAPON).CurState;
int theflash = atk == cur? 0:1;
player.SetSafeFlash(weap, flash, theflash);
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
State cur = psp.CurState;
int theflash = atk == cur? 0:1;
player.SetSafeFlash(weap, flash, theflash);
}
}
}
player.mo.PlayAttacking2 ();

View file

@ -56,7 +56,11 @@ class Beak : Weapon
{
return;
}
player.GetPSprite(PSP_WEAPON).y = WEAPONTOP;
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
psp.y = WEAPONTOP;
}
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState());
}
@ -85,7 +89,11 @@ class Beak : Weapon
}
A_StartSound ("chicken/peck", CHAN_VOICE);
player.chickenPeck = 12;
player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,7);
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
psp.Tics -= random[BeakAtk](0,7);
}
}
}
@ -133,7 +141,11 @@ class BeakPowered : Beak
}
A_StartSound ("chicken/peck", CHAN_VOICE);
player.chickenPeck = 12;
player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,3);
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
psp.Tics -= random[BeakAtk](0,3);
}
}
}

View file

@ -67,8 +67,12 @@ class Gauntlets : Weapon
if (!weapon.DepleteAmmo (weapon.bAltFire))
return;
player.GetPSprite(PSP_WEAPON).x = ((random[GauntletAtk](0, 3)) - 2);
player.GetPSprite(PSP_WEAPON).y = WEAPONTOP + (random[GauntletAtk](0, 3));
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
psp.x = ((random[GauntletAtk](0, 3)) - 2);
psp.y = WEAPONTOP + (random[GauntletAtk](0, 3));
}
}
double ang = angle;
if (power)

View file

@ -74,8 +74,12 @@ class Mace : HereticWeapon
}
else
{
player.GetPSprite(PSP_WEAPON).x = random[MaceAtk](-2, 1);
player.GetPSprite(PSP_WEAPON).y = WEAPONTOP + random[MaceAtk](0, 3);
let psp = player.GetPSprite(PSP_WEAPON);
if (psp)
{
psp.x = random[MaceAtk](-2, 1);
psp.y = WEAPONTOP + random[MaceAtk](0, 3);
}
Actor ball = SpawnPlayerMissile("MaceFX1", angle + (random[MaceAtk](-4, 3) * (360. / 256)));
if (ball)
{

View file

@ -1323,9 +1323,11 @@ class PowerTargeter : Powerup
}
PSprite center = player.GetPSprite(PSprite.TARGETCENTER);
center.x = POS_X;
center.y = POS_Y;
if (center)
{
center.x = POS_X;
center.y = POS_Y;
}
PositionAccuracy ();
}
@ -1402,12 +1404,18 @@ class PowerTargeter : Powerup
if (player != null)
{
PSprite left = player.GetPSprite(PSprite.TARGETLEFT);
left.x = POS_X - (100 - player.mo.accuracy);
left.y = POS_Y;
if (left)
{
left.x = POS_X - (100 - player.mo.accuracy);
left.y = POS_Y;
}
PSprite right = player.GetPSprite(PSprite.TARGETRIGHT);
right.x = POS_X + (100 - player.mo.accuracy);
right.y = POS_Y;
if (right)
{
right.x = POS_X + (100 - player.mo.accuracy);
right.y = POS_Y;
}
}
}

View file

@ -443,11 +443,11 @@ class CustomInventory : StateProvider
//---------------------------------------------------------------------------
// This is only here, because these functions were originally exported on Inventory, despite only working for weapons, so this is here to satisfy some potential old mods having called it through CustomInventory.
deprecated("2.3") action void A_GunFlash(statelabel flash = null, int flags = 0) {}
deprecated("2.3") action void A_Lower() {}
deprecated("2.3") action void A_Raise() {}
deprecated("2.3") action void A_CheckReload() {}
deprecated("3.7") action void A_WeaponReady(int flags = 0) {} // this was somehow missed in 2.3 ...
deprecated("2.3", "must be called from Weapon") action void A_GunFlash(statelabel flash = null, int flags = 0) {}
deprecated("2.3", "must be called from Weapon") action void A_Lower() {}
deprecated("2.3", "must be called from Weapon") action void A_Raise() {}
deprecated("2.3", "must be called from Weapon") action void A_CheckReload() {}
deprecated("3.7", "must be called from Weapon") action void A_WeaponReady(int flags = 0) {} // this was somehow missed in 2.3 ...
native bool CallStateChain (Actor actor, State state);
//===========================================================================

View file

@ -227,6 +227,7 @@ class Weapon : StateProvider
return;
}
let psp = player.GetPSprite(PSP_WEAPON);
if (!psp) return;
if (player.morphTics || player.cheats & CF_INSTANTWEAPSWITCH)
{
psp.y = WEAPONBOTTOM;
@ -276,6 +277,7 @@ class Weapon : StateProvider
return;
}
let psp = player.GetPSprite(PSP_WEAPON);
if (!psp) return;
psp.y -= raisespeed;
if (psp.y > WEAPONTOP)
{ // Not raised all the way yet
@ -341,7 +343,8 @@ class Weapon : StateProvider
}
// Play ready sound, if any.
if (weapon.ReadySound && player.GetPSprite(PSP_WEAPON).curState == weapon.FindState('Ready'))
let psp = player.GetPSprite(PSP_WEAPON);
if (weapon.ReadySound && psp && psp.curState == weapon.FindState('Ready'))
{
if (!weapon.bReadySndHalf || random[WpnReadySnd]() < 128)
{
@ -361,8 +364,11 @@ class Weapon : StateProvider
// Prepare for bobbing action.
player.WeaponState |= WF_WEAPONBOBBING;
let pspr = player.GetPSprite(PSP_WEAPON);
pspr.x = 0;
pspr.y = WEAPONTOP;
if (pspr)
{
pspr.x = 0;
pspr.y = WEAPONTOP;
}
}
}
@ -865,9 +871,12 @@ class Weapon : StateProvider
p.refire = 0;
let pspr = p.GetPSprite(PSP_WEAPON);
pspr.y = WEAPONBOTTOM;
pspr.ResetInterpolation();
pspr.SetState(GetUpState());
if (pspr)
{
pspr.y = WEAPONBOTTOM;
pspr.ResetInterpolation();
pspr.SetState(GetUpState());
}
}
//===========================================================================

View file

@ -28,6 +28,11 @@ extend class Actor
return null, 0, 0;
}
// [MC] Called when an actor morphs, on both the previous form (!current) and present form (current).
virtual void PreMorph(Actor mo, bool current) {}
virtual void PostMorph(Actor mo, bool current) {}
virtual void PreUnmorph(Actor mo, bool current) {}
virtual void PostUnmorph(Actor mo, bool current) {}
//===========================================================================
//
@ -105,6 +110,11 @@ extend class Actor
}
let morphed = MorphedMonster(Spawn (spawntype, Pos, NO_REPLACE));
// [MC] Notify that we're just about to start the transfer.
PreMorph(morphed, false); // False: No longer the current.
morphed.PreMorph(self, true); // True: Becoming this actor.
Substitute (morphed);
if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate)
{
@ -140,6 +150,8 @@ extend class Actor
let eflash = Spawn(enter_flash ? enter_flash : (class<Actor>)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE);
if (eflash)
eflash.target = morphed;
PostMorph(morphed, false);
morphed.PostMorph(self, true);
return true;
}
}

View file

@ -1659,7 +1659,8 @@ class PlayerPawn : Actor
{
if (player.ReadyWeapon != null)
{
player.GetPSprite(PSP_WEAPON).y = WEAPONTOP;
let psp = player.GetPSprite(PSP_WEAPON);
if (psp) psp.y = WEAPONTOP;
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState());
}
return;
@ -1686,7 +1687,8 @@ class PlayerPawn : Actor
weapon.PlayUpSound(self);
player.refire = 0;
player.GetPSprite(PSP_WEAPON).y = player.cheats & CF_INSTANTWEAPSWITCH? WEAPONTOP : WEAPONBOTTOM;
let psp = player.GetPSprite(PSP_WEAPON);
if (psp) psp.y = player.cheats & CF_INSTANTWEAPSWITCH? WEAPONTOP : WEAPONBOTTOM;
// make sure that the previous weapon's flash state is terminated.
// When coming here from a weapon drop it may still be active.
player.SetPsprite(PSP_FLASH, null);
@ -2716,7 +2718,7 @@ struct PlayerInfo native play // self is what internally is known as player_t
native clearscope bool HasWeaponsInSlot(int slot) const;
// The actual implementation is on PlayerPawn where it can be overridden. Use that directly in the future.
deprecated("3.7") bool MorphPlayer(playerinfo p, Class<PlayerPawn> spawntype, int duration, int style, Class<Actor> enter_flash = null, Class<Actor> exit_flash = null)
deprecated("3.7", "MorphPlayer() should be used on a PlayerPawn object") bool MorphPlayer(playerinfo p, Class<PlayerPawn> spawntype, int duration, int style, Class<Actor> enter_flash = null, Class<Actor> exit_flash = null)
{
if (mo != null)
{
@ -2726,7 +2728,7 @@ struct PlayerInfo native play // self is what internally is known as player_t
}
// This somehow got its arguments mixed up. 'self' should have been the player to be unmorphed, not the activator
deprecated("3.7") bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false)
deprecated("3.7", "UndoPlayerMorph() should be used on a PlayerPawn object") bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false)
{
if (player.mo != null)
{
@ -2735,7 +2737,7 @@ struct PlayerInfo native play // self is what internally is known as player_t
return false;
}
deprecated("3.7") void DropWeapon()
deprecated("3.7", "DropWeapon() should be used on a PlayerPawn object") void DropWeapon()
{
if (mo != null)
{
@ -2743,7 +2745,7 @@ struct PlayerInfo native play // self is what internally is known as player_t
}
}
deprecated("3.7") void BringUpWeapon()
deprecated("3.7", "BringUpWeapon() should be used on a PlayerPawn object") void BringUpWeapon()
{
if (mo) mo.BringUpWeapon();
}

View file

@ -57,7 +57,8 @@ extend class PlayerPawn
if (player.ReadyWeapon != null)
{
player.GetPSprite(PSP_WEAPON).y = WEAPONTOP;
let psp = player.GetPSprite(PSP_WEAPON);
if (psp) psp.y = WEAPONTOP;
}
if (morphweaponcls == null || !(morphweaponcls is 'Weapon'))
@ -138,6 +139,11 @@ extend class PlayerPawn
}
let morphed = PlayerPawn(Spawn (spawntype, Pos, NO_REPLACE));
// Use GetClass in the event someone actually allows replacements.
PreMorph(morphed, false);
morphed.PreMorph(self, true);
EndAllPowerupEffects();
Substitute(morphed);
if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate)
@ -211,6 +217,8 @@ extend class PlayerPawn
morphed.ScoreIcon = ScoreIcon; // [GRB]
if (eflash)
eflash.target = morphed;
PostMorph(morphed, false); // No longer the current body
morphed.PostMorph(self, true); // This is the current body
return true;
}
@ -249,6 +257,10 @@ extend class PlayerPawn
player.morphTics = 2*TICRATE;
return false;
}
PreUnmorph(altmo, false); // This body's about to be left.
altmo.PreUnmorph(self, true); // This one's about to become current.
// No longer using tracer as morph storage. That is what 'alternative' is for.
// If the tracer has changed on the morph, change the original too.
altmo.target = target;
@ -395,6 +407,8 @@ extend class PlayerPawn
beastweap.Destroy ();
}
}
PostUnmorph(altmo, false); // This body is no longer current.
altmo.PostUnmorph(self, true); // altmo body is current.
Destroy ();
// Restore playerclass armor to its normal amount.
let hxarmor = HexenArmor(altmo.FindInventory('HexenArmor'));
@ -544,6 +558,8 @@ class MorphedMonster : Actor
UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds
return false;
}
PreUnmorph(unmorphed, false);
unmorphed.PreUnmorph(self, true);
unmorphed.Angle = Angle;
unmorphed.target = target;
unmorphed.bShadow = bShadow;
@ -563,6 +579,8 @@ class MorphedMonster : Actor
unmorphed.args[4] = args[4];
unmorphed.CopyFriendliness (self, true);
unmorphed.bUnmorphed = false;
PostUnmorph(unmorphed, false); // From is false here: Leaving the caller's body.
unmorphed.PostUnmorph(self, true); // True here: Entering this body from here.
UnmorphedMe = NULL;
Substitute(unmorphed);
Destroy ();

View file

@ -202,7 +202,7 @@ class Sigil : Weapon
return;
}
PSprite pspr = player.GetPSprite(PSP_WEAPON);
pspr.SetState(pspr.CurState + invoker.health);
if (pspr) pspr.SetState(pspr.CurState + invoker.health);
invoker.downpieces = 0;
}
@ -225,7 +225,7 @@ class Sigil : Weapon
PSprite pspr = player.GetPSprite(PSP_WEAPON);
int pieces = invoker.downpieces;
if (pieces < 1 || pieces > 5) pieces = invoker.health;
pspr.SetState(pspr.CurState + pieces);
if (pspr) pspr.SetState(pspr.CurState + pieces);
}
//============================================================================
@ -243,7 +243,7 @@ class Sigil : Weapon
return;
}
PSprite pspr = player.GetPSprite(PSP_WEAPON);
pspr.SetState(pspr.CurState + (4 * invoker.health - 3));
if (pspr) pspr.SetState(pspr.CurState + (4 * invoker.health - 3));
}
//============================================================================

View file

@ -121,19 +121,22 @@ class StrifePlayer : PlayerPawn
State firehandslower = FindState("FireHandsLower");
State firehands = FindState("FireHands");
if (psp.CurState != null && firehandslower != null && firehands != null)
if (psp)
{
// Calculate state to go to.
int dist = firehands.DistanceTo(psp.curState);
if (dist > 0)
if (psp.CurState != null && firehandslower != null && firehands != null)
{
player.playerstate = PST_DEAD;
psp.SetState(firehandslower + dist);
return;
// Calculate state to go to.
int dist = firehands.DistanceTo(psp.curState);
if (dist > 0)
{
player.playerstate = PST_DEAD;
psp.SetState(firehandslower + dist);
return;
}
}
player.playerstate = PST_DEAD;
psp.SetState(null);
}
player.playerstate = PST_DEAD;
psp.SetState(null);
}
}
@ -142,19 +145,20 @@ class StrifePlayer : PlayerPawn
if (player != null)
{
PSprite psp = player.GetPSprite(PSP_STRIFEHANDS);
if (psp.CurState == null)
if (psp)
{
psp.SetState(null);
return;
if (psp.CurState == null)
{
psp.SetState(null);
return;
}
psp.y += 9;
if (psp.y > WEAPONBOTTOM*2)
{
psp.SetState(null);
}
}
psp.y += 9;
if (psp.y > WEAPONBOTTOM*2)
{
psp.SetState(null);
}
if (player.extralight > 0) player.extralight--;
}
return;

View file

@ -137,8 +137,11 @@ class Mauler2 : Mauler
if (player != null)
{
PSprite psp = player.GetPSprite(PSP_WEAPON);
psp.x += Random2[Mauler2]() / 64.;
psp.y += Random2[Mauler2]() / 64.;
if (psp)
{
psp.x += Random2[Mauler2]() / 64.;
psp.y += Random2[Mauler2]() / 64.;
}
}
}

View file

@ -45,7 +45,7 @@ struct _ native // These are the global variables, the struct is only here to av
native readonly int Net_Arbitrator;
native ui BaseStatusBar StatusBar;
native readonly Weapon WP_NOCHANGE;
deprecated("3.8") native readonly bool globalfreeze;
deprecated("3.8", "Use Actor.isFrozen() or Level.isFrozen() instead") native readonly bool globalfreeze;
native int LocalViewPitch;
native readonly @MusPlayingInfo musplaying;
native readonly bool generic_ui;
@ -110,7 +110,7 @@ struct TexMan
};
native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny);
deprecated("3.8") static void ReplaceTextures(String from, String to, int flags)
deprecated("3.8", "Use Level.ReplaceTextures() instead") static void ReplaceTextures(String from, String to, int flags)
{
level.ReplaceTextures(from, to, flags);
}
@ -191,6 +191,8 @@ enum DrawTextureTags
DTA_Internal3,
DTA_Spacing, // Strings only: Additional spacing between characters
DTA_Monospace, // Strings only: Use a fixed distance between characters.
DTA_FullscreenEx, // advanced fullscreen control.
};
class Shape2DTransform : Object native
@ -242,7 +244,7 @@ struct Screen native
// This is a leftover of the abandoned Inventory.DrawPowerup method.
deprecated("2.5") static ui void DrawHUDTexture(TextureID tex, double x, double y)
deprecated("2.5", "Use StatusBar.DrawTexture() instead") static ui void DrawHUDTexture(TextureID tex, double x, double y)
{
statusBar.DrawTexture(tex, (x, y), BaseStatusBar.DI_SCREEN_RIGHT_TOP, 1., (32, 32));
}
@ -436,16 +438,16 @@ class Object native
native static String G_SkillName();
native static int G_SkillPropertyInt(int p);
native static double G_SkillPropertyFloat(int p);
deprecated("3.8") static vector3, int G_PickDeathmatchStart()
deprecated("3.8", "Use Level.PickDeathMatchStart() instead") static vector3, int G_PickDeathmatchStart()
{
return level.PickDeathmatchStart();
}
deprecated("3.8") static vector3, int G_PickPlayerStart(int pnum, int flags = 0)
deprecated("3.8", "Use Level.PickPlayerStart() instead") static vector3, int G_PickPlayerStart(int pnum, int flags = 0)
{
return level.PickPlayerStart(pnum, flags);
}
deprecated("4.3") native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0);
native static void S_StartSound (Sound sound_id, int channel, int flags = 0, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0);
deprecated("4.3", "Use S_StartSound() instead") native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0);
native static void S_StartSound (Sound sound_id, int channel, int flags = 0, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0, float startTime = 0.0);
native static void S_PauseSound (bool notmusic, bool notsfx);
native static void S_ResumeSound (bool notsfx);
native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false);
@ -530,7 +532,7 @@ class ThinkerIterator : Object native
class ActorIterator : Object native
{
deprecated("3.8") static ActorIterator Create(int tid, class<Actor> type = "Actor")
deprecated("3.8", "Use Level.CreateActorIterator() instead") static ActorIterator Create(int tid, class<Actor> type = "Actor")
{
return level.CreateActorIterator(tid, type);
}
@ -716,7 +718,7 @@ struct LevelLocals native
native readonly bool polygrind;
native readonly bool nomonsters;
native readonly bool allowrespawn;
deprecated("3.8") native bool frozen;
deprecated("3.8", "Use Level.isFrozen() instead") native bool frozen;
native readonly bool infinite_flight;
native readonly bool no_dlg_freeze;
native readonly bool keepfullinventory;
@ -740,7 +742,7 @@ struct LevelLocals native
native static void MakeScreenShot();
native static void MakeAutoSave();
native void WorldDone();
deprecated("3.8") static void RemoveAllBots(bool fromlist) { /* intentionally left as no-op. */ }
deprecated("3.8", "This function does nothing") static void RemoveAllBots(bool fromlist) { /* intentionally left as no-op. */ }
native ui Vector2 GetAutomapPosition();
native void SetInterMusic(String nextmap);
native String FormatMapName(int mapnamecolor);
@ -761,7 +763,7 @@ struct LevelLocals native
native clearscope Sector PointInSector(Vector2 pt) const;
native clearscope bool IsPointInLevel(vector3 p) const;
deprecated("3.8") clearscope static bool IsPointInMap(vector3 p)
deprecated("3.8", "Use Level.IsPointInLevel() instead") clearscope static bool IsPointInMap(vector3 p)
{
return level.IsPointInLevel(p);
}
@ -925,15 +927,15 @@ struct StringStruct native
native String Mid(int pos = 0, int len = 2147483647) const;
native void Truncate(int newlen);
native void Remove(int index, int remlen);
deprecated("4.1") native String CharAt(int pos) const;
deprecated("4.1") native int CharCodeAt(int pos) const;
deprecated("4.1", "use Left() or Mid() instead") native String CharAt(int pos) const;
deprecated("4.1", "use ByteAt() instead") native int CharCodeAt(int pos) const;
native int ByteAt(int pos) const;
native String Filter();
native int IndexOf(String substr, int startIndex = 0) const;
deprecated("3.5.1") native int LastIndexOf(String substr, int endIndex = 2147483647) const;
deprecated("3.5.1", "use RightIndexOf() instead") native int LastIndexOf(String substr, int endIndex = 2147483647) const;
native int RightIndexOf(String substr, int endIndex = 2147483647) const;
deprecated("4.1") native void ToUpper();
deprecated("4.1") native void ToLower();
deprecated("4.1", "use MakeUpper() instead") native void ToUpper();
deprecated("4.1", "use MakeLower() instead") native void ToLower();
native String MakeUpper() const;
native String MakeLower() const;
native static int CharUpper(int ch);
@ -1005,7 +1007,7 @@ class Floor : MovingFloor native
genFloorChg
};
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)
deprecated("3.8", "Use Level.CreateFloor() instead") 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);
}
@ -1051,7 +1053,7 @@ class Ceiling : MovingCeiling native
crushSlowdown = 2
}
deprecated("3.8") static 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)
deprecated("3.8", "Use Level.CreateCeiling() instead") static 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)
{
return level.CreateCeiling(sec, type, ln, speed, speed2, height, crush, silent, change, crushmode);
}

View file

@ -2,12 +2,12 @@
extend class Object
{
deprecated("2.4") static int GameType()
deprecated("2.4", "Use gameinfo.gametype instead") static int GameType()
{
return gameinfo.gametype;
}
deprecated("2.4") static void C_MidPrint(string fontname, string textlabel, bool bold = false)
deprecated("2.4", "Use Console.MidPrint() instead") static void C_MidPrint(string fontname, string textlabel, bool bold = false)
{
let f = Font.GetFont(fontname);
if (f == null) return;
@ -27,7 +27,7 @@ extend class Actor
//
//==========================================================================
deprecated("3.7") bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false)
deprecated("3.7", "Use GetClass(), type cast, or 'is' operator instead") bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false)
{
let check = GetPointer(ptr_select);
if (check == null || checkclass == null)
@ -52,7 +52,7 @@ extend class Actor
// deprecated because it requires AAPTR to work.
//
//==========================================================================
deprecated("3.7") double GetDistance(bool checkz, int ptr = AAPTR_TARGET) const
deprecated("3.7", "Use Actor.Distance2D() or Actor.Distance3D() instead") double GetDistance(bool checkz, int ptr = AAPTR_TARGET) const
{
let target = GetPointer(ptr);
@ -81,7 +81,7 @@ extend class Actor
//
//==========================================================================
deprecated("3.7") double GetAngle(int flags, int ptr = AAPTR_TARGET)
deprecated("3.7", "Use Actor.AngleTo() instead") double GetAngle(int flags, int ptr = AAPTR_TARGET)
{
let target = GetPointer(ptr);
@ -107,7 +107,7 @@ extend class Actor
//
//==========================================================================
deprecated("3.7") double GetSpriteAngle(int ptr = AAPTR_DEFAULT)
deprecated("3.7", "Use Actor.SpriteAngle instead") double GetSpriteAngle(int ptr = AAPTR_DEFAULT)
{
let target = GetPointer(ptr);
return target? target.SpriteAngle : 0;
@ -122,13 +122,13 @@ extend class Actor
//
//==========================================================================
deprecated("3.7") double GetSpriteRotation(int ptr = AAPTR_DEFAULT)
deprecated("3.7", "Use Actor.SpriteRotation instead") double GetSpriteRotation(int ptr = AAPTR_DEFAULT)
{
let target = GetPointer(ptr);
return target? target.SpriteRotation : 0;
}
deprecated("2.3") void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET)
deprecated("2.3", "Use A_SpawnProjectile() instead") void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET)
{
A_SpawnProjectile(missiletype, spawnheight, spawnofs_xy, angle, flags|CMF_BADPITCH, pitch, ptr);
}
@ -136,7 +136,7 @@ extend class Actor
extend class StateProvider
{
deprecated("2.3") action void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0)
deprecated("2.3", "Use A_FireProjectile() instead") action void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0)
{
A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch);
}

View file

@ -1047,6 +1047,7 @@ enum ETranslationTable
TRANSLATION_Blood,
TRANSLATION_RainPillar,
TRANSLATION_Custom,
TRANSLATION_Font,
};
enum EFindFloorCeiling

View file

@ -1,6 +1,6 @@
struct HealthGroup native play
{
deprecated("3.8") static clearscope HealthGroup Find(int id)
deprecated("3.8", "Use Level.FindHealthGroup() instead") static clearscope HealthGroup Find(int id)
{
return level.FindHealthGroup(id);
}

View file

@ -1,4 +1,11 @@
struct Dictionary native
/**
* Dictionary provides key-value storage.
*
* Both keys and values are strings.
*
* @note keys are case-sensitive.
*/
class Dictionary
{
native static Dictionary Create();
@ -23,7 +30,15 @@ struct Dictionary native
native String ToString() const;
}
struct DictionaryIterator native
/**
* Provides iterating over a Dictionary.
*
* Order is not specified.
*
* DictionaryIterator is not serializable. To make DictionaryIterator a class
* member, use `transient` keyword.
*/
class DictionaryIterator
{
native static DictionaryIterator Create(Dictionary dict);

View file

@ -423,7 +423,7 @@ struct Sector native play
native int GetAttachedCount();
native void RemoveForceField();
deprecated("3.8") static clearscope Sector PointInSector(Vector2 pt)
deprecated("3.8", "Use Level.PointInSector instead") static clearscope Sector PointInSector(Vector2 pt)
{
return level.PointInSector(pt);
}
@ -588,7 +588,7 @@ struct Sector native play
class SectorTagIterator : Object native
{
deprecated("3.8") static SectorTagIterator Create(int tag, line defline = null)
deprecated("3.8", "Use Level.CreateSectorTagIterator() instead") static SectorTagIterator Create(int tag, line defline = null)
{
return level.CreateSectorTagIterator(tag, defline);
}
@ -598,7 +598,7 @@ class SectorTagIterator : Object native
class LineIdIterator : Object native
{
deprecated("3.8") static LineIdIterator Create(int tag)
deprecated("3.8", "Use Level.CreateLineIdIterator() instead") static LineIdIterator Create(int tag)
{
return level.CreateLineIdIterator(tag);
}

View file

@ -209,6 +209,7 @@ IWad
IWad
{
Name = "Hexen: Demo Version"
Autoname = "hexen.shareware"
Game = "Hexen"
Config = "Hexen"
Mapinfo = "mapinfo/hexen.txt"
@ -259,7 +260,7 @@ IWad
IWad
{
Autoname = "hereticshareware"
Autoname = "heretic.shareware"
Name = "Heretic Shareware"
Game = "Heretic"
Config = "Heretic"
@ -415,6 +416,7 @@ IWad
IWad
{
Name = "DOOM Shareware"
Autoname = "doom.id.doom1.shareware"
Game = "Doom"
Config = "Doom"
Mapinfo = "mapinfo/doom1.txt"