Merge branch 'master' into timidity++

# Conflicts:
#	src/sound/musicformats/music_midistream.cpp
This commit is contained in:
Christoph Oelckers 2018-03-02 00:08:12 +01:00
commit 4c0f68bcd4
41 changed files with 430 additions and 132 deletions

View file

@ -886,6 +886,12 @@ public:
// a full 3D version of the above
double Distance3DSquared(AActor *other, bool absolute = false)
{
DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
return (Pos() - otherpos).LengthSquared();
}
double Distance3D(AActor *other, bool absolute = false)
{
DVector3 otherpos = absolute ? other->Pos() : other->PosRelative(this);

View file

@ -92,6 +92,7 @@ enum
CP_SETTHINGSKILLS,
CP_SETSECTORTEXTURE,
CP_SETSECTORLIGHT,
CP_SETLINESECTORREF,
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -283,6 +284,18 @@ void ParseCompatibility()
CompatParams.Push(sc.Number);
}
}
else if (sc.Compare("setlinesectorref"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
CompatParams.Push(CP_SETLINESECTORREF);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
sc.MustGetString();
CompatParams.Push(sc.MustMatchString(LineSides));
sc.MustGetNumber();
CompatParams.Push(sc.Number);
flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES;
}
else if (sc.Compare("clearlinespecial"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
@ -719,6 +732,22 @@ void SetCompatibilityParams()
i += 3;
break;
}
case CP_SETLINESECTORREF:
{
if ((unsigned)CompatParams[i + 1] < level.lines.Size())
{
line_t *line = &level.lines[CompatParams[i + 1]];
assert(line != nullptr);
side_t *side = line->sidedef[CompatParams[i + 2]];
if (side != nullptr && (unsigned)CompatParams[i + 3] < level.sectors.Size())
{
side->sector = &level.sectors[CompatParams[i + 3]];
}
}
i += 4;
break;
}
}
}
}

View file

@ -2840,14 +2840,14 @@ static bool LoadDehSupp ()
sc.MustGetString();
PClassActor *actortype = static_cast<PClassActor *>(type);
s.State = actortype->FindState(sc.String);
if (s.State == NULL)
if (s.State == NULL && addit)
{
sc.ScriptError("Invalid state '%s' in '%s'", sc.String, type->TypeName.GetChars());
}
sc.MustGetStringName(",");
sc.MustGetNumber();
if (s.State == NULL || sc.Number < 1 || !actortype->OwnsState(s.State + sc.Number - 1))
if (addit && (s.State == NULL || sc.Number < 1 || !actortype->OwnsState(s.State + sc.Number - 1)))
{
sc.ScriptError("Invalid state range in '%s'", type->TypeName.GetChars());
}

View file

@ -40,15 +40,18 @@
#include "cmdlib.h"
#include "doomstat.h"
#include "serializer.h"
#include "vm.h"
EXTERN_CVAR(Int, con_scaletext)
IMPLEMENT_CLASS(DHUDMessage, false, true)
IMPLEMENT_POINTERS_START(DHUDMessage)
IMPLEMENT_POINTER(Next)
IMPLEMENT_CLASS(DHUDMessageBase, true, true)
IMPLEMENT_POINTERS_START(DHUDMessageBase)
IMPLEMENT_POINTER(Next)
IMPLEMENT_POINTERS_END
IMPLEMENT_CLASS(DHUDMessage, false, false)
IMPLEMENT_CLASS(DHUDMessageFadeOut, false, false)
IMPLEMENT_CLASS(DHUDMessageFadeInOut, false, false)
IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, false, false)
@ -57,6 +60,68 @@ IMPLEMENT_CLASS(DHUDMessageTypeOnFadeOut, false, false)
* Basic HUD message. Appears and disappears without any special effects *
*************************************************************************/
void DHUDMessageBase::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc("next", Next)
("sbarid", SBarID);
}
DEFINE_ACTION_FUNCTION(DHUDMessageBase, Tick)
{
PARAM_SELF_PROLOGUE(DHUDMessageBase);
ACTION_RETURN_BOOL(self->Tick());
}
DEFINE_ACTION_FUNCTION(DHUDMessageBase, ScreenSizeChanged)
{
PARAM_SELF_PROLOGUE(DHUDMessageBase);
self->ScreenSizeChanged();
return 0;
}
DEFINE_ACTION_FUNCTION(DHUDMessageBase, Draw)
{
PARAM_SELF_PROLOGUE(DHUDMessageBase);
PARAM_INT(bottom);
PARAM_INT(visibility);
self->Draw(bottom, visibility);
return 0;
}
bool DHUDMessageBase::CallTick()
{
IFVIRTUAL(DHUDMessageBase, Tick)
{
VMValue params[] = { (DObject*)this };
int retval;
VMReturn ret; ret.IntAt(&retval);
VMCall(func, params, countof(params), &ret, 1);
return !!retval;
}
return Tick();
}
void DHUDMessageBase::CallScreenSizeChanged()
{
IFVIRTUAL(DHUDMessageBase, ScreenSizeChanged)
{
VMValue params[] = { (DObject*)this };
VMCall(func, params, countof(params), nullptr, 0);
}
else ScreenSizeChanged();
}
void DHUDMessageBase::CallDraw(int bottom, int visibility)
{
IFVIRTUAL(DHUDMessageBase, Draw)
{
VMValue params[] = { (DObject*)this, bottom, visibility };
VMCall(func, params, countof(params), nullptr, 0);
}
else Draw(bottom, visibility);
}
//============================================================================
//
// DHUDMessage Constructor
@ -130,7 +195,6 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
WrapWidth = 0;
HandleAspect = true;
Top = y;
Next = NULL;
Lines = NULL;
HoldTics = (int)(holdTime * TICRATE);
Tics = 0;
@ -184,10 +248,8 @@ void DHUDMessage::Serialize(FSerializer &arc)
("tics", Tics)
("state", State)
.Enum("textcolor", TextColor)
("sbarid", SBarID)
("sourcetext", SourceText)
("font", Font)
("next", Next)
("hudwidth", HUDWidth)
("hudheight", HUDHeight)
("nowrap", NoWrap)

View file

@ -59,10 +59,34 @@ bool ST_IsLatencyVisible();
// HUD Message base object --------------------------------------------------
class DHUDMessage : public DObject
// This is a mo-op base class to allow derived ZScript message types that can be managed by the status bar.
class DHUDMessageBase : public DObject
{
DECLARE_CLASS (DHUDMessage, DObject)
DECLARE_CLASS(DHUDMessageBase, DObject)
HAS_OBJECT_POINTERS
public:
virtual void Serialize(FSerializer &arc);
virtual bool Tick() { return true; } // Returns true to indicate time for removal
virtual void ScreenSizeChanged() {}
virtual void Draw(int bottom, int visibility) {}
bool CallTick(); // Returns true to indicate time for removal
void CallScreenSizeChanged();
void CallDraw(int bottom, int visibility);
private:
TObjPtr<DHUDMessageBase*> Next = nullptr;
uint32_t SBarID = 0;
friend class DBaseStatusBar;
};
// HUD Message --------------------------------------------------
class DHUDMessage : public DHUDMessageBase
{
DECLARE_CLASS (DHUDMessage, DHUDMessageBase)
public:
DHUDMessage (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime);
@ -70,12 +94,12 @@ public:
virtual void Serialize(FSerializer &arc);
void Draw (int bottom, int visibility);
virtual void Draw (int bottom, int visibility) override;
virtual void ResetText (const char *text);
virtual void DrawSetup ();
virtual void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick (); // Returns true to indicate time for removal
virtual void ScreenSizeChanged ();
virtual bool Tick () override;
virtual void ScreenSizeChanged () override;
void SetVisibility(int vis)
{
@ -130,11 +154,8 @@ protected:
DHUDMessage () : SourceText(NULL) {}
private:
TObjPtr<DHUDMessage*> Next;
uint32_t SBarID;
char *SourceText;
friend class DBaseStatusBar;
};
// HUD message visibility flags
@ -360,9 +381,9 @@ public:
void SetSize(int reltop = 32, int hres = 320, int vres = 200, int hhres = -1, int hvres = -1);
void OnDestroy() override;
void AttachMessage (DHUDMessage *msg, uint32_t id=0, int layer=HUDMSGLayer_Default);
DHUDMessage *DetachMessage (DHUDMessage *msg);
DHUDMessage *DetachMessage (uint32_t id);
void AttachMessage (DHUDMessageBase *msg, uint32_t id=0, int layer=HUDMSGLayer_Default);
DHUDMessageBase *DetachMessage (DHUDMessageBase *msg);
DHUDMessageBase *DetachMessage (uint32_t id);
void DetachAllMessages ();
void ShowPlayerName ();
double GetDisplacement() { return Displacement; }
@ -455,7 +476,7 @@ private:
void DrawWaiting () const;
void SetDrawSize(int reltop, int hres, int vres);
TObjPtr<DHUDMessage*> Messages[NUM_HUDMSGLAYERS];
TObjPtr<DHUDMessageBase*> Messages[NUM_HUDMSGLAYERS];
int BaseRelTop;
int BaseSBarHorizontalResolution;

View file

@ -410,10 +410,10 @@ void DBaseStatusBar::OnDestroy ()
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *msg = Messages[i];
DHUDMessageBase *msg = Messages[i];
while (msg)
{
DHUDMessage *next = msg->Next;
DHUDMessageBase *next = msg->Next;
msg->Destroy();
msg = next;
}
@ -594,14 +594,14 @@ void DBaseStatusBar::Tick ()
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *msg = Messages[i];
DHUDMessage **prev = &Messages[i];
DHUDMessageBase *msg = Messages[i];
DHUDMessageBase **prev = &Messages[i];
while (msg)
{
DHUDMessage *next = msg->Next;
DHUDMessageBase *next = msg->Next;
if (msg->Tick ())
if (msg->CallTick ())
{
*prev = next;
msg->Destroy();
@ -662,10 +662,10 @@ void DBaseStatusBar::CallTick()
//
//---------------------------------------------------------------------------
void DBaseStatusBar::AttachMessage (DHUDMessage *msg, uint32_t id, int layer)
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
{
DHUDMessage *old = NULL;
DHUDMessage **prev;
DHUDMessageBase *old = NULL;
DHUDMessageBase **prev;
DObject *container = this;
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
@ -697,18 +697,28 @@ void DBaseStatusBar::AttachMessage (DHUDMessage *msg, uint32_t id, int layer)
GC::WriteBarrier(container, msg);
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, AttachMessage)
{
PARAM_SELF_PROLOGUE(DBaseStatusBar);
PARAM_OBJECT(msg, DHUDMessageBase);
PARAM_UINT(id);
PARAM_INT(layer);
self->AttachMessage(msg, id, layer);
return 0;
}
//---------------------------------------------------------------------------
//
// PROC DetachMessage
//
//---------------------------------------------------------------------------
DHUDMessage *DBaseStatusBar::DetachMessage (DHUDMessage *msg)
DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *probe = Messages[i];
DHUDMessage **prev = &Messages[i];
DHUDMessageBase *probe = Messages[i];
DHUDMessageBase **prev = &Messages[i];
while (probe && probe != msg)
{
@ -725,12 +735,20 @@ DHUDMessage *DBaseStatusBar::DetachMessage (DHUDMessage *msg)
return NULL;
}
DHUDMessage *DBaseStatusBar::DetachMessage (uint32_t id)
DEFINE_ACTION_FUNCTION(DBaseStatusBar, DetachMessage)
{
PARAM_SELF_PROLOGUE(DBaseStatusBar);
PARAM_OBJECT(msg, DHUDMessageBase);
ACTION_RETURN_OBJECT(self->DetachMessage(msg));
}
DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *probe = Messages[i];
DHUDMessage **prev = &Messages[i];
DHUDMessageBase *probe = Messages[i];
DHUDMessageBase **prev = &Messages[i];
while (probe && probe->SBarID != id)
{
@ -747,6 +765,13 @@ DHUDMessage *DBaseStatusBar::DetachMessage (uint32_t id)
return NULL;
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, DetachMessageID)
{
PARAM_SELF_PROLOGUE(DBaseStatusBar);
PARAM_INT(id);
ACTION_RETURN_OBJECT(self->DetachMessage(id));
}
//---------------------------------------------------------------------------
//
// PROC DetachAllMessages
@ -757,18 +782,26 @@ void DBaseStatusBar::DetachAllMessages ()
{
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *probe = Messages[i];
DHUDMessageBase *probe = Messages[i];
Messages[i] = NULL;
while (probe != NULL)
{
DHUDMessage *next = probe->Next;
DHUDMessageBase *next = probe->Next;
probe->Destroy();
probe = next;
}
}
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, DetachAllMessages)
{
PARAM_SELF_PROLOGUE(DBaseStatusBar);
self->DetachAllMessages();
return 0;
}
//---------------------------------------------------------------------------
//
// PROC ShowPlayerName
@ -940,7 +973,7 @@ void DBaseStatusBar::FlashCrosshair ()
void DBaseStatusBar::DrawMessages (int layer, int bottom)
{
DHUDMessage *msg = Messages[layer];
DHUDMessageBase *msg = Messages[layer];
int visibility = 0;
if (viewactive)
@ -953,8 +986,8 @@ void DBaseStatusBar::DrawMessages (int layer, int bottom)
}
while (msg)
{
DHUDMessage *next = msg->Next;
msg->Draw (bottom, visibility);
DHUDMessageBase *next = msg->Next;
msg->CallDraw (bottom, visibility);
msg = next;
}
}
@ -1307,10 +1340,10 @@ void DBaseStatusBar::ScreenSizeChanged ()
for (size_t i = 0; i < countof(Messages); ++i)
{
DHUDMessage *message = Messages[i];
DHUDMessageBase *message = Messages[i];
while (message != NULL)
{
message->ScreenSizeChanged ();
message->CallScreenSizeChanged ();
message = message->Next;
}
}

View file

@ -149,6 +149,7 @@ FGameConfigFile::FGameConfigFile ()
SetValueForKey ("Path", "$PROGDIR", true);
#else
SetValueForKey ("Path", "$HOME/" GAME_DIR, true);
SetValueForKey ("Path", SHARE_DIR, true);
SetValueForKey ("Path", "/usr/local/share/doom", true);
SetValueForKey ("Path", "/usr/local/share/games/doom", true);
SetValueForKey ("Path", "/usr/share/doom", true);

View file

@ -209,9 +209,10 @@ static bool currentModelMatrixState;
void FRenderState::ApplyFixedFunction()
{
if (mTextureMode != ffTextureMode)
int thistm = mTextureMode == TM_MODULATE && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode;
if (thistm != ffTextureMode)
{
ffTextureMode = mTextureMode;
ffTextureMode = thistm;
if (ffTextureMode == TM_CLAMPY) ffTextureMode = TM_MODULATE; // this cannot be replicated. Too bad if it creates visual artifacts
gl_SetTextureMode(ffTextureMode);
}

View file

@ -405,7 +405,6 @@ void F2DDrawer::Draw()
gl_SetRenderStyle(dt->mRenderStyle, !dt->mMasked, false);
gl_RenderState.SetMaterial(dt->mTexture, CLAMP_XY_NOMIP, dt->mTranslation, -1, dt->mAlphaTexture);
if (dt->mTexture->tex->bHasCanvas) gl_RenderState.SetTextureMode(TM_OPAQUE);
glEnable(GL_SCISSOR_TEST);
glScissor(dt->mScissor[0], dt->mScissor[1], dt->mScissor[2], dt->mScissor[3]);

View file

@ -164,7 +164,7 @@ bool FRenderState::ApplyShader()
activeShader->muFogEnabled.Set(fogset);
activeShader->muPalLightLevels.Set(static_cast<int>(gl_bandedswlight) | (static_cast<int>(gl_fogmode) << 8));
activeShader->muGlobVis.Set(GLRenderer->mGlobVis / 32.0f);
activeShader->muTextureMode.Set(mTextureMode);
activeShader->muTextureMode.Set(mTextureMode == TM_MODULATE && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode);
activeShader->muCameraPos.Set(mCameraPos.vec);
activeShader->muLightParms.Set(mLightParms);
activeShader->muFogColor.Set(mFogColor);

View file

@ -112,6 +112,7 @@ class FRenderState
int mEffectState;
int mColormapState;
int mTempTM = TM_MODULATE;
float stAlphaThreshold;
int stSrcBlend, stDstBlend;
@ -150,6 +151,14 @@ public:
{
if (mat->tex->UseBasePalette() || gl.legacyMode) translation = TRANSLATION(TRANSLATION_Standard, 8);
}
if (mat->tex->bHasCanvas)
{
mTempTM = TM_OPAQUE;
}
else
{
mTempTM = TM_MODULATE;
}
mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex;
mShaderTimer = mat->tex->gl_info.shaderspeed;
mat->Bind(clampmode, translation);

View file

@ -358,42 +358,46 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort)
//
//
//==========================================================================
void GLDrawList::SortSpriteIntoPlane(SortNode * head,SortNode * sort)
void GLDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort)
{
GLFlat * fh=&flats[drawitems[head->itemindex].index];
GLSprite * ss=&sprites[drawitems[sort->itemindex].index];
GLFlat * fh = &flats[drawitems[head->itemindex].index];
GLSprite * ss = &sprites[drawitems[sort->itemindex].index];
bool ceiling = fh->z > r_viewpoint.Pos.Z;
if ((ss->z1>fh->z && ss->z2<fh->z) || ss->modelframe)
auto hiz = ss->z1 > ss->z2 ? ss->z1 : ss->z2;
auto loz = ss->z1 < ss->z2 ? ss->z1 : ss->z2;
if ((hiz > fh->z && loz < fh->z) || ss->modelframe)
{
// We have to split this sprite
GLSprite s=*ss;
GLSprite s = *ss;
AddSprite(&s); // add a copy to avoid reallocation issues.
// Splitting is done in the shader with clip planes, if available
// Splitting is done in the shader with clip planes, if available.
// The fallback here only really works for non-y-billboarded sprites.
if (gl.flags & RFL_NO_CLIP_PLANES)
{
GLSprite * ss1;
ss1=&sprites[sprites.Size()-1];
ss=&sprites[drawitems[sort->itemindex].index]; // may have been reallocated!
float newtexv=ss->vt + ((ss->vb-ss->vt)/(ss->z2-ss->z1))*(fh->z-ss->z1);
ss1 = &sprites[sprites.Size() - 1];
ss = &sprites[drawitems[sort->itemindex].index]; // may have been reallocated!
float newtexv = ss->vt + ((ss->vb - ss->vt) / (ss->z2 - ss->z1))*(fh->z - ss->z1);
if (!ceiling)
{
ss->z1=ss1->z2=fh->z;
ss->vt=ss1->vb=newtexv;
ss->z1 = ss1->z2 = fh->z;
ss->vt = ss1->vb = newtexv;
}
else
{
ss1->z1=ss->z2=fh->z;
ss1->vt=ss->vb=newtexv;
ss1->z1 = ss->z2 = fh->z;
ss1->vt = ss->vb = newtexv;
}
}
SortNode * sort2=SortNodes.GetNew();
memset(sort2,0,sizeof(SortNode));
sort2->itemindex=drawitems.Size()-1;
SortNode * sort2 = SortNodes.GetNew();
memset(sort2, 0, sizeof(SortNode));
sort2->itemindex = drawitems.Size() - 1;
head->AddToLeft(sort);
head->AddToRight(sort2);
@ -406,7 +410,6 @@ void GLDrawList::SortSpriteIntoPlane(SortNode * head,SortNode * sort)
{
head->AddToRight(sort);
}
}

View file

@ -1211,7 +1211,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s
}
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze)
if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN))
timefrac = 0.;
float xvf = (particle->Vel.X) * timefrac;
float yvf = (particle->Vel.Y) * timefrac;

View file

@ -1060,8 +1060,8 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
// Draw the stuff
//
//
if (realfront->e->XFloor.lightlist.Size()==0 || mDrawer->FixedColormap) split.PutWall(translucent);
else split.SplitWall(realfront, translucent);
if (front->e->XFloor.lightlist.Size()==0 || mDrawer->FixedColormap) split.PutWall(translucent);
else split.SplitWall(front, translucent);
t=1;
}
@ -1074,8 +1074,8 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
// Draw the stuff without splitting
//
//
if (realfront->e->XFloor.lightlist.Size()==0 || mDrawer->FixedColormap) PutWall(translucent);
else SplitWall(realfront, translucent);
if (front->e->XFloor.lightlist.Size()==0 || mDrawer->FixedColormap) PutWall(translucent);
else SplitWall(front, translucent);
}
alpha=1.0f;
}
@ -1437,7 +1437,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
sector_t * segback;
#ifdef _DEBUG
if (seg->linedef->Index() == 1)
if (seg->linedef->Index() == 10)
{
int a = 0;
}

View file

@ -244,6 +244,7 @@ struct FActorInfo
PClassActor *Replacee = nullptr;
FState *OwnedStates = nullptr;
int NumOwnedStates = 0;
bool SkipSuperSet = false;
uint8_t GameFilter = GAME_Any;
uint16_t SpawnID = 0;
uint16_t ConversationID = 0;
@ -287,7 +288,7 @@ struct FActorInfo
};
// This is now merely a wrapper that adds actor-specific functionality to PClass.
// No objects of this type will be created ever - its only use is to static_casr
// No objects of this type will be created ever - its only use is to static_cast
// PClass to it.
class PClassActor : public PClass
{
@ -343,7 +344,7 @@ public:
bool OwnsState(const FState *state)
{
auto i = ActorInfo();
return state >= i->OwnedStates && state < i->OwnedStates + i->NumOwnedStates;
return i != nullptr && state >= i->OwnedStates && state < i->OwnedStates + i->NumOwnedStates;
}
PClassActor *GetReplacement(bool lookskill=true);

View file

@ -377,6 +377,8 @@ xx(MomZ)
xx(Threshold)
xx(DefThreshold)
xx(Abs)
xx(TeleportSpecial)
xx(Teleport)
xx(ACS_NamedExecuteWithResult)
xx(CallACS)
xx(Sqrt)

View file

@ -814,8 +814,8 @@ void FNodeBuilder::SplitSegs (uint32_t set, node_t &node, uint32_t splitseg, uin
frac = InterceptVector (node, *seg);
newvert.x = Vertices[seg->v1].x;
newvert.y = Vertices[seg->v1].y;
newvert.x += fixed_t(frac * double(Vertices[seg->v2].x - newvert.x));
newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y));
newvert.x += fixed_t(frac * (double(Vertices[seg->v2].x) - newvert.x));
newvert.y += fixed_t(frac * (double(Vertices[seg->v2].y) - newvert.y));
vertnum = VertexMap->SelectVertexClose (newvert);
if (vertnum != (unsigned int)seg->v1 && vertnum != (unsigned int)seg->v2)

View file

@ -91,6 +91,8 @@ struct FSimpleVert
fixed_t x, y;
};
typedef int64_t fixed64_t;
class FNodeBuilder
{
struct FPrivSeg
@ -167,14 +169,14 @@ class FNodeBuilder
FNodeBuilder &MyBuilder;
TArray<int> *VertexGrid;
fixed_t MinX, MinY, MaxX, MaxY;
fixed64_t MinX, MinY, MaxX, MaxY;
int BlocksWide, BlocksTall;
enum { BLOCK_SHIFT = 8 + FRACBITS };
enum { BLOCK_SIZE = 1 << BLOCK_SHIFT };
int InsertVertex (FPrivVert &vert);
inline int GetBlock (fixed_t x, fixed_t y)
inline int GetBlock (fixed64_t x, fixed64_t y)
{
assert (x >= MinX);
assert (y >= MinY);

View file

@ -641,8 +641,8 @@ FNodeBuilder::FVertexMap::FVertexMap (FNodeBuilder &builder,
MinY = miny;
BlocksWide = int(((double(maxx) - minx + 1) + (BLOCK_SIZE - 1)) / BLOCK_SIZE);
BlocksTall = int(((double(maxy) - miny + 1) + (BLOCK_SIZE - 1)) / BLOCK_SIZE);
MaxX = MinX + BlocksWide * BLOCK_SIZE - 1;
MaxY = MinY + BlocksTall * BLOCK_SIZE - 1;
MaxX = MinX + fixed64_t(BlocksWide) * BLOCK_SIZE - 1;
MaxY = MinY + fixed64_t(BlocksTall) * BLOCK_SIZE - 1;
VertexGrid = new TArray<int>[BlocksWide * BlocksTall];
}
@ -703,10 +703,10 @@ int FNodeBuilder::FVertexMap::InsertVertex (FNodeBuilder::FPrivVert &vert)
// If a vertex is near a block boundary, then it will be inserted on
// both sides of the boundary so that SelectVertexClose can find
// it by checking in only one block.
fixed_t minx = MAX (MinX, vert.x - VERTEX_EPSILON);
fixed_t maxx = MIN (MaxX, vert.x + VERTEX_EPSILON);
fixed_t miny = MAX (MinY, vert.y - VERTEX_EPSILON);
fixed_t maxy = MIN (MaxY, vert.y + VERTEX_EPSILON);
fixed64_t minx = MAX (MinX, fixed64_t(vert.x) - VERTEX_EPSILON);
fixed64_t maxx = MIN (MaxX, fixed64_t(vert.x) + VERTEX_EPSILON);
fixed64_t miny = MAX (MinY, fixed64_t(vert.y) - VERTEX_EPSILON);
fixed64_t maxy = MIN (MaxY, fixed64_t(vert.y) + VERTEX_EPSILON);
int blk[4] =
{

View file

@ -898,7 +898,9 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
}
// check if the actor can step through the ceiling portal. In this case one-sided lines in the current area should not block
if (!cres.line->frontsector->PortalBlocksMovement(sector_t::ceiling))
// Use the same rules for stepping through a portal as for non-portal case.
bool ismissile = (tm.thing->flags & MF_MISSILE) && !(tm.thing->flags6 & MF6_STEPMISSILE) && !(tm.thing->flags3 & MF3_FLOORHUGGER);
if (!ismissile && !cres.line->frontsector->PortalBlocksMovement(sector_t::ceiling))
{
double portz = cres.line->frontsector->GetPortalPlaneZ(sector_t::ceiling);
if (tm.thing->Z() < portz && tm.thing->Z() + tm.thing->MaxStepHeight >= portz && tm.floorz < portz)
@ -1008,7 +1010,9 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
FLineOpening open;
P_LineOpening(open, tm.thing, ld, ref, &cres.Position, cres.portalflags);
if (!tm.thing->Sector->PortalBlocksMovement(sector_t::ceiling))
// Use the same rules for stepping through a portal as for non-portal case.
bool ismissile = (tm.thing->flags & MF_MISSILE) && !(tm.thing->flags6 & MF6_STEPMISSILE) && !(tm.thing->flags3 & MF3_FLOORHUGGER);
if (!ismissile && !tm.thing->Sector->PortalBlocksMovement(sector_t::ceiling))
{
sector_t *oppsec = cres.line->frontsector == tm.thing->Sector ? cres.line->backsector : cres.line->frontsector;
if (oppsec->PortalBlocksMovement(sector_t::ceiling))
@ -2707,8 +2711,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
FLinkContext ctx;
DVector3 oldpos = thing->Pos();
thing->UnlinkFromWorld(&ctx);
thing->SetXYZ(thing->PosRelative(thing->Sector->GetOppositePortalGroup(sector_t::ceiling)));
thing->Prev = thing->Pos() - oldpos;
thing->SetXYZ(thing->PosRelative(tm.portalgroup));
thing->Prev += thing->Pos() - oldpos;
thing->Sector = P_PointInSector(thing->Pos());
thing->PrevPortalGroup = thing->Sector->PortalGroup;
thing->LinkToWorld(&ctx);

View file

@ -8127,6 +8127,20 @@ DEFINE_ACTION_FUNCTION(AActor, absangle) // should this be global?
ACTION_RETURN_FLOAT(absangle(DAngle(a1), DAngle(a2)).Degrees);
}
DEFINE_ACTION_FUNCTION(AActor, Distance2DSquared)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT_NOT_NULL(other, AActor);
ACTION_RETURN_FLOAT(self->Distance2DSquared(other));
}
DEFINE_ACTION_FUNCTION(AActor, Distance3DSquared)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT_NOT_NULL(other, AActor);
ACTION_RETURN_FLOAT(self->Distance3DSquared(other));
}
DEFINE_ACTION_FUNCTION(AActor, Distance2D)
{
PARAM_SELF_PROLOGUE(AActor);

View file

@ -35,7 +35,7 @@ EXTERN_CVAR(Int, gl_particles_style)
void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue)
{
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze)
if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN))
timefrac = 0.;
DVector3 pos = particle->Pos + (particle->Vel * timefrac);
double psize = particle->size / 8.0;

View file

@ -125,9 +125,17 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
// Applying model transformations:
// 1) Applying actor angle, pitch and roll to the model
if (smf->flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ, smf->rotationCenterY);
}
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
if (smf->flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ, -smf->rotationCenterY);
}
// 2) Applying Doomsday like rotation of the weapon pickup models
// The rotation angle is based on the elapsed time.
@ -789,6 +797,13 @@ void gl_InitModels()
{
smf.flags |= MDL_DONTCULLBACKFACES;
}
else if (sc.Compare("userotationcenter"))
{
smf.flags |= MDL_USEROTATIONCENTER;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
}
else
{
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);

View file

@ -447,6 +447,7 @@ enum
MDL_USEACTORROLL = 64,
MDL_BADROTATION = 128,
MDL_DONTCULLBACKFACES = 256,
MDL_USEROTATIONCENTER = 512,
};
struct FSpriteModelFrame

View file

@ -677,7 +677,7 @@ void S_UnloadReverbDef ()
Environments = &Off;
}
CUSTOM_CVAR(Bool, eaxedit_test, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
CUSTOM_CVAR(Bool, eaxedit_test, false, CVAR_NOINITCALL)
{
if (self)
{

View file

@ -2304,6 +2304,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build)
}
pointer.Free(build);
value.Target = false; // This is for 'unrequesting' the address of a register variable. If not done here, passing a preincrement expression to a function will generate bad code.
return value;
}
@ -7406,7 +7407,16 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (arrayispointer)
{
arraytype = static_cast<PArray*>(Array->ValueType->toPointer()->PointedType);
auto ptr = Array->ValueType->toPointer();
if (ptr != nullptr)
{
arraytype = static_cast<PArray*>(ptr->PointedType);
}
else
{
ScriptPosition.Message(MSG_ERROR, "Internal error when generating code for array access");
return ExpEmit();
}
}
else
{
@ -7758,6 +7768,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
}
else
{
// This alias is needed because Actor has a Teleport function.
if (MethodName == NAME_TeleportSpecial) MethodName = NAME_Teleport;
special = P_FindLineSpecial(MethodName.GetChars(), &min, &max);
}
if (special != 0 && min >= 0)

View file

@ -540,7 +540,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
if (info->Size != actorclass->Size)
{
bag.ScriptPosition.Message(MSG_OPTERROR,
"'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored in type %s.", info->TypeName.GetChars());
"'skip_super' is only allowed in subclasses of Actor with no additional fields and will be ignored in type %s.", info->TypeName.GetChars());
return;
}
if (bag.StateSet)
@ -552,6 +552,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
*defaults = *GetDefault<AActor>();
ResetBaggage (&bag, RUNTIME_CLASS(AActor));
static_cast<PClassActor*>(bag.Info)->ActorInfo()->SkipSuperSet = true; // ZScript processes the states later so this property must be flagged for later handling.
}
//==========================================================================

View file

@ -1968,7 +1968,10 @@ void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *spe
void PDynArray::WriteValue(FSerializer &ar, const char *key, const void *addr) const
{
FArray *aray = (FArray*)addr;
if (aray->Count > 0)
// We may skip an empty array only if it gets stored under a named key.
// If no name is given, i.e. it's part of an outer array's element list, even empty arrays must be stored,
// because otherwise the array would lose its entry.
if (aray->Count > 0 || key == nullptr)
{
if (ar.BeginArray(key))
{

View file

@ -2872,7 +2872,18 @@ void ZCCCompiler::CompileStates()
FString statename; // The state builder wants the label as one complete string, not separated into tokens.
FStateDefinitions statedef;
statedef.MakeStateDefines(ValidateActor(c->ClassType()->ParentClass));
if (static_cast<PClassActor*>(c->ClassType())->ActorInfo()->SkipSuperSet)
{
// SKIP_SUPER'ed actors only get the base states from AActor.
statedef.MakeStateDefines(RUNTIME_CLASS(AActor));
}
else
{
statedef.MakeStateDefines(ValidateActor(c->ClassType()->ParentClass));
}
int numframes = 0;
for (auto s : c->States)

View file

@ -190,32 +190,32 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype)
{
try
{
switch (devtype)
{
switch (devtype)
{
case MDEV_GUS:
return new TimidityMIDIDevice(Args);
case MDEV_MMAPI:
case MDEV_MMAPI:
#ifdef _WIN32
return CreateWinMIDIDevice(mididevice);
return CreateWinMIDIDevice(mididevice);
#endif
// Intentional fall-through for non-Windows systems.
// Intentional fall-through for non-Windows systems.
case MDEV_FLUIDSYNTH:
return new FluidSynthMIDIDevice(Args);
case MDEV_FLUIDSYNTH:
return new FluidSynthMIDIDevice(Args);
case MDEV_OPL:
return new OPLMIDIDevice(Args);
case MDEV_OPL:
return new OPLMIDIDevice(Args);
case MDEV_TIMIDITY:
return CreateTimidityPPMIDIDevice(Args);
case MDEV_TIMIDITY:
return CreateTimidityPPMIDIDevice(Args);
case MDEV_WILDMIDI:
return new WildMIDIDevice(Args);
case MDEV_WILDMIDI:
return new WildMIDIDevice(Args);
default:
default:
break;
}
}
}
catch (CRecoverableError &err)
{
@ -721,6 +721,14 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, uint32_t max_time)
if (InitialPlayback)
{
InitialPlayback = false;
// Send the GS System Reset SysEx message.
events[0] = 0; // dwDeltaTime
events[1] = 0; // dwStreamID
events[2] = (MEVENT_LONGMSG << 24) | 6; // dwEvent
events[3] = MAKE_ID(0xf0, 0x7e, 0x7f, 0x09); // dwParms[0]
events[4] = MAKE_ID(0x01, 0xf7, 0x00, 0x00); // dwParms[1]
events += 5;
// Send the full master volume SysEx message.
events[0] = 0; // dwDeltaTime
events[1] = 0; // dwStreamID

View file

@ -79,7 +79,7 @@ namespace swrenderer
sector_t* heightsec = NULL;
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze)
if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN))
timefrac = 0.;
double ippx = particle->Pos.X + particle->Vel.X * timefrac;

View file

@ -35,6 +35,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <wctype.h>
#include "v_text.h"
@ -387,7 +388,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo
continue;
}
if (isspace(c))
if (iswspace(c))
{
if (!lastWasSpace)
{
@ -420,12 +421,12 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo
start = space;
space = NULL;
while (*start && isspace (*start) && *start != '\n')
while (*start && iswspace (*start) && *start != '\n')
start++;
if (*start == '\n')
start++;
else
while (*start && isspace (*start))
while (*start && iswspace (*start))
start++;
string = start;
}
@ -443,7 +444,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo
while (s < string)
{
// If there is any non-white space in the remainder of the string, add it.
if (!isspace (*s++))
if (!iswspace (*s++))
{
auto i = Lines.Reserve(1);
breakit (&Lines[i], font, start, string, linecolor);