Merge branch 'master' of https://github.com/ZDoom/gzdoom
This commit is contained in:
commit
1fae4b9d4a
27 changed files with 714 additions and 116 deletions
|
|
@ -1001,6 +1001,7 @@ set (PCH_SOURCES
|
|||
common/textures/multipatchtexturebuilder.cpp
|
||||
common/textures/skyboxtexture.cpp
|
||||
common/textures/animtexture.cpp
|
||||
common/textures/firetexture.cpp
|
||||
common/textures/v_collection.cpp
|
||||
common/textures/formats/automaptexture.cpp
|
||||
common/textures/formats/brightmaptexture.cpp
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "palentry.h"
|
||||
#include "name.h"
|
||||
#include "dictionary.h"
|
||||
#include "bonecomponents.h"
|
||||
|
||||
extern bool save_full;
|
||||
|
||||
|
|
@ -247,7 +248,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString
|
|||
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &mo, struct ModelOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnim &ao, ModelAnim *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def);
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
||||
|
||||
void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "TRS.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
|
||||
class DBoneComponents : public DObject
|
||||
{
|
||||
|
|
@ -14,3 +16,41 @@ public:
|
|||
|
||||
DBoneComponents() = default;
|
||||
};
|
||||
|
||||
struct ModelAnimFrameInterp
|
||||
{
|
||||
float inter = -1.0f;
|
||||
int frame1 = -1;
|
||||
int frame2 = -1;
|
||||
};
|
||||
|
||||
struct ModelAnimFramePrecalculatedIQM
|
||||
{
|
||||
TArray<TRS> precalcBones;
|
||||
};
|
||||
|
||||
enum EModelAnimFlags
|
||||
{
|
||||
MODELANIM_NONE = 1 << 0, // no animation
|
||||
MODELANIM_LOOP = 1 << 1, // animation loops, otherwise it stays on the last frame once it ends
|
||||
};
|
||||
|
||||
struct ModelAnim
|
||||
{
|
||||
int firstFrame = 0;
|
||||
int lastFrame = 0;
|
||||
int loopFrame = 0;
|
||||
float framerate = 0;
|
||||
double startFrame = 0;
|
||||
int flags = MODELANIM_NONE;
|
||||
double startTic = 0; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation)
|
||||
double switchOffset = 0; // when the animation was changed -- where to interpolate the switch from
|
||||
};
|
||||
|
||||
static_assert(sizeof(ModelAnim) == sizeof(double) * 6);
|
||||
|
||||
using ModelAnimFrame = std::variant<std::nullptr_t, ModelAnimFrameInterp, ModelAnimFramePrecalculatedIQM>;
|
||||
|
||||
double getCurrentFrame(const ModelAnim &anim, double tic, bool *looped);
|
||||
void calcFrame(const ModelAnim &anim, double tic, ModelAnimFrameInterp &inter);
|
||||
void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to, float &inter);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include "tarray.h"
|
||||
#include "name.h"
|
||||
|
||||
#include "bonecomponents.h"
|
||||
|
||||
class DBoneComponents;
|
||||
class FModelRenderer;
|
||||
class FGameTexture;
|
||||
|
|
@ -94,7 +96,10 @@ public:
|
|||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
|
||||
virtual float getAspectFactor(float vscale) { return 1.f; }
|
||||
virtual const TArray<TRS>* AttachAnimationData() { return nullptr; };
|
||||
virtual const TArray<VSMatrix> CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* bones, int index) { return {}; };
|
||||
|
||||
virtual ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) { return nullptr; };
|
||||
|
||||
virtual const TArray<VSMatrix> CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) { return {}; };
|
||||
|
||||
void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
|
||||
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }
|
||||
|
|
|
|||
|
|
@ -120,7 +120,12 @@ public:
|
|||
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
||||
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
||||
const TArray<TRS>* AttachAnimationData() override;
|
||||
const TArray<VSMatrix> CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* bones, int index) override;
|
||||
|
||||
ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) override;
|
||||
const TArray<VSMatrix> CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) override;
|
||||
|
||||
ModelAnimFramePrecalculatedIQM CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData, DBoneComponents* bones, int index);
|
||||
const TArray<VSMatrix> CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData, DBoneComponents* bones, int index);
|
||||
|
||||
private:
|
||||
void LoadGeometry();
|
||||
|
|
|
|||
|
|
@ -560,7 +560,108 @@ static TRS InterpolateBone(const TRS &from, const TRS &to, float t, float invt)
|
|||
return bone;
|
||||
}
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* boneComponentData, int index)
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
ModelAnimFrame IQMModel::PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index)
|
||||
{
|
||||
if(inter <= 0)
|
||||
{
|
||||
return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFrameInterp>(from))
|
||||
{
|
||||
auto &from_interp = std::get<ModelAnimFrameInterp>(from);
|
||||
|
||||
return CalculateFrameIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFramePrecalculatedIQM>(from))
|
||||
{
|
||||
return CalculateFrameIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get<ModelAnimFramePrecalculatedIQM>(from), animationData, bones, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index);
|
||||
}
|
||||
}
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index)
|
||||
{
|
||||
if(inter <= 0)
|
||||
{
|
||||
return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFrameInterp>(from))
|
||||
{
|
||||
auto &from_interp = std::get<ModelAnimFrameInterp>(from);
|
||||
|
||||
return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFramePrecalculatedIQM>(from))
|
||||
{
|
||||
return CalculateBonesIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get<ModelAnimFramePrecalculatedIQM>(from), animationData, bones, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index);
|
||||
}
|
||||
}
|
||||
|
||||
ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData, DBoneComponents* boneComponentData, int index)
|
||||
{
|
||||
ModelAnimFramePrecalculatedIQM out;
|
||||
const TArray<TRS>& animationFrames = animationData ? *animationData : TRSData;
|
||||
|
||||
out.precalcBones.Resize(Joints.Size());
|
||||
|
||||
if (Joints.Size() > 0)
|
||||
{
|
||||
int numbones = Joints.SSize();
|
||||
|
||||
int offset1 = frame1 * numbones;
|
||||
int offset2 = frame2 * numbones;
|
||||
|
||||
int offset1_1 = frame1_prev * numbones;
|
||||
int offset2_1 = frame2_prev * numbones;
|
||||
|
||||
float invt = 1.0f - inter;
|
||||
float invt1 = 1.0f - inter1_prev;
|
||||
float invt2 = 1.0f - inter2_prev;
|
||||
|
||||
for (int i = 0; i < numbones; i++)
|
||||
{
|
||||
TRS prev;
|
||||
|
||||
if(precalculated)
|
||||
{
|
||||
prev = precalculated->precalcBones[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
|
||||
{
|
||||
prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
|
||||
}
|
||||
}
|
||||
|
||||
TRS next;
|
||||
|
||||
if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0))
|
||||
{
|
||||
next = inter2_prev <= 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2);
|
||||
}
|
||||
|
||||
if(frame1 >= 0 || inter < 0)
|
||||
{
|
||||
out.precalcBones[i] = inter < 0 ? animationFrames[offset1 + i] : InterpolateBone(prev, next , inter, invt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray<TRS>* animationData, DBoneComponents* boneComponentData, int index)
|
||||
{
|
||||
const TArray<TRS>& animationFrames = animationData ? *animationData : TRSData;
|
||||
if (Joints.Size() > 0)
|
||||
|
|
@ -597,9 +698,16 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float in
|
|||
{
|
||||
TRS prev;
|
||||
|
||||
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
|
||||
if(precalculated)
|
||||
{
|
||||
prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
|
||||
prev = precalculated->precalcBones[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
|
||||
{
|
||||
prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
|
||||
}
|
||||
}
|
||||
|
||||
TRS next;
|
||||
|
|
|
|||
|
|
@ -770,6 +770,26 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetDisplayTopOffset, GetDisplayTopOffset)
|
|||
ACTION_RETURN_FLOAT(GetDisplayTopOffset(self, code));
|
||||
}
|
||||
|
||||
static int GetChar(FFont* font, int c)
|
||||
{
|
||||
int texc = 0;
|
||||
auto getch = font->GetChar(c, CR_UNDEFINED, nullptr);
|
||||
if (getch)
|
||||
texc = getch->GetID().GetIndex();
|
||||
return texc;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetChar, ::GetChar)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FFont);
|
||||
PARAM_INT(mchar);
|
||||
|
||||
if (numret > 0) ret[0].SetInt(::GetChar(self, mchar));
|
||||
if (numret > 1) ret[1].SetInt(self->GetCharWidth(mchar));
|
||||
return min(2, numret);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// file system
|
||||
|
|
|
|||
139
src/common/textures/firetexture.cpp
Normal file
139
src/common/textures/firetexture.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
** firetexture.cpp
|
||||
** PSX/N64-style fire texture implementation
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright Cacodemon345 2024
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
/* Algorithm based on https://github.com/fabiensanglard/DoomFirePSX */
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "firetexture.h"
|
||||
#include "m_random.h"
|
||||
#include "imagehelpers.h"
|
||||
|
||||
#include "engineerrors.h"
|
||||
|
||||
static constexpr int32_t FIRESKY_W = 64;
|
||||
static constexpr int32_t FIRESKY_H = 128;
|
||||
|
||||
FireTexture::FireTexture()
|
||||
{
|
||||
SetSize(FIRESKY_W, FIRESKY_H);
|
||||
Image.Clear();
|
||||
Image.AppendFill(0, Width * Height);
|
||||
}
|
||||
|
||||
void FireTexture::SetPalette(TArray<PalEntry>& colors)
|
||||
{
|
||||
Palette.Clear();
|
||||
Palette.Append(colors);
|
||||
|
||||
/* This shouldn't happen in any circumstances. */
|
||||
if (Palette.Size() > 256)
|
||||
{
|
||||
I_FatalError("Fire palette too big!");
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < Width; i++) {
|
||||
Image[(Height - 1) * Width + i] = (uint8_t)(Palette.Size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void FireTexture::Update()
|
||||
{
|
||||
for (unsigned int y = 1; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
uint8_t srcPixel = Image[y * Width + x];
|
||||
|
||||
if (srcPixel == 0)
|
||||
{
|
||||
Image[(y - 1) * Width + x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int XRand = M_Random() & 3;
|
||||
int destRand = M_Random() & 1;
|
||||
|
||||
Image[(y - 1) * Width + ((x + 1 - XRand) % Width)] = srcPixel - destRand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FBitmap FireTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
|
||||
{
|
||||
FBitmap bitmap;
|
||||
bitmap.Create(Width, Height);
|
||||
uint32_t* pixels = (uint32_t*)bitmap.GetPixels();
|
||||
|
||||
for (unsigned int y = 0; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
pixels[y * Width + x] = Palette[Image[y * Width + x]];
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
TArray<uint8_t> FireTexture::Get8BitPixels(bool alphatex)
|
||||
{
|
||||
FBitmap bitmap = GetBgraBitmap(nullptr, nullptr);
|
||||
const uint8_t* data = bitmap.GetPixels();
|
||||
|
||||
uint8_t* dest_p;
|
||||
int dest_adv = Height;
|
||||
int dest_rew = Width * Height - 1;
|
||||
|
||||
TArray<uint8_t> Pixels(Width * Height);
|
||||
dest_p = Pixels.Data();
|
||||
|
||||
bool doalpha = alphatex;
|
||||
// Convert the source image from row-major to column-major format and remap it
|
||||
for (int y = Height; y != 0; --y)
|
||||
{
|
||||
for (int x = Width; x != 0; --x)
|
||||
{
|
||||
int b = *data++;
|
||||
int g = *data++;
|
||||
int r = *data++;
|
||||
int a = *data++;
|
||||
if (a < 128) *dest_p = 0;
|
||||
else *dest_p = ImageHelpers::RGBToPalette(doalpha, r, g, b);
|
||||
dest_p += dest_adv;
|
||||
}
|
||||
dest_p -= dest_rew;
|
||||
}
|
||||
return Pixels;
|
||||
}
|
||||
17
src/common/textures/firetexture.h
Normal file
17
src/common/textures/firetexture.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "textures.h"
|
||||
|
||||
|
||||
class FireTexture : public FTexture
|
||||
{
|
||||
TArray<uint8_t> Image;
|
||||
TArray<PalEntry> Palette;
|
||||
|
||||
public:
|
||||
FireTexture();
|
||||
void SetPalette(TArray<PalEntry>& colors);
|
||||
void Update();
|
||||
virtual FBitmap GetBgraBitmap(const PalEntry* remap, int* trans) override;
|
||||
virtual TArray<uint8_t> Get8BitPixels(bool alphatex) override;
|
||||
};
|
||||
|
|
@ -306,7 +306,8 @@ void FImageSource::EndPrecaching()
|
|||
|
||||
void FImageSource::RegisterForPrecache(FImageSource *img, bool requiretruecolor)
|
||||
{
|
||||
img->CollectForPrecache(precacheInfo, requiretruecolor);
|
||||
if (img)
|
||||
img->CollectForPrecache(precacheInfo, requiretruecolor);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
iwad->prio = sc.Number;
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("SupportWAD"))
|
||||
{
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
iwad->SupportWAD = sc.String;
|
||||
}
|
||||
else if (sc.Compare("Config"))
|
||||
{
|
||||
sc.MustGetStringName("=");
|
||||
|
|
@ -562,6 +568,18 @@ void FIWadManager::ValidateIWADs()
|
|||
|
||||
static bool havepicked = false;
|
||||
|
||||
|
||||
FString FIWadManager::IWADPathFileSearch(const FString &file)
|
||||
{
|
||||
for(const FString &path : mSearchPaths)
|
||||
{
|
||||
FString f = path + "/" + file;
|
||||
if(FileExists(f)) return f;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int FIWadManager::IdentifyVersion (std::vector<std::string>&wadfiles, const char *iwad, const char *zdoom_wad, const char *optional_wad)
|
||||
{
|
||||
const char *iwadparm = Args->CheckValue ("-iwad");
|
||||
|
|
@ -802,11 +820,11 @@ int FIWadManager::IdentifyVersion (std::vector<std::string>&wadfiles, const char
|
|||
D_AddFile (wadfiles, zdoom_wad, true, -1, GameConfig);
|
||||
|
||||
// [SP] Load non-free assets if available. This must be done before the IWAD.
|
||||
int iwadnum;
|
||||
int iwadnum = 1;
|
||||
if (D_AddFile(wadfiles, optional_wad, true, -1, GameConfig))
|
||||
iwadnum = 2;
|
||||
else
|
||||
iwadnum = 1;
|
||||
{
|
||||
iwadnum++;
|
||||
}
|
||||
|
||||
fileSystem.SetIwadNum(iwadnum);
|
||||
if (picks[pick].mRequiredPath.IsNotEmpty())
|
||||
|
|
@ -818,6 +836,17 @@ int FIWadManager::IdentifyVersion (std::vector<std::string>&wadfiles, const char
|
|||
fileSystem.SetMaxIwadNum(iwadnum);
|
||||
|
||||
auto info = mIWadInfos[picks[pick].mInfoIndex];
|
||||
|
||||
if(info.SupportWAD.IsNotEmpty())
|
||||
{
|
||||
FString supportWAD = IWADPathFileSearch(info.SupportWAD);
|
||||
|
||||
if(supportWAD.IsNotEmpty())
|
||||
{
|
||||
D_AddFile(wadfiles, supportWAD.GetChars(), true, -1, GameConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Load additional resources from the same directory as the IWAD itself.
|
||||
for (unsigned i=0; i < info.Load.Size(); i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ struct FIWADInfo
|
|||
FString Name; // Title banner text for this IWAD
|
||||
FString Autoname; // Name of autoload ini section for this IWAD
|
||||
FString IWadname; // Default name this game would use - this is for IWAD detection in GAMEINFO.
|
||||
FString SupportWAD; // Optional support WAD, load if present (initially implemented for id24)
|
||||
int prio = 0; // selection priority for given IWAD name.
|
||||
FString Configname; // Name of config section for this IWAD
|
||||
FString Required; // Requires another IWAD
|
||||
|
|
@ -133,7 +134,9 @@ class FIWadManager
|
|||
void CollectSearchPaths();
|
||||
void AddIWADCandidates(const char *dir);
|
||||
void ValidateIWADs();
|
||||
FString IWADPathFileSearch(const FString &file);
|
||||
public:
|
||||
|
||||
FIWadManager(const char *fn, const char *fnopt);
|
||||
const FIWADInfo *FindIWAD(std::vector<std::string>& wadfiles, const char *iwad, const char *basewad, const char *optionalwad);
|
||||
const FString *GetAutoname(unsigned int num) const
|
||||
|
|
|
|||
|
|
@ -1236,6 +1236,7 @@ void G_Ticker ()
|
|||
case ga_intro:
|
||||
gamestate = GS_INTRO;
|
||||
gameaction = ga_nothing;
|
||||
C_HideConsole(); // On some systems, console is open during intro
|
||||
break;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,12 @@ static FRandom pr_animatepictures ("AnimatePics");
|
|||
|
||||
void FTextureAnimator::DeleteAll()
|
||||
{
|
||||
for (unsigned int i = 0; i < mFireTextures.Size(); i++)
|
||||
{
|
||||
mFireTextures[i].texture->CleanHardwareData(true);
|
||||
}
|
||||
mAnimations.Clear();
|
||||
mFireTextures.Clear();
|
||||
|
||||
for (unsigned i = 0; i < mSwitchDefs.Size(); i++)
|
||||
{
|
||||
|
|
@ -348,6 +353,10 @@ void FTextureAnimator::InitAnimDefs ()
|
|||
TexMan.GameTexture(picnum)->SetSkyOffset(sc.Number);
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("firetexture"))
|
||||
{
|
||||
ParseFireTexture (sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError (NULL);
|
||||
|
|
@ -782,6 +791,84 @@ void FTextureAnimator::ParseCameraTexture(FScanner &sc)
|
|||
viewer->SetDisplaySize((float)fitwidth, (float)fitheight);
|
||||
}
|
||||
|
||||
void FTextureAnimator::ParseFireTexture(FScanner& sc)
|
||||
{
|
||||
FString picname;
|
||||
FFireTexture fireTexture;
|
||||
TArray<PalEntry> palette;
|
||||
uint32_t duration;
|
||||
|
||||
sc.MustGetString();
|
||||
picname = sc.String;
|
||||
sc.MustGetStringName("tics");
|
||||
sc.MustGetValue(true);
|
||||
duration = uint32_t(sc.Float * 1000 / TICRATE);
|
||||
|
||||
FGameTexture* gametex = MakeGameTexture(new FireTexture(), picname.GetChars(), ETextureType::Wall);
|
||||
// No decals here.
|
||||
gametex->SetNoDecals(true);
|
||||
if (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("allowdecals"))
|
||||
{
|
||||
gametex->SetNoDecals(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.UnGet();
|
||||
}
|
||||
}
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("color"))
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
sc.MustGetValue(false);
|
||||
r = sc.Number;
|
||||
sc.MustGetValue(false);
|
||||
g = sc.Number;
|
||||
sc.MustGetValue(false);;
|
||||
b = sc.Number;
|
||||
sc.MustGetValue(false);
|
||||
a = sc.Number;
|
||||
palette.Push(PalEntry(a, r, g, b));
|
||||
if (a != 255 && a != 0);
|
||||
gametex->SetTranslucent(true);
|
||||
|
||||
if (palette.Size() > 256)
|
||||
{
|
||||
sc.ScriptError("Too many colors specified!");
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("palette"))
|
||||
{
|
||||
uint8_t index = 0;
|
||||
sc.MustGetValue(false);
|
||||
index = sc.Number;
|
||||
PalEntry pal = GPalette.BaseColors[index];
|
||||
pal.a = pal.isBlack() ? 0 : 255;
|
||||
palette.Push(pal);
|
||||
|
||||
if (palette.Size() > 256)
|
||||
{
|
||||
sc.ScriptError("Too many colors specified!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.UnGet();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fireTexture.texture = gametex;
|
||||
fireTexture.Duration = duration;
|
||||
fireTexture.SwitchTime = 0;
|
||||
static_cast<FireTexture*>(gametex->GetTexture())->SetPalette(palette);
|
||||
mFireTextures.Push(fireTexture);
|
||||
TexMan.AddGameTexture(gametex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FTextureAnimator :: FixAnimations
|
||||
|
|
@ -1040,6 +1127,32 @@ FTextureID FTextureAnimator::UpdateStandaloneAnimation(FStandaloneAnimation &ani
|
|||
|
||||
void FTextureAnimator::UpdateAnimations (uint64_t mstime)
|
||||
{
|
||||
for (unsigned int i = 0; i < mFireTextures.Size(); i++)
|
||||
{
|
||||
FFireTexture* fire = &mFireTextures[i];
|
||||
bool updated = false;
|
||||
|
||||
if (fire->SwitchTime == 0)
|
||||
{
|
||||
fire->SwitchTime = mstime + fire->Duration;
|
||||
}
|
||||
else while (fire->SwitchTime <= mstime)
|
||||
{
|
||||
static_cast<FireTexture*>(fire->texture->GetTexture())->Update();
|
||||
fire->SwitchTime = mstime + fire->Duration;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
fire->texture->CleanHardwareData();
|
||||
|
||||
if (fire->texture->GetSoftwareTexture())
|
||||
delete fire->texture->GetSoftwareTexture();
|
||||
|
||||
fire->texture->SetSoftwareTexture(nullptr);
|
||||
}
|
||||
}
|
||||
for (unsigned int j = 0; j < mAnimations.Size(); ++j)
|
||||
{
|
||||
FAnimDef *anim = &mAnimations[j];
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "textureid.h"
|
||||
#include "tarray.h"
|
||||
#include "s_soundinternal.h"
|
||||
#include "firetexture.h"
|
||||
|
||||
struct FStandaloneAnimation
|
||||
{
|
||||
|
|
@ -17,6 +18,13 @@ struct FStandaloneAnimation
|
|||
|
||||
static_assert(sizeof(FStandaloneAnimation) == sizeof(uint64_t)*2);
|
||||
|
||||
struct FFireTexture
|
||||
{
|
||||
uint32_t Duration; // Duration before updates.
|
||||
uint64_t SwitchTime; // Absolute time before update.
|
||||
FGameTexture* texture;
|
||||
};
|
||||
|
||||
struct FAnimDef
|
||||
{
|
||||
struct FAnimFrame
|
||||
|
|
@ -77,6 +85,7 @@ class FTextureAnimator
|
|||
TArray<FAnimDef> mAnimations;
|
||||
TArray<FSwitchDef*> mSwitchDefs;
|
||||
TArray<FDoorAnimation> mAnimatedDoors;
|
||||
TArray<FFireTexture> mFireTextures;
|
||||
|
||||
void ParseAnim(FScanner& sc, ETextureType usetype);
|
||||
FAnimDef* ParseRangeAnim(FScanner& sc, FTextureID picnum, ETextureType usetype, bool missing);
|
||||
|
|
@ -84,6 +93,7 @@ class FTextureAnimator
|
|||
void ParseWarp(FScanner& sc);
|
||||
void ParseCanvasTexture(FScanner& sc);
|
||||
void ParseCameraTexture(FScanner& sc);
|
||||
void ParseFireTexture(FScanner& sc);
|
||||
FTextureID ParseFramenum(FScanner& sc, FTextureID basepicnum, ETextureType usetype, bool allowMissing);
|
||||
void ParseTime(FScanner& sc, uint32_t& min, uint32_t& max);
|
||||
|
||||
|
|
|
|||
|
|
@ -987,6 +987,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload)
|
|||
("flags3", flags3)
|
||||
("vkdflags", vkdflags)
|
||||
("fadeto", fadeto)
|
||||
("skyspeed1", skyspeed1)
|
||||
("skyspeed2", skyspeed2)
|
||||
("found_secrets", found_secrets)
|
||||
("found_items", found_items)
|
||||
("killed_monsters", killed_monsters)
|
||||
|
|
|
|||
|
|
@ -700,24 +700,6 @@ enum EViewPosFlags // [MC] Flags for SetViewPos.
|
|||
VPSF_ORTHOGRAPHIC = 1 << 4, // Use orthographic projection (hardware renderer only).
|
||||
};
|
||||
|
||||
enum EAnimOverrideFlags
|
||||
{
|
||||
ANIMOVERRIDE_NONE = 1 << 0, // no animation
|
||||
ANIMOVERRIDE_LOOP = 1 << 1, // animation loops, otherwise it stays on the last frame once it ends
|
||||
};
|
||||
|
||||
struct AnimOverride
|
||||
{
|
||||
int firstFrame;
|
||||
int lastFrame;
|
||||
int loopFrame;
|
||||
double startFrame;
|
||||
int flags = ANIMOVERRIDE_NONE;
|
||||
float framerate;
|
||||
double startTic; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation)
|
||||
double switchOffset; // when the animation was changed -- where to interpolate the switch from
|
||||
};
|
||||
|
||||
struct ModelOverride
|
||||
{
|
||||
int modelID;
|
||||
|
|
@ -753,8 +735,8 @@ public:
|
|||
int overrideFlagsSet;
|
||||
int overrideFlagsClear;
|
||||
|
||||
AnimOverride curAnim;
|
||||
AnimOverride prevAnim; // used for interpolation when switching anims
|
||||
ModelAnim curAnim;
|
||||
ModelAnimFrame prevAnim; // used for interpolation when switching anims
|
||||
|
||||
DActorModelData() = default;
|
||||
virtual void Serialize(FSerializer& arc) override;
|
||||
|
|
|
|||
|
|
@ -5128,8 +5128,6 @@ enum ESetAnimationFlags
|
|||
SAF_NOOVERRIDE = 1 << 2,
|
||||
};
|
||||
|
||||
extern double getCurrentFrame(const AnimOverride &anim, double tic);
|
||||
|
||||
void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags, double ticFrac)
|
||||
{
|
||||
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
|
||||
|
|
@ -5150,7 +5148,7 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(animName == NAME_None)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -5165,12 +5163,12 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
int animStart = mdl->FindFirstFrame(animName);
|
||||
if(animStart == FErr_NotFound)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("Could not find animation %s\n", animName.GetChars());
|
||||
return;
|
||||
}
|
||||
|
||||
if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != ANIMOVERRIDE_NONE && self->modelData->curAnim.firstFrame == animStart)
|
||||
if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != MODELANIM_NONE && self->modelData->curAnim.firstFrame == animStart)
|
||||
{
|
||||
//same animation as current, skip setting it
|
||||
return;
|
||||
|
|
@ -5178,7 +5176,48 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(!(flags & SAF_INSTANT))
|
||||
{
|
||||
self->modelData->prevAnim = self->modelData->curAnim;
|
||||
if(self->modelData->curAnim.startTic > tic)
|
||||
{
|
||||
ModelAnimFrameInterp to;
|
||||
float inter;
|
||||
|
||||
calcFrames(self->modelData->curAnim, tic, to, inter);
|
||||
|
||||
const TArray<TRS>* animationData = nullptr;
|
||||
|
||||
int animationid = -1;
|
||||
|
||||
const FSpriteModelFrame * smf = &BaseSpriteModelFrames[self->GetClass()];
|
||||
|
||||
if (self->modelData->animationIDs.Size() > 0 && self->modelData->animationIDs[0] >= 0)
|
||||
{
|
||||
animationid = self->modelData->animationIDs[0];
|
||||
}
|
||||
else if(smf->modelsAmount > 0)
|
||||
{
|
||||
animationid = smf->animationIDs[0];
|
||||
}
|
||||
|
||||
FModel* animation = mdl;
|
||||
|
||||
if (animationid >= 0)
|
||||
{
|
||||
animation = Models[animationid];
|
||||
animationData = animation->AttachAnimationData();
|
||||
}
|
||||
|
||||
self->modelData->prevAnim = animation->PrecalculateFrame(self->modelData->prevAnim, to, inter, animationData, self->boneComponentData, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->modelData->prevAnim = ModelAnimFrameInterp{};
|
||||
|
||||
calcFrame(self->modelData->curAnim, tic, std::get<ModelAnimFrameInterp>(self->modelData->prevAnim));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->modelData->prevAnim = nullptr;
|
||||
}
|
||||
|
||||
int animEnd = mdl->FindLastFrame(animName);
|
||||
|
|
@ -5192,19 +5231,19 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(startFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (startFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
else if(loopFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (loopFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
else if(endFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (endFrame) is past the end of animation %s\n", endFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
|
|
@ -5213,14 +5252,12 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
self->modelData->curAnim.lastFrame = endFrame < 0 ? animEnd - 1 : animStart + endFrame;
|
||||
self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame;
|
||||
self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame;
|
||||
self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0;
|
||||
self->modelData->curAnim.flags = (flags & SAF_LOOP) ? MODELANIM_LOOP : 0;
|
||||
self->modelData->curAnim.framerate = (float)framerate;
|
||||
|
||||
if(!(flags & SAF_INSTANT))
|
||||
{
|
||||
self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic);
|
||||
|
||||
int startTic = floor(tic) + interpolateTics;
|
||||
int startTic = int(floor(tic)) + interpolateTics;
|
||||
self->modelData->curAnim.startTic = startTic;
|
||||
self->modelData->curAnim.switchOffset = startTic - tic;
|
||||
}
|
||||
|
|
@ -5252,7 +5289,7 @@ void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFr
|
|||
|
||||
EnsureModelData(self);
|
||||
|
||||
if(self->modelData->curAnim.flags & ANIMOVERRIDE_NONE) return;
|
||||
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
|
||||
|
||||
if(framerate < 0)
|
||||
{
|
||||
|
|
@ -5272,7 +5309,7 @@ void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFr
|
|||
return;
|
||||
}
|
||||
|
||||
double frame = getCurrentFrame(self->modelData->curAnim, tic);
|
||||
double frame = getCurrentFrame(self->modelData->curAnim, tic, nullptr);
|
||||
|
||||
self->modelData->curAnim.startFrame = frame;
|
||||
self->modelData->curAnim.startTic = tic;
|
||||
|
|
|
|||
|
|
@ -1443,7 +1443,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, AnimModelOverride &amo
|
|||
return arc;
|
||||
}
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def)
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelAnim &ao, struct ModelAnim *def)
|
||||
{
|
||||
arc.BeginObject(key);
|
||||
arc("firstFrame", ao.firstFrame);
|
||||
|
|
@ -1458,6 +1458,64 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &a
|
|||
return arc;
|
||||
}
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def)
|
||||
{
|
||||
arc.BeginObject(key);
|
||||
if(arc.isReading())
|
||||
{
|
||||
if(arc.HasKey("firstFrame"))
|
||||
{ // legacy save, clear interpolation
|
||||
ao = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString type = "nullptr";
|
||||
arc("type", type);
|
||||
if(type.Compare("nullptr") == 0)
|
||||
{
|
||||
ao = nullptr;
|
||||
}
|
||||
else if(type.Compare("interp") == 0)
|
||||
{
|
||||
ModelAnimFrameInterp tmp;
|
||||
arc("inter", tmp.inter);
|
||||
arc("frame1", tmp.frame1);
|
||||
arc("frame2", tmp.frame2);
|
||||
ao = tmp;
|
||||
}
|
||||
else if(type.Compare("precalcIQM") == 0)
|
||||
{
|
||||
//TODO, unreachable
|
||||
ao = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // if(arc.isWriting())
|
||||
{
|
||||
if(std::holds_alternative<std::nullptr_t>(ao))
|
||||
{
|
||||
FString tmp = "nullptr";
|
||||
arc("type", tmp);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFrameInterp>(ao))
|
||||
{
|
||||
FString type = "interp";
|
||||
arc("type", type);
|
||||
arc("inter", std::get<ModelAnimFrameInterp>(ao).inter);
|
||||
arc("frame1", std::get<ModelAnimFrameInterp>(ao).frame1);
|
||||
arc("frame2", std::get<ModelAnimFrameInterp>(ao).frame2);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFramePrecalculatedIQM>(ao))
|
||||
{
|
||||
//TODO
|
||||
FString type = "nullptr";
|
||||
arc("type", type);
|
||||
}
|
||||
}
|
||||
arc.EndObject();
|
||||
return arc;
|
||||
}
|
||||
|
||||
void DActorModelData::Serialize(FSerializer& arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
|
@ -3862,7 +3920,7 @@ void AActor::Tick ()
|
|||
special2++;
|
||||
}
|
||||
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
modelData->curAnim.startTic += 1;
|
||||
}
|
||||
|
|
@ -3915,7 +3973,7 @@ void AActor::Tick ()
|
|||
special2++;
|
||||
}
|
||||
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
modelData->curAnim.startTic += 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
|
|||
renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags);
|
||||
}
|
||||
|
||||
double getCurrentFrame(const AnimOverride &anim, double tic)
|
||||
double getCurrentFrame(const ModelAnim &anim, double tic, bool *looped)
|
||||
{
|
||||
if(anim.framerate <= 0) return anim.startFrame;
|
||||
|
||||
|
|
@ -283,8 +283,9 @@ double getCurrentFrame(const AnimOverride &anim, double tic)
|
|||
|
||||
double duration = double(anim.lastFrame) - anim.startFrame;
|
||||
|
||||
if((anim.flags & ANIMOVERRIDE_LOOP) && frame >= duration)
|
||||
if((anim.flags & MODELANIM_LOOP) && frame >= duration)
|
||||
{
|
||||
if(looped) *looped = true;
|
||||
frame = frame - duration;
|
||||
return fmod(frame, anim.lastFrame - anim.loopFrame) + anim.loopFrame;
|
||||
}
|
||||
|
|
@ -294,15 +295,37 @@ double getCurrentFrame(const AnimOverride &anim, double tic)
|
|||
}
|
||||
}
|
||||
|
||||
static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &prev, int &next)
|
||||
void calcFrame(const ModelAnim &anim, double tic, ModelAnimFrameInterp &inter)
|
||||
{
|
||||
double frame = getCurrentFrame(anim, tic);
|
||||
bool looped = false;
|
||||
|
||||
prev = int(floor(frame));
|
||||
double frame = getCurrentFrame(anim, tic, &looped);
|
||||
|
||||
inter = frame - prev;
|
||||
inter.frame1 = int(floor(frame));
|
||||
|
||||
next = int(ceil(frame));
|
||||
inter.inter = frame - inter.frame1;
|
||||
|
||||
inter.frame2 = int(ceil(frame));
|
||||
|
||||
int startFrame = (looped ? anim.loopFrame : anim.startFrame);
|
||||
|
||||
if(inter.frame1 < startFrame) inter.frame1 = anim.lastFrame;
|
||||
if(inter.frame2 > anim.lastFrame) inter.frame2 = startFrame;
|
||||
}
|
||||
|
||||
void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to, float &inter)
|
||||
{
|
||||
if(curAnim.startTic > tic)
|
||||
{
|
||||
inter = (tic - (curAnim.startTic - curAnim.switchOffset)) / curAnim.switchOffset;
|
||||
|
||||
calcFrame(curAnim, curAnim.startTic, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
inter = -1.0f;
|
||||
calcFrame(curAnim, tic, to);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
||||
|
|
@ -313,17 +336,11 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
int smf_flags = smf->getFlags(actor->modelData);
|
||||
|
||||
const FSpriteModelFrame * smfNext = nullptr;
|
||||
double inter = 0.;
|
||||
double inter_main = -1.f;
|
||||
double inter_next = -1.f;
|
||||
float inter = 0.;
|
||||
|
||||
bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS);
|
||||
|
||||
int decoupled_main_prev_frame = -1;
|
||||
int decoupled_next_prev_frame = -1;
|
||||
|
||||
int decoupled_main_frame = -1;
|
||||
int decoupled_next_frame = -1;
|
||||
ModelAnimFrameInterp decoupled_frame;
|
||||
|
||||
// if prev_frame == -1: interpolate(main_frame, next_frame, inter), else: interpolate(interpolate(main_prev_frame, main_frame, inter_main), interpolate(next_prev_frame, next_frame, inter_next), inter)
|
||||
// 4-way interpolation is needed to interpolate animation switches between animations that aren't 35hz
|
||||
|
|
@ -331,33 +348,15 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
if(is_decoupled)
|
||||
{
|
||||
smfNext = smf = &BaseSpriteModelFrames[actor->GetClass()];
|
||||
if(actor->modelData && !(actor->modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(actor->modelData && !(actor->modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
double tic = actor->Level->totaltime;
|
||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
|
||||
{
|
||||
tic += I_GetTimeFrac();
|
||||
}
|
||||
if(actor->modelData->curAnim.startTic > tic)
|
||||
{
|
||||
inter = (tic - (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchOffset)) / actor->modelData->curAnim.switchOffset;
|
||||
|
||||
double nextFrame = actor->modelData->curAnim.startFrame;
|
||||
|
||||
double prevFrame = actor->modelData->prevAnim.startFrame;
|
||||
|
||||
decoupled_next_prev_frame = floor(nextFrame);
|
||||
decoupled_next_frame = ceil(nextFrame);
|
||||
inter_next = nextFrame - floor(nextFrame);
|
||||
|
||||
decoupled_main_prev_frame = floor(prevFrame);
|
||||
decoupled_main_frame = ceil(prevFrame);
|
||||
inter_main = prevFrame - floor(prevFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
calcFrame(actor->modelData->curAnim, tic, inter, decoupled_main_frame, decoupled_next_frame);
|
||||
}
|
||||
calcFrames(actor->modelData->curAnim, tic, decoupled_frame, inter);
|
||||
}
|
||||
}
|
||||
else if (gl_interpolate_model_frames && !(smf_flags & MDL_NOINTERPOLATION))
|
||||
|
|
@ -548,43 +547,30 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
}
|
||||
|
||||
// [RL0] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS
|
||||
if ((!(smf_flags & MDL_MODELSAREATTACHMENTS) && !is_decoupled) || !evaluatedSingle)
|
||||
if(!evaluatedSingle)
|
||||
{
|
||||
FModel* animation = mdl;
|
||||
const TArray<TRS>* animationData = nullptr;
|
||||
|
||||
if (animationid >= 0)
|
||||
{
|
||||
FModel* animation = Models[animationid];
|
||||
animation = Models[animationid];
|
||||
const TArray<TRS>* animationData = animation->AttachAnimationData();
|
||||
}
|
||||
|
||||
if(is_decoupled)
|
||||
if(is_decoupled)
|
||||
{
|
||||
if(decoupled_frame.frame1 != -1)
|
||||
{
|
||||
if(decoupled_main_frame != -1)
|
||||
{
|
||||
boneData = animation->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
boneData = animation->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
boneData = animation->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1);
|
||||
evaluatedSingle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_decoupled)
|
||||
{
|
||||
if(decoupled_main_frame != -1)
|
||||
{
|
||||
boneData = mdl->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, nullptr, actor->boneComponentData, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boneData = mdl->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, nullptr, actor->boneComponentData, i);
|
||||
}
|
||||
boneStartingPosition = renderer->SetupFrame(mdl, 0, 0, 0, boneData, -1);
|
||||
evaluatedSingle = true;
|
||||
boneData = animation->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1);
|
||||
evaluatedSingle = (smf_flags & MDL_MODELSAREATTACHMENTS) || is_decoupled;
|
||||
}
|
||||
|
||||
mdl->RenderFrame(renderer, tex, modelframe, nextFrame ? modelframenext : modelframe, nextFrame ? inter : -1.f, translation, ssidp, boneData, boneStartingPosition);
|
||||
|
|
|
|||
|
|
@ -460,8 +460,8 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
|||
|
||||
const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera :
|
||||
gl_billboard_faces_camera
|
||||
&& ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) || (actor->renderflags2 & RF2_BILLBOARDFACECAMERA)))
|
||||
|| (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) || (particle->flags & SPF_FACECAMERA))));
|
||||
|| ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) && (actor->renderflags2 & RF2_BILLBOARDFACECAMERA)))
|
||||
|| (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA))));
|
||||
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE);
|
||||
|
|
@ -481,7 +481,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
|||
float yy = -center.Y + y;
|
||||
float zz = -center.Z + z;
|
||||
// [Nash] check for special sprite drawing modes
|
||||
if (drawWithXYBillboard || isWallSprite)
|
||||
if (drawWithXYBillboard || drawBillboardFacingCamera || isWallSprite)
|
||||
{
|
||||
mat.MakeIdentity();
|
||||
mat.Translate(center.X, center.Z, center.Y); // move to sprite center
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
*dest = source0[sample_index];
|
||||
*dest |= 0xff000000;
|
||||
dest += pitch;
|
||||
frac += fracstep;
|
||||
}
|
||||
|
|
@ -90,6 +91,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
uint32_t fg = source0[sample_index];
|
||||
fg |= 0xff000000;
|
||||
|
||||
uint32_t alpha = max(min(frac >> (16 - start_fade), 256), 0);
|
||||
uint32_t inv_alpha = 256 - alpha;
|
||||
|
|
@ -110,6 +112,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
*dest = source0[sample_index];
|
||||
*dest |= 0xff000000;
|
||||
|
||||
frac += fracstep;
|
||||
dest += pitch;
|
||||
|
|
@ -121,6 +124,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
uint32_t fg = source0[sample_index];
|
||||
fg |= 0xff000000;
|
||||
|
||||
uint32_t alpha = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
|
||||
uint32_t inv_alpha = 256 - alpha;
|
||||
|
|
@ -189,6 +193,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
*dest = fg;
|
||||
|
|
@ -222,6 +227,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
uint32_t alpha = max(min(frac >> (16 - start_fade), 256), 0);
|
||||
|
|
@ -245,6 +251,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
*dest = fg;
|
||||
|
||||
|
|
@ -262,6 +269,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
uint32_t alpha = max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
*dest = source0[sample_index];
|
||||
*dest |= 0xff000000;
|
||||
dest += pitch;
|
||||
frac += fracstep;
|
||||
}
|
||||
|
|
@ -90,6 +91,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
uint32_t fg = source0[sample_index];
|
||||
fg |= 0xff000000;
|
||||
|
||||
__m128i alpha = _mm_set1_epi16(max(min(frac >> (16 - start_fade), 256), 0));
|
||||
__m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha);
|
||||
|
|
@ -108,6 +110,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
*dest = source0[sample_index];
|
||||
*dest |= 0xff000000;
|
||||
|
||||
frac += fracstep;
|
||||
dest += pitch;
|
||||
|
|
@ -119,6 +122,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index = (((((uint32_t)frac) << 8) >> FRACBITS) * textureheight0) >> FRACBITS;
|
||||
uint32_t fg = source0[sample_index];
|
||||
fg |= 0xff000000;
|
||||
|
||||
__m128i alpha = _mm_set1_epi16(max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0));
|
||||
__m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha);
|
||||
|
|
@ -173,6 +177,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
*dest = fg;
|
||||
|
|
@ -218,6 +223,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
__m128i alpha = _mm_set1_epi16(max(min(frac >> (16 - start_fade), 256), 0));
|
||||
|
|
@ -241,6 +247,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
*dest = fg;
|
||||
|
||||
|
|
@ -258,6 +265,7 @@ namespace swrenderer
|
|||
{
|
||||
uint32_t sample_index2 = min(sample_index, maxtextureheight1);
|
||||
fg = source1[sample_index2];
|
||||
fg |= 0xff000000;
|
||||
}
|
||||
|
||||
__m128i alpha = _mm_set1_epi16(max(min(((2 << 24) - frac) >> (16 - start_fade), 256), 0));
|
||||
|
|
|
|||
|
|
@ -657,6 +657,7 @@ struct Font native
|
|||
native BrokenLines BreakLines(String text, int maxlen);
|
||||
native int GetGlyphHeight(int code);
|
||||
native int GetDefaultKerning();
|
||||
native TextureID, int GetChar(int c);
|
||||
}
|
||||
|
||||
struct Console native
|
||||
|
|
|
|||
|
|
@ -188,11 +188,12 @@ class ListMenu : Menu
|
|||
override bool MenuEvent (int mkey, bool fromcontroller)
|
||||
{
|
||||
int oldSelect = mDesc.mSelectedItem;
|
||||
int startedAt = max(0, mDesc.mSelectedItem);
|
||||
int startedAt;
|
||||
|
||||
switch (mkey)
|
||||
{
|
||||
case MKEY_Up:
|
||||
startedAt = mDesc.mSelectedItem < 0 ? 0 : mDesc.mSelectedItem;
|
||||
do
|
||||
{
|
||||
if (--mDesc.mSelectedItem < 0) mDesc.mSelectedItem = mDesc.mItems.Size()-1;
|
||||
|
|
@ -203,6 +204,7 @@ class ListMenu : Menu
|
|||
return true;
|
||||
|
||||
case MKEY_Down:
|
||||
startedAt = mDesc.mSelectedItem < 0 ? mDesc.mItems.Size()-1 : mDesc.mSelectedItem;
|
||||
do
|
||||
{
|
||||
if (++mDesc.mSelectedItem >= mDesc.mItems.Size()) mDesc.mSelectedItem = 0;
|
||||
|
|
|
|||
|
|
@ -483,8 +483,8 @@ class SaveMenu : LoadSaveMenu
|
|||
{
|
||||
Super.Init(parent, desc);
|
||||
manager.InsertNewSaveNode();
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
UpdateSaveComment();
|
||||
}
|
||||
|
||||
|
|
@ -623,8 +623,8 @@ class LoadMenu : LoadSaveMenu
|
|||
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||
{
|
||||
Super.Init(parent, desc);
|
||||
TopItem = 0;
|
||||
Selected = manager.ExtractSaveData (-1);
|
||||
TopItem = MAX(0, Selected - listboxRows + 1);
|
||||
UpdateSaveComment();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ IWad
|
|||
"DMENUPIC", "M_ACPT", "M_CAN", "M_EXITO", "M_CHG"
|
||||
BannerColors = "54 54 54", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -356,6 +357,7 @@ IWad
|
|||
Load = "extras.wad"
|
||||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -374,6 +376,7 @@ IWad
|
|||
Load = "extras.wad", "soundtrack"
|
||||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -388,6 +391,7 @@ IWad
|
|||
MustContain = "SMOOSHED", "ANIMDEFS", "LANGUAGE", "MAPINFO", "ENDOOM", "M_DOOM", "TITLEPIC", "TEXTURES"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -404,6 +408,7 @@ IWad
|
|||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2", "E1M10", "SEWERS"
|
||||
BannerColors = "18 18 18", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -420,6 +425,7 @@ IWad
|
|||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2"
|
||||
BannerColors = "54 54 54", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -436,6 +442,7 @@ IWad
|
|||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1"
|
||||
BannerColors = "54 54 54", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -449,6 +456,7 @@ IWad
|
|||
MustContain = "E1M1"
|
||||
BannerColors = "54 54 54", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -463,6 +471,7 @@ IWad
|
|||
MustContain = "MAP01", "REDTNT2", "DMAPINFO"
|
||||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -478,6 +487,7 @@ IWad
|
|||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
Load = "extras.wad"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -492,6 +502,7 @@ IWad
|
|||
MustContain = "MAP01", "REDTNT2"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -506,6 +517,7 @@ IWad
|
|||
MustContain = "MAP01", "CAMO1", "DMAPINFO"
|
||||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -521,6 +533,7 @@ IWad
|
|||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
Load = "extras.wad"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -535,6 +548,7 @@ IWad
|
|||
MustContain = "MAP01", "CAMO1"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -550,6 +564,7 @@ IWad
|
|||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
Load = "nerve.wad"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -565,6 +580,7 @@ IWad
|
|||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
Load = "extras.wad"
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -580,6 +596,7 @@ IWad
|
|||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
Load = "nerveunity.wad", "extras.wad", "soundtrack"
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -596,6 +613,7 @@ IWad
|
|||
IgnoreTitlePatches = 1
|
||||
Load = "nerve.wad"
|
||||
DeleteLumps = "M_EPI1", "M_EPI2", "M_EPISOD"
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
IWad
|
||||
|
|
@ -609,6 +627,7 @@ IWad
|
|||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01", "WIOBJ"
|
||||
BannerColors = "ff ff ff", "a8 00 00"
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
// Doom 2 must be last to be checked because MAP01 is its only requirement
|
||||
|
|
@ -624,6 +643,7 @@ IWad
|
|||
MustContain = "MAP01"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
SupportWAD = "id24res.wad"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue