From 1b80b7bf2f83f6bf6d8681cc1e8b5af57aaa18d7 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 1 Mar 2020 23:45:11 -0500 Subject: [PATCH 01/30] - ported over Nash's startTime for A_StartSound --- src/scripting/vmthunks_actors.cpp | 6 ++++-- src/sound/backend/i_sound.cpp | 6 +++--- src/sound/backend/i_sound.h | 6 +++--- src/sound/backend/oalsound.cpp | 21 ++++++++++++++------ src/sound/backend/oalsound.h | 6 +++--- src/sound/s_doomsound.cpp | 28 ++++++++++++++------------- src/sound/s_doomsound.h | 8 ++++---- src/sound/s_sound.cpp | 6 +++--- src/sound/s_soundinternal.h | 2 +- wadsrc/static/zscript/actors/actor.zs | 4 ++-- 10 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 12cd27676..92d4bb74f 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -179,7 +179,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) PARAM_FLOAT(attenuation); PARAM_BOOL(local); PARAM_FLOAT(pitch); - A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch); + PARAM_FLOAT(startTime); + A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch, startTime); return 0; } @@ -192,7 +193,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; } diff --git a/src/sound/backend/i_sound.cpp b/src/sound/backend/i_sound.cpp index 256163404..f1f0e3c87 100644 --- a/src/sound/backend/i_sound.cpp +++ b/src/sound/backend/i_sound.cpp @@ -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) { } diff --git a/src/sound/backend/i_sound.h b/src/sound/backend/i_sound.h index 0564f7857..573159242 100644 --- a/src/sound/backend/i_sound.h +++ b/src/sound/backend/i_sound.h @@ -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; diff --git a/src/sound/backend/oalsound.cpp b/src/sound/backend/oalsound.cpp index a2848a967..c6c4af18e 100644 --- a/src/sound/backend/oalsound.cpp +++ b/src/sound/backend/oalsound.cpp @@ -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(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(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(startTime); + auto diff = steady_clock::now().time_since_epoch() - startTimeDuration; + chan->StartTime = static_cast(duration_cast(diff).count()); } float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) diff --git a/src/sound/backend/oalsound.h b/src/sound/backend/oalsound.h index 1d2f09fba..952b8776e 100644 --- a/src/sound/backend/oalsound.h +++ b/src/sound/backend/oalsound.h @@ -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*); diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index bec5fff8b..282bf15e3 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -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(volume), static_cast(attn), static_cast(pitch)); + PARAM_FLOAT(startTime); + S_SoundPitch(channel & 7, EChanFlags::FromInt(channel & ~7), id, static_cast(volume), static_cast(attn), static_cast(pitch), static_cast(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(volume), static_cast(attn), static_cast(pitch)); + PARAM_FLOAT(startTime); + S_SoundPitch(channel, EChanFlags::FromInt(flags), id, static_cast(volume), static_cast(attn), static_cast(pitch), static_cast(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) +void A_PlaySound(AActor* self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch, double startTime) { 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, startTime); } diff --git a/src/sound/s_doomsound.h b/src/sound/s_doomsound.h index 5a1a8fa09..584700ef2 100644 --- a/src/sound/s_doomsound.h +++ b/src/sound/s_doomsound.h @@ -17,7 +17,7 @@ void S_PrecacheLevel(FLevelLocals* l); // Start sound for thing at 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); @@ -56,8 +56,8 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch); // Stores/retrieves playing channel information in an archive. 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_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch, double startTime = 0.); +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); diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index 9c15c47b5..5979d320f 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -368,7 +368,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; @@ -568,11 +568,11 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, 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)) diff --git a/src/sound/s_soundinternal.h b/src/sound/s_soundinternal.h index 4dc978ed3..e3647b9c7 100644 --- a/src/sound/s_soundinternal.h +++ b/src/sound/s_soundinternal.h @@ -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); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 55b90edcb..d28721154 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1054,8 +1054,8 @@ class Actor : Thinker native deprecated("2.3") 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 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") 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, double startTime = 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); } From 5dfdac62ab88c06c2e2993b811b1e17a467d3a3d Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 2 Mar 2020 00:42:02 -0500 Subject: [PATCH 02/30] - add checking in S_StartSound for startTime length --- src/sound/s_sound.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index 5979d320f..a3250582e 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -36,6 +36,7 @@ #include #include +#include "templates.h" #include "s_soundinternal.h" #include "m_swap.h" #include "superfasthash.h" @@ -566,9 +567,13 @@ 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(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, startTime); + chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL, startTime); } else { From 3d3a29979b225122f51d8b7dc80dc0ccc731e80e Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 2 Mar 2020 02:17:12 -0500 Subject: [PATCH 03/30] - remove addition from deprecated A_PlaySound --- src/scripting/vmthunks_actors.cpp | 3 +-- wadsrc/static/zscript/actors/actor.zs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 92d4bb74f..31c4ab7b4 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -193,8 +193,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound) PARAM_FLOAT(volume); PARAM_FLOAT(attenuation); PARAM_FLOAT(pitch); - PARAM_FLOAT(startTime); - A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); + A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, 0.0f); return 0; } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index d28721154..8d3a5be4b 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1054,7 +1054,7 @@ class Actor : Thinker native deprecated("2.3") 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 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, double startTime = 0.0); + 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, double startTime = 0.0); native void A_SoundVolume(int slot, double volume); native void A_SoundPitch(int slot, double pitch); From 9e5444f8ae48564ab6e1cc24f19ec561a0f7ea29 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 2 Mar 2020 07:15:30 -0500 Subject: [PATCH 04/30] - fixed: removed startTime from the wrong function internally. --- src/scripting/vmthunks_actors.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 31c4ab7b4..bf058d479 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -179,8 +179,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) PARAM_FLOAT(attenuation); PARAM_BOOL(local); PARAM_FLOAT(pitch); - PARAM_FLOAT(startTime); - A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch, startTime); + A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch, 0.0f); return 0; } @@ -193,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, 0.0f); + PARAM_FLOAT(startTime); + A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); return 0; } From 178cf40428efaef3888904f592be9dbb831ec5f8 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 3 Mar 2020 22:50:01 -0500 Subject: [PATCH 05/30] - fix debug assertion, cleanup vestigial A_PlaySound addition --- src/scripting/vmthunks_actors.cpp | 2 +- src/sound/s_doomsound.cpp | 4 ++-- src/sound/s_doomsound.h | 2 +- wadsrc/static/zscript/base.zs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index bf058d479..e90184031 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -179,7 +179,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) PARAM_FLOAT(attenuation); PARAM_BOOL(local); PARAM_FLOAT(pitch); - A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch, 0.0f); + A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch); return 0; } diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index 282bf15e3..48f094f81 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -479,11 +479,11 @@ void A_StartSound(AActor *self, int soundid, int channel, int flags, double volu 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, double 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, startTime); + A_StartSound(self, soundid, channel & 7, channel & ~7, volume, attenuation, pitch, 0.0f); } diff --git a/src/sound/s_doomsound.h b/src/sound/s_doomsound.h index 584700ef2..2ea833dc0 100644 --- a/src/sound/s_doomsound.h +++ b/src/sound/s_doomsound.h @@ -56,7 +56,7 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch); // Stores/retrieves playing channel information in an archive. void S_SerializeSounds(FSerializer &arc); -void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch, double startTime = 0.); +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, double startTime = 0.); static void S_SetListener(AActor *listenactor); void S_SoundReset(); diff --git a/wadsrc/static/zscript/base.zs b/wadsrc/static/zscript/base.zs index beb170470..8e3cc5675 100644 --- a/wadsrc/static/zscript/base.zs +++ b/wadsrc/static/zscript/base.zs @@ -445,7 +445,7 @@ class Object native 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); + 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); From fcf004ec39240aed6aad421a5557391c4497bc4c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Mar 2020 11:01:33 +0200 Subject: [PATCH 06/30] - fixed infinite loop reporting '... before first state' errors https://forum.zdoom.org/viewtopic.php?t=67729 --- src/scripting/zscript/zcc_compile.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 316e39f37..b11cf10bb 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -3407,7 +3407,6 @@ void ZCCCompiler::CompileStates() if (!statedef.SetWait()) { Error(st, "%s before first state", st->NodeType == AST_StateFail ? "Fail" : "Wait"); - continue; } break; @@ -3415,7 +3414,6 @@ void ZCCCompiler::CompileStates() if (!statedef.SetLoop()) { Error(st, "LOOP before first state"); - continue; } break; From 33b343ef3166f7c2640ac2e732363c478ba14d7c Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sat, 15 Feb 2020 16:12:45 -0600 Subject: [PATCH 07/30] Added Pre(Un)Morph and Post(Un)Morph functions. - cls: The other class's cast type which the actor is transitioning from/to. --- wadsrc/static/zscript/actors/morph.zs | 13 +++++++++++++ .../static/zscript/actors/player/player_morph.zs | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/wadsrc/static/zscript/actors/morph.zs b/wadsrc/static/zscript/actors/morph.zs index b48bb98d4..8dbfb3862 100644 --- a/wadsrc/static/zscript/actors/morph.zs +++ b/wadsrc/static/zscript/actors/morph.zs @@ -28,6 +28,12 @@ extend class Actor return null, 0, 0; } + // [MC] Called when an actor morphs, on both the previous form (passive) and present form (!passive). + // 'cls' points to the other class they transitioned from/to. + virtual void PreMorph(Class cls) {} + virtual void PostMorph(Class cls) {} + virtual void PreUnmorph(Class cls) {} + virtual void PostUnmorph(Class cls) {} //=========================================================================== // @@ -105,6 +111,11 @@ extend class Actor } let morphed = MorphedMonster(Spawn (spawntype, Pos, NO_REPLACE)); + + // Use GetClass in the event someone actually allows replacements. + PreMorph(morphed.GetClass()); + morphed.PreMorph(GetClass()); + Substitute (morphed); if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate) { @@ -140,6 +151,8 @@ extend class Actor let eflash = Spawn(enter_flash ? enter_flash : (class)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE); if (eflash) eflash.target = morphed; + PostMorph(morphed.GetClass()); + morphed.PostMorph(GetClass()); return true; } } diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index 87ee90ac9..2a4437159 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -138,6 +138,11 @@ extend class PlayerPawn } let morphed = PlayerPawn(Spawn (spawntype, Pos, NO_REPLACE)); + + // Use GetClass in the event someone actually allows replacements. + PreMorph(morphed.GetClass()); + morphed.PreMorph(GetClass()); + EndAllPowerupEffects(); Substitute(morphed); if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate) @@ -211,6 +216,8 @@ extend class PlayerPawn morphed.ScoreIcon = ScoreIcon; // [GRB] if (eflash) eflash.target = morphed; + PostMorph(morphed.GetClass()); + morphed.PostMorph(GetClass()); return true; } @@ -249,6 +256,9 @@ extend class PlayerPawn player.morphTics = 2*TICRATE; return false; } + PreUnmorph(altmo.GetClass()); + altmo.PreUnmorph(GetClass()); + // 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 +405,8 @@ extend class PlayerPawn beastweap.Destroy (); } } + PostUnmorph(altmo.GetClass()); + altmo.PostUnmorph(GetClass()); Destroy (); // Restore playerclass armor to its normal amount. let hxarmor = HexenArmor(altmo.FindInventory('HexenArmor')); @@ -544,6 +556,8 @@ class MorphedMonster : Actor UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds return false; } + PreUnmorph(unmorphed.GetClass()); + unmorphed.PreUnmorph(GetClass()); unmorphed.Angle = Angle; unmorphed.target = target; unmorphed.bShadow = bShadow; @@ -563,6 +577,8 @@ class MorphedMonster : Actor unmorphed.args[4] = args[4]; unmorphed.CopyFriendliness (self, true); unmorphed.bUnmorphed = false; + PostUnmorph(unmorphed.GetClass()); + unmorphed.PostUnmorph(GetClass()); UnmorphedMe = NULL; Substitute(unmorphed); Destroy (); From 70f9b649aa27f1109c25175789c90b8b503b2441 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 8 Mar 2020 09:19:20 -0500 Subject: [PATCH 08/30] Changed Pre/Post(Un)Morph to take the other actor and a boolean indicating direction. - 'current' is true for the actor that is the new body, false for the old body. --- wadsrc/static/zscript/actors/morph.zs | 21 ++++++++-------- .../zscript/actors/player/player_morph.zs | 25 ++++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/wadsrc/static/zscript/actors/morph.zs b/wadsrc/static/zscript/actors/morph.zs index 8dbfb3862..1dcfb31fa 100644 --- a/wadsrc/static/zscript/actors/morph.zs +++ b/wadsrc/static/zscript/actors/morph.zs @@ -28,12 +28,11 @@ extend class Actor return null, 0, 0; } - // [MC] Called when an actor morphs, on both the previous form (passive) and present form (!passive). - // 'cls' points to the other class they transitioned from/to. - virtual void PreMorph(Class cls) {} - virtual void PostMorph(Class cls) {} - virtual void PreUnmorph(Class cls) {} - virtual void PostUnmorph(Class cls) {} + // [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) {} //=========================================================================== // @@ -112,9 +111,9 @@ extend class Actor let morphed = MorphedMonster(Spawn (spawntype, Pos, NO_REPLACE)); - // Use GetClass in the event someone actually allows replacements. - PreMorph(morphed.GetClass()); - morphed.PreMorph(GetClass()); + // [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) @@ -151,8 +150,8 @@ extend class Actor let eflash = Spawn(enter_flash ? enter_flash : (class)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE); if (eflash) eflash.target = morphed; - PostMorph(morphed.GetClass()); - morphed.PostMorph(GetClass()); + PostMorph(morphed, false); + morphed.PostMorph(self, true); return true; } } diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index 2a4437159..a7c1a97e5 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -140,8 +140,8 @@ extend class PlayerPawn let morphed = PlayerPawn(Spawn (spawntype, Pos, NO_REPLACE)); // Use GetClass in the event someone actually allows replacements. - PreMorph(morphed.GetClass()); - morphed.PreMorph(GetClass()); + PreMorph(morphed, false); + morphed.PreMorph(self, true); EndAllPowerupEffects(); Substitute(morphed); @@ -216,8 +216,8 @@ extend class PlayerPawn morphed.ScoreIcon = ScoreIcon; // [GRB] if (eflash) eflash.target = morphed; - PostMorph(morphed.GetClass()); - morphed.PostMorph(GetClass()); + PostMorph(morphed, false); // No longer the current body + morphed.PostMorph(self, true); // This is the current body return true; } @@ -256,8 +256,9 @@ extend class PlayerPawn player.morphTics = 2*TICRATE; return false; } - PreUnmorph(altmo.GetClass()); - altmo.PreUnmorph(GetClass()); + + 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. @@ -405,8 +406,8 @@ extend class PlayerPawn beastweap.Destroy (); } } - PostUnmorph(altmo.GetClass()); - altmo.PostUnmorph(GetClass()); + 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')); @@ -556,8 +557,8 @@ class MorphedMonster : Actor UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds return false; } - PreUnmorph(unmorphed.GetClass()); - unmorphed.PreUnmorph(GetClass()); + PreUnmorph(unmorphed, false); + unmorphed.PreUnmorph(self, true); unmorphed.Angle = Angle; unmorphed.target = target; unmorphed.bShadow = bShadow; @@ -577,8 +578,8 @@ class MorphedMonster : Actor unmorphed.args[4] = args[4]; unmorphed.CopyFriendliness (self, true); unmorphed.bUnmorphed = false; - PostUnmorph(unmorphed.GetClass()); - unmorphed.PostUnmorph(GetClass()); + 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 (); From 3607ffaf663570e579f66a51740a9dfa5e7451bb Mon Sep 17 00:00:00 2001 From: Alexander Kromm Date: Thu, 30 Jan 2020 00:10:07 +0700 Subject: [PATCH 09/30] fix Dictionary and DictionaryIterator memory leaks --- src/scripting/thingdef_data.cpp | 15 --- src/serializer.cpp | 2 +- src/utility/dictionary.cpp | 175 ++++++++++++++++++++-------- src/utility/dictionary.h | 60 +++++++++- src/version.h | 4 +- wadsrc/static/zscript/dictionary.zs | 19 ++- 6 files changed, 200 insertions(+), 75 deletions(-) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index c308b00e3..5f61bbfab 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -843,21 +843,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(ar, key, *(Dictionary **)addr, nullptr); - return true; - } - ); - FAutoSegIterator probe(CRegHead, CRegTail); while (*++probe != NULL) diff --git a/src/serializer.cpp b/src/serializer.cpp index 6e58973e2..860dcad2a 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -2190,7 +2190,7 @@ Dictionary *DictionaryFromString(const FString &string) return nullptr; } - Dictionary *const dict = new Dictionary; + Dictionary *const dict = Create(); if (string.IsEmpty()) { diff --git a/src/utility/dictionary.cpp b/src/utility/dictionary.cpp index 6da43dca1..7e9e14a1f 100644 --- a/src/utility/dictionary.cpp +++ b/src/utility/dictionary.cpp @@ -3,20 +3,87 @@ #include "scripting/vm/vm.h" #include "serializer.h" +#include + +//===================================================================================== +// +// 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); + TransferFrom(*pointerToDeserializedDictionary); + delete pointerToDeserializedDictionary; + } +} + +static Dictionary *DictCreate() +{ + Dictionary *dict { Create() }; + + return dict; +} + +static void DictInsert(Dictionary *dict, const FString &key, const FString &value) +{ + dict->Insert(key, value); +} + +static void DictAt(const Dictionary *dict, const FString &key, FString *result) +{ + const FString *value = dict->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->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(*dict); + Dict = dict; + + GC::WriteBarrier(this, Dict); +} + +static DictionaryIterator *DictIteratorCreate(Dictionary *dict) +{ + DictionaryIterator *iterator = Create(); + 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); diff --git a/src/utility/dictionary.h b/src/utility/dictionary.h index 4ccd11370..d97099482 100644 --- a/src/utility/dictionary.h +++ b/src/utility/dictionary.h @@ -2,13 +2,63 @@ #include "tarray.h" #include "zstring.h" +#include "dobject.h" -using Dictionary = TMap; +#include -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, public TMap { - explicit DictionaryIterator(const Dictionary &dict); + DECLARE_CLASS(Dictionary, DObject) - Dictionary::ConstIterator Iterator; - Dictionary::ConstPair *Pair; +public: + + void Serialize(FSerializer &arc) override; +}; + +/** + * @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 Iterator; + Dictionary::ConstPair *Pair; + + /** + * @brief Dictionary attribute exists for holding a pointer to iterated + * dictionary, so it is known by GC. + */ + Dictionary *Dict; }; diff --git a/src/version.h b/src/version.h index d46902acb..6936de47d 100644 --- a/src/version.h +++ b/src/version.h @@ -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 4558 // 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 "GZDOOM" diff --git a/wadsrc/static/zscript/dictionary.zs b/wadsrc/static/zscript/dictionary.zs index 432cec891..0bd48cd69 100644 --- a/wadsrc/static/zscript/dictionary.zs +++ b/wadsrc/static/zscript/dictionary.zs @@ -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); From b038c168c635fedd58bf6f9baffd37ccadf31904 Mon Sep 17 00:00:00 2001 From: Alexander Kromm Date: Thu, 6 Feb 2020 21:20:33 +0700 Subject: [PATCH 10/30] aggregate TMap into Dictionary instead of deriving from it --- src/serializer.cpp | 4 ++-- src/utility/dictionary.cpp | 10 +++++----- src/utility/dictionary.h | 10 ++++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/serializer.cpp b/src/serializer.cpp index 860dcad2a..cd9b5b8f2 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -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 writer(buffer); @@ -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; diff --git a/src/utility/dictionary.cpp b/src/utility/dictionary.cpp index 7e9e14a1f..a6bcccc66 100644 --- a/src/utility/dictionary.cpp +++ b/src/utility/dictionary.cpp @@ -42,7 +42,7 @@ void Dictionary::Serialize(FSerializer &arc) // Receive new Dictionary, copy contents, clean up. Dictionary *pointerToDeserializedDictionary; arc(key, pointerToDeserializedDictionary); - TransferFrom(*pointerToDeserializedDictionary); + Map.TransferFrom(pointerToDeserializedDictionary->Map); delete pointerToDeserializedDictionary; } } @@ -56,12 +56,12 @@ static Dictionary *DictCreate() static void DictInsert(Dictionary *dict, const FString &key, const FString &value) { - dict->Insert(key, value); + dict->Map.Insert(key, value); } static void DictAt(const Dictionary *dict, const FString &key, FString *result) { - const FString *value = dict->CheckKey(key); + const FString *value = dict->Map.CheckKey(key); *result = value ? *value : ""; } @@ -72,7 +72,7 @@ static void DictToString(const Dictionary *dict, FString *result) static void DictRemove(Dictionary *dict, const FString &key) { - dict->Remove(key); + dict->Map.Remove(key); } //===================================================================================== @@ -150,7 +150,7 @@ void DictionaryIterator::Serialize(FSerializer &arc) void DictionaryIterator::init(Dictionary *dict) { - Iterator = std::make_unique(*dict); + Iterator = std::make_unique(dict->Map); Dict = dict; GC::WriteBarrier(this, Dict); diff --git a/src/utility/dictionary.h b/src/utility/dictionary.h index d97099482..ef6bd3f68 100644 --- a/src/utility/dictionary.h +++ b/src/utility/dictionary.h @@ -13,13 +13,19 @@ * * It is derived from DObject to be a part of normal GC process. */ -class Dictionary final : public DObject, public TMap +class Dictionary final : public DObject { DECLARE_CLASS(Dictionary, DObject) public: + using StringMap = TMap; + using ConstIterator = StringMap::ConstIterator; + using ConstPair = StringMap::ConstPair; + void Serialize(FSerializer &arc) override; + + StringMap Map; }; /** @@ -45,7 +51,7 @@ public: */ DictionaryIterator(); - void Serialize(FSerializer &arc) override; + void Serialize(FSerializer &arc) override; /** * @brief init function complements constructor. From 9daec9dc46eefb6a7f45019b08d4502f8a9d5f03 Mon Sep 17 00:00:00 2001 From: Alexander Kromm Date: Thu, 6 Feb 2020 21:49:59 +0700 Subject: [PATCH 11/30] bring minimal save version back, as most of the savegames load fine --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 6936de47d..24e0fbd96 100644 --- a/src/version.h +++ b/src/version.h @@ -84,7 +84,7 @@ const char *GetVersionString(); #define SAVEGAME_EXT "zds" // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 4558 +#define MINSAVEVER 4556 // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. From 920b322d72bb69dfa29f1815eec4a69eb83609a5 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 11 Mar 2020 02:18:43 +0100 Subject: [PATCH 12/30] Add missing segment clipping clamps for decals, sprites and wall sprites --- src/rendering/swrenderer/things/r_decal.cpp | 10 +--------- src/rendering/swrenderer/things/r_sprite.cpp | 2 +- src/rendering/swrenderer/things/r_wallsprite.cpp | 2 +- .../swrenderer/viewport/r_spritedrawer.cpp | 16 +++++++++++++--- .../swrenderer/viewport/r_spritedrawer.h | 2 +- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/rendering/swrenderer/things/r_decal.cpp b/src/rendering/swrenderer/things/r_decal.cpp index cfcc01ccd..263b86d3a 100644 --- a/src/rendering/swrenderer/things/r_decal.cpp +++ b/src/rendering/swrenderer/things/r_decal.cpp @@ -218,14 +218,6 @@ namespace swrenderer } } - // Clip sprite to drawseg - x1 = MAX(clipper->x1, x1); - x2 = MIN(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 diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 164432e69..cedb0fa22 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -274,7 +274,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); } } } diff --git a/src/rendering/swrenderer/things/r_wallsprite.cpp b/src/rendering/swrenderer/things/r_wallsprite.cpp index d80cb0edc..b5ee7ba14 100644 --- a/src/rendering/swrenderer/things/r_wallsprite.cpp +++ b/src/rendering/swrenderer/things/r_wallsprite.cpp @@ -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); } } diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp index 9a0586076..7d3af54ec 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp @@ -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(WallC.sx1, clipx1); + int x2 = MIN(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; diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.h b/src/rendering/swrenderer/viewport/r_spritedrawer.h index f07b81fba..f233d2c03 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.h +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.h @@ -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); From 8613e478996691d34a27891779b40456ad9bb042 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 11 Mar 2020 00:31:19 +0100 Subject: [PATCH 13/30] - default terrain's DamageTimeMask to a reasonable value. Use 31, which is the default for damaging floor specials instead of 0. --- src/gamedata/p_terrain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gamedata/p_terrain.cpp b/src/gamedata/p_terrain.cpp index 8472b1fab..58eeba9b9 100644 --- a/src/gamedata/p_terrain.cpp +++ b/src/gamedata/p_terrain.cpp @@ -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 { From 2acdf5cfaba4c78af08d32e32edb4cad3ca6a8a6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 11 Mar 2020 00:38:26 +0100 Subject: [PATCH 14/30] - added autonames for the shareware games They still need to access some internal filters, despite blocking loading addons. --- wadsrc_extra/static/iwadinfo.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wadsrc_extra/static/iwadinfo.txt b/wadsrc_extra/static/iwadinfo.txt index bc9ca5cd4..56a044445 100644 --- a/wadsrc_extra/static/iwadinfo.txt +++ b/wadsrc_extra/static/iwadinfo.txt @@ -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" From a638cfbd6eb778b1f52baae46b0aa19da5f2157a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 11 Mar 2020 00:56:29 +0100 Subject: [PATCH 15/30] - fixed: player_t::GetPSprite cannot guarantee success As a consequence it must return null in the failure case instead of asserting and all calls to this function must check for the failure case. --- src/playsim/p_pspr.cpp | 7 +-- .../zscript/actors/doom/weaponchaingun.zs | 3 +- .../static/zscript/actors/heretic/chicken.zs | 18 ++++++-- .../zscript/actors/heretic/weapongauntlets.zs | 8 +++- .../zscript/actors/heretic/weaponmace.zs | 8 +++- .../zscript/actors/inventory/powerups.zs | 22 +++++++--- .../zscript/actors/inventory/weapons.zs | 21 ++++++--- wadsrc/static/zscript/actors/player/player.zs | 6 ++- .../zscript/actors/player/player_morph.zs | 3 +- wadsrc/static/zscript/actors/strife/sigil.zs | 6 +-- .../zscript/actors/strife/strifeplayer.zs | 44 ++++++++++--------- .../zscript/actors/strife/weaponmauler.zs | 7 ++- 12 files changed, 101 insertions(+), 52 deletions(-) diff --git a/src/playsim/p_pspr.cpp b/src/playsim/p_pspr.cpp index bcbbf2f18..c282995e0 100644 --- a/src/playsim/p_pspr.cpp +++ b/src/playsim/p_pspr.cpp @@ -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) { diff --git a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs index 7d00827fa..267977e0d 100644 --- a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs +++ b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs @@ -70,7 +70,8 @@ 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; + let psp = player.GetPSprite(PSP_WEAPON); + if (psp) State cur = psp.CurState; int theflash = atk == cur? 0:1; player.SetSafeFlash(weap, flash, theflash); } diff --git a/wadsrc/static/zscript/actors/heretic/chicken.zs b/wadsrc/static/zscript/actors/heretic/chicken.zs index c643f6c9c..6e5354623 100644 --- a/wadsrc/static/zscript/actors/heretic/chicken.zs +++ b/wadsrc/static/zscript/actors/heretic/chicken.zs @@ -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); + } } } diff --git a/wadsrc/static/zscript/actors/heretic/weapongauntlets.zs b/wadsrc/static/zscript/actors/heretic/weapongauntlets.zs index 2f4b500e4..9e92e3cce 100644 --- a/wadsrc/static/zscript/actors/heretic/weapongauntlets.zs +++ b/wadsrc/static/zscript/actors/heretic/weapongauntlets.zs @@ -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) diff --git a/wadsrc/static/zscript/actors/heretic/weaponmace.zs b/wadsrc/static/zscript/actors/heretic/weaponmace.zs index 9928443ee..52edd6000 100644 --- a/wadsrc/static/zscript/actors/heretic/weaponmace.zs +++ b/wadsrc/static/zscript/actors/heretic/weaponmace.zs @@ -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) { diff --git a/wadsrc/static/zscript/actors/inventory/powerups.zs b/wadsrc/static/zscript/actors/inventory/powerups.zs index ede8f7aa7..6ac852aba 100644 --- a/wadsrc/static/zscript/actors/inventory/powerups.zs +++ b/wadsrc/static/zscript/actors/inventory/powerups.zs @@ -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; + } } } diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index 9da5329bc..06854da9d 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -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()); + } } //=========================================================================== diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 4f42b6159..c19674455 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -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); diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index a7c1a97e5..66fd0f1d8 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -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')) diff --git a/wadsrc/static/zscript/actors/strife/sigil.zs b/wadsrc/static/zscript/actors/strife/sigil.zs index fcf7933ee..60919c855 100644 --- a/wadsrc/static/zscript/actors/strife/sigil.zs +++ b/wadsrc/static/zscript/actors/strife/sigil.zs @@ -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)); } //============================================================================ diff --git a/wadsrc/static/zscript/actors/strife/strifeplayer.zs b/wadsrc/static/zscript/actors/strife/strifeplayer.zs index 9ddba754a..902816227 100644 --- a/wadsrc/static/zscript/actors/strife/strifeplayer.zs +++ b/wadsrc/static/zscript/actors/strife/strifeplayer.zs @@ -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; diff --git a/wadsrc/static/zscript/actors/strife/weaponmauler.zs b/wadsrc/static/zscript/actors/strife/weaponmauler.zs index 3c5000893..b805c3ac5 100644 --- a/wadsrc/static/zscript/actors/strife/weaponmauler.zs +++ b/wadsrc/static/zscript/actors/strife/weaponmauler.zs @@ -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.; + } } } From 4201c4fbb579637356180d5838410b607ea158e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 11 Mar 2020 19:47:23 +0100 Subject: [PATCH 16/30] - fixed A_FireCGun. --- wadsrc/static/zscript/actors/doom/weaponchaingun.zs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs index 267977e0d..58a450688 100644 --- a/wadsrc/static/zscript/actors/doom/weaponchaingun.zs +++ b/wadsrc/static/zscript/actors/doom/weaponchaingun.zs @@ -71,9 +71,12 @@ 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'); let psp = player.GetPSprite(PSP_WEAPON); - if (psp) State cur = psp.CurState; - int theflash = atk == cur? 0:1; - player.SetSafeFlash(weap, flash, theflash); + if (psp) + { + State cur = psp.CurState; + int theflash = atk == cur? 0:1; + player.SetSafeFlash(weap, flash, theflash); + } } } player.mo.PlayAttacking2 (); From 13e6ea7796dce17f651667265cc803ce3d67fc63 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 13 Mar 2020 13:33:11 +0200 Subject: [PATCH 17/30] - added line break to 'No GENMIDI lump' message 'ST_Init: Init startup screen.' is no longer concatenated with the given line --- src/sound/music/i_music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index 8ef1cad89..b171321d7 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -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); From b9d4ce052b10e8d93d3e32b09e3bf5d6c843247f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 14 Mar 2020 12:33:36 +0200 Subject: [PATCH 18/30] - replaced assert() in ZScript fields compilation code Field pointer can be null if error occurred while compiling its definition --- src/scripting/zscript/zcc_compile.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b11cf10bb..26b4b73ca 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1559,9 +1559,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayName).GetChars()); } - assert(f != nullptr); - - if (field->Flags & (ZCC_Version | ZCC_Deprecated)) + if ((field->Flags & (ZCC_Version | ZCC_Deprecated)) && f != nullptr) { f->mVersion = field->Version; From f46e80e2b450f7e0b88ae307ae380ef1293bbc3c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 14 Mar 2020 12:47:03 +0200 Subject: [PATCH 19/30] - fixed FLineTraceData scripting definition https://forum.zdoom.org/viewtopic.php?t=67795 --- src/scripting/thingdef_data.cpp | 4 ++++ src/scripting/vmthunks_actors.cpp | 1 + wadsrc/static/zscript/actors/actor.zs | 26 +++++++++++++------------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 5f61bbfab..6b17a65f4 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -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" @@ -903,6 +904,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) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index e90184031..8d7a1711d 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1957,6 +1957,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); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 8d3a5be4b..966770bb2 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -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 From 7a141f3aa3b67b5b1d326f5d9b3904da1b65f847 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 10 Mar 2020 16:31:21 +0800 Subject: [PATCH 20/30] Add help messages for most of the deprecated stuff in ZScript. --- wadsrc/static/zscript/actors/actor.zs | 46 +++++++++---------- wadsrc/static/zscript/actors/attacks.zs | 6 +-- wadsrc/static/zscript/actors/checks.zs | 2 +- .../zscript/actors/inventory/stateprovider.zs | 10 ++-- wadsrc/static/zscript/actors/player/player.zs | 8 ++-- wadsrc/static/zscript/base.zs | 34 +++++++------- wadsrc/static/zscript/compatibility.zs | 18 ++++---- wadsrc/static/zscript/destructible.zs | 2 +- wadsrc/static/zscript/mapdata.zs | 6 +-- 9 files changed, 66 insertions(+), 66 deletions(-) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 966770bb2..704b8fb85 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -339,17 +339,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.; @@ -596,7 +596,7 @@ class Actor : Thinker native native static int ApplyDamageFactors(class 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); } @@ -906,7 +906,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) { @@ -1052,18 +1052,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 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); + 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(, 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, ...); @@ -1084,7 +1084,7 @@ class Actor : Thinker native native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class 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 = [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); @@ -1120,10 +1120,10 @@ class Actor : Thinker native native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetRoll(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); diff --git a/wadsrc/static/zscript/actors/attacks.zs b/wadsrc/static/zscript/actors/attacks.zs index 8cc627b34..bb2cdeec4 100644 --- a/wadsrc/static/zscript/actors/attacks.zs +++ b/wadsrc/static/zscript/actors/attacks.zs @@ -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 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 MissileType = MissileName; DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); diff --git a/wadsrc/static/zscript/actors/checks.zs b/wadsrc/static/zscript/actors/checks.zs index 573664b57..280abf4fe 100644 --- a/wadsrc/static/zscript/actors/checks.zs +++ b/wadsrc/static/zscript/actors/checks.zs @@ -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; } diff --git a/wadsrc/static/zscript/actors/inventory/stateprovider.zs b/wadsrc/static/zscript/actors/inventory/stateprovider.zs index 469b56090..05aa06f22 100644 --- a/wadsrc/static/zscript/actors/inventory/stateprovider.zs +++ b/wadsrc/static/zscript/actors/inventory/stateprovider.zs @@ -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); //=========================================================================== diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index c19674455..3a5727739 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2718,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 spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null) + deprecated("3.7", "MorphPlayer() should be used on a PlayerPawn object") bool MorphPlayer(playerinfo p, Class spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null) { if (mo != null) { @@ -2728,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) { @@ -2737,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) { @@ -2745,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(); } diff --git a/wadsrc/static/zscript/base.zs b/wadsrc/static/zscript/base.zs index 8e3cc5675..ee8c3fb89 100644 --- a/wadsrc/static/zscript/base.zs +++ b/wadsrc/static/zscript/base.zs @@ -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); } @@ -242,7 +242,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,15 +436,15 @@ 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); + 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); @@ -530,7 +530,7 @@ class ThinkerIterator : Object native class ActorIterator : Object native { - deprecated("3.8") static ActorIterator Create(int tid, class type = "Actor") + deprecated("3.8", "Use Level.CreateActorIterator() instead") static ActorIterator Create(int tid, class type = "Actor") { return level.CreateActorIterator(tid, type); } @@ -716,7 +716,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 +740,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 +761,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 +925,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 +1005,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 +1051,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); } diff --git a/wadsrc/static/zscript/compatibility.zs b/wadsrc/static/zscript/compatibility.zs index 90ba082b9..3c0482ba0 100644 --- a/wadsrc/static/zscript/compatibility.zs +++ b/wadsrc/static/zscript/compatibility.zs @@ -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 checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false) + deprecated("3.7", "Use GetClass(), type cast, or 'is' operator instead") bool CheckClass(class 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 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 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 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 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); } diff --git a/wadsrc/static/zscript/destructible.zs b/wadsrc/static/zscript/destructible.zs index c44a1ef30..a7e0dc982 100644 --- a/wadsrc/static/zscript/destructible.zs +++ b/wadsrc/static/zscript/destructible.zs @@ -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); } diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index f7e07d211..1ac5f12de 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -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); } From 2edbbac759a41fb137e943fa650a2fb981cd05ae Mon Sep 17 00:00:00 2001 From: Nash Muhandes Date: Sat, 14 Mar 2020 20:17:04 +0800 Subject: [PATCH 21/30] Print weapon name tag when switching with "slot" command (#1048) --- src/g_game.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/g_game.cpp b/src/g_game.cpp index f8f2134ba..fa5405d3e 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -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(nullptr, SendItemUse->GetTag(), + 1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('W', 'E', 'P', 'N')); + } } } From db5efddf12ca22b6655f26639bc43d12824e7a70 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Mar 2020 09:27:02 +0100 Subject: [PATCH 22/30] - implemented better aspect ratio control for fullscreen images. Due to backwards compatibility needs and for flexibility this needs to be controlled by a gameinfo setting (fullscreenautoaspect): 0: Treat all images as having an aspect ratio of 4:3, this is the default for compatibility reasons 1: Scale all images to fit the screen, i.e. either pillarbox or letterbox them. 2: Scale all images to fill the screen. 3: Scale all images so that the center 4:3 area is always fully visible. This is the recommended mode for 16:9 images designed to be shown with the sides being cropped on narrower displays. A new DTA_ tag - DTA_FullscreenEx also exists which allows specifying the scale mode directly --- src/gamedata/gi.cpp | 2 ++ src/gamedata/gi.h | 1 + src/rendering/2d/v_draw.cpp | 58 +++++++++++++++++++++++++++++- src/rendering/v_video.cpp | 71 ------------------------------------- src/rendering/v_video.h | 8 ++--- 5 files changed, 64 insertions(+), 76 deletions(-) diff --git a/src/gamedata/gi.cpp b/src/gamedata/gi.cpp index a952313a5..5076938c5 100644 --- a/src/gamedata/gi.cpp +++ b/src/gamedata/gi.cpp @@ -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") diff --git a/src/gamedata/gi.h b/src/gamedata/gi.h index d1dc534e3..84e383135 100644 --- a/src/gamedata/gi.h +++ b/src/gamedata/gi.h @@ -204,6 +204,7 @@ struct gameinfo_t int berserkpic; double normforwardmove[2]; double normsidemove[2]; + int fullscreenautoaspect = 3; const char *GetFinalePage(unsigned int num) const; }; diff --git a/src/rendering/2d/v_draw.cpp b/src/rendering/2d/v_draw.cpp index 82d87b543..1964bf3ae 100644 --- a/src/rendering/2d/v_draw.cpp +++ b/src/rendering/2d/v_draw.cpp @@ -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 == 200)? 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: @@ -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(); } diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index efb35bbe9..9b61eb243 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -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 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(h * yratio); - else - h = static_cast(y); -} - CCMD(vid_setsize) { if (argv.argc() < 3) diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index d1ecbc5d5..479b5d145 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -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 @@ -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); From 27b8284881d7dac7fa713f06430e5dcc2a398062 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Mar 2020 10:02:19 +0100 Subject: [PATCH 23/30] - forgot to remove the test settings for the fullscreen feature. --- src/gamedata/gi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamedata/gi.h b/src/gamedata/gi.h index 84e383135..5d5f061e3 100644 --- a/src/gamedata/gi.h +++ b/src/gamedata/gi.h @@ -204,7 +204,7 @@ struct gameinfo_t int berserkpic; double normforwardmove[2]; double normsidemove[2]; - int fullscreenautoaspect = 3; + int fullscreenautoaspect = 0; const char *GetFinalePage(unsigned int num) const; }; From 0c04cddd28ba775e41c79186e31c4aed91361263 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Mar 2020 10:22:42 +0100 Subject: [PATCH 24/30] - allow specifying full palettes in translation definitions. --- src/gamedata/textures/texturemanager.cpp | 2 +- src/gamedata/w_wad.cpp | 2 +- src/r_data/r_translate.cpp | 51 ++++++++++++++++++++++-- src/r_data/r_translate.h | 1 + src/r_data/v_palette.cpp | 44 +++++++++++++++++--- src/r_data/v_palette.h | 2 +- src/win32/st_start_util.cpp | 2 +- wadsrc/static/zscript/base.zs | 2 + 8 files changed, 92 insertions(+), 14 deletions(-) diff --git a/src/gamedata/textures/texturemanager.cpp b/src/gamedata/textures/texturemanager.cpp index 8f052222c..ee5badce8 100644 --- a/src/gamedata/textures/texturemanager.cpp +++ b/src/gamedata/textures/texturemanager.cpp @@ -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; diff --git a/src/gamedata/w_wad.cpp b/src/gamedata/w_wad.cpp index 485ca33ea..959268350 100644 --- a/src/gamedata/w_wad.cpp +++ b/src/gamedata/w_wad.cpp @@ -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; } diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index e6a85c929..f22402720 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -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 { - NewTranslation.AddToTranslation(sc.String); + int pallump = Wads.CheckNumForFullName(sc.String, true, ns_global); + if (pallump) // + { + 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); + } + else + { + NewTranslation.AddToTranslation(sc.String); + } } - catch (CRecoverableError &err) + 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); diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 0c52f256d..bf0d38646 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -78,6 +78,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(); diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 1a6c25b25..4135fab12 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -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(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(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(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 (); diff --git a/src/r_data/v_palette.h b/src/r_data/v_palette.h index e12ba9a8f..dbabd92e8 100644 --- a/src/r_data/v_palette.h +++ b/src/r_data/v_palette.h @@ -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) diff --git a/src/win32/st_start_util.cpp b/src/win32/st_start_util.cpp index b347a3439..72bb3f14a 100644 --- a/src/win32/st_start_util.cpp +++ b/src/win32/st_start_util.cpp @@ -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]; diff --git a/wadsrc/static/zscript/base.zs b/wadsrc/static/zscript/base.zs index ee8c3fb89..e8e986aa2 100644 --- a/wadsrc/static/zscript/base.zs +++ b/wadsrc/static/zscript/base.zs @@ -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_FullsceeenEx, // advanced fullscreen control. }; class Shape2DTransform : Object native From 16ae7e312458e68b50cc45816b63018fc8d67133 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Mar 2020 12:19:22 +0100 Subject: [PATCH 25/30] - fixed typo. --- src/rendering/2d/v_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/2d/v_draw.cpp b/src/rendering/2d/v_draw.cpp index 1964bf3ae..095cf780e 100644 --- a/src/rendering/2d/v_draw.cpp +++ b/src/rendering/2d/v_draw.cpp @@ -381,7 +381,7 @@ bool DFrameBuffer::SetTextureParms(DrawParms *parms, FTexture *img, double xx, d double srcwidth = img->GetDisplayWidthDouble(); double srcheight = img->GetDisplayHeightDouble(); int autoaspect = parms->fsscalemode; - aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 200)? 1.333 : srcwidth / srcheight; + aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 400)? 1.333 : srcwidth / srcheight; parms->x = parms->y = 0; parms->keepratio = true; auto screenratio = ActiveRatio(GetWidth(), GetHeight()); From a50a5101bc3f9fd6a23b768213a1b14cef6b3f27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Mar 2020 15:56:35 +0100 Subject: [PATCH 26/30] - fixed another typo. --- wadsrc/static/zscript/base.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/base.zs b/wadsrc/static/zscript/base.zs index e8e986aa2..7cbaf8e91 100644 --- a/wadsrc/static/zscript/base.zs +++ b/wadsrc/static/zscript/base.zs @@ -192,7 +192,7 @@ enum DrawTextureTags DTA_Spacing, // Strings only: Additional spacing between characters DTA_Monospace, // Strings only: Use a fixed distance between characters. - DTA_FullsceeenEx, // advanced fullscreen control. + DTA_FullscreenEx, // advanced fullscreen control. }; class Shape2DTransform : Object native From b7970ed76386ca045fd3a964e4a6dd0fb3bb3e8a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Mar 2020 09:21:37 +0100 Subject: [PATCH 27/30] - block StaticPointerSubstitution for non-player objects. The only safe use of this function is to swap out PlayerPawns for morphing or respawning. --- src/dobject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dobject.cpp b/src/dobject.cpp index b16e69d9b..e1ebc654b 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -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) From 828cba13a1339d197c57906fa52f3dea54b49199 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Mar 2020 17:23:30 +0100 Subject: [PATCH 28/30] - changed translation management so that the fonts also use translation IDs. --- src/gamedata/fonts/font.cpp | 27 ++++++++++--------- src/gamedata/fonts/hexfont.cpp | 2 +- src/gamedata/fonts/specialfont.cpp | 26 +++++++++--------- src/gamedata/fonts/v_font.h | 8 +++--- src/intermission/intermission.cpp | 2 -- src/r_data/r_translate.h | 1 + src/rendering/2d/v_2ddrawer.cpp | 12 ++++----- src/rendering/2d/v_2ddrawer.h | 4 +-- src/rendering/2d/v_draw.cpp | 9 ++----- src/rendering/2d/v_drawtext.cpp | 20 +++++++------- src/rendering/gl/textures/gl_hwtexture.cpp | 11 ++------ .../hwrenderer/textures/hw_texcontainer.h | 11 ++------ .../hwrenderer/utility/hw_draw2d.cpp | 3 +-- .../polyrenderer/backend/poly_hwtexture.cpp | 11 ++------ src/rendering/v_video.h | 2 +- .../vulkan/textures/vk_hwtexture.cpp | 11 ++------ wadsrc/static/zscript/constants.zs | 1 + 17 files changed, 63 insertions(+), 98 deletions(-) diff --git a/src/gamedata/fonts/font.cpp b/src/gamedata/fonts/font.cpp index 87815ab9f..85053ad32 100644 --- a/src/gamedata/fonts/font.cpp +++ b/src/gamedata/fonts/font.cpp @@ -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 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]; } //========================================================================== diff --git a/src/gamedata/fonts/hexfont.cpp b/src/gamedata/fonts/hexfont.cpp index e57982928..fde86bc3d 100644 --- a/src/gamedata/fonts/hexfont.cpp +++ b/src/gamedata/fonts/hexfont.cpp @@ -417,7 +417,7 @@ public: } } } - Ranges[CR_UNTRANSLATED] = remap; + Translations[CR_UNTRANSLATED] = remap.StoreTranslation(TRANSLATION_Font); forceremap = true; } diff --git a/src/gamedata/fonts/specialfont.cpp b/src/gamedata/fonts/specialfont.cpp index 8bac60fe2..6231db07e 100644 --- a/src/gamedata/fonts/specialfont.cpp +++ b/src/gamedata/fonts/specialfont.cpp @@ -160,7 +160,7 @@ void FSpecialFont::LoadTranslations() uint8_t identity[256]; TArray Luminosity; int TotalColors; - int i, j; + int i; for (i = 0; i < count; i++) { @@ -199,22 +199,20 @@ void FSpecialFont::LoadTranslations() static_cast(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; } diff --git a/src/gamedata/fonts/v_font.h b/src/gamedata/fonts/v_font.h index 67c7318d4..e97a5ebc4 100644 --- a/src/gamedata/fonts/v_font.h +++ b/src/gamedata/fonts/v_font.h @@ -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 post = nullptr); void FixXMoves(); static int SimpleTranslation (uint32_t *colorsused, uint8_t *translation, @@ -166,7 +166,7 @@ protected: }; TArray Chars; int ActiveColors; - TArray Ranges; + TArray Translations; uint8_t PatchRemap[256]; int Lump; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index e536e3882..2db845748 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -370,7 +370,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 +423,6 @@ void DIntermissionScreenText::Drawer () // draw some of the text onto the screen count = (mTicker - mTextDelay) / mTextSpeed; - range = font->GetColorTranslation (mTextColor); for ( ; count > 0 ; count-- ) { diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index bf0d38646..7f57e680d 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -19,6 +19,7 @@ enum TRANSLATION_Blood, TRANSLATION_RainPillar, TRANSLATION_Custom, + TRANSLATION_Font, NUM_TRANSLATION_TABLES }; diff --git a/src/rendering/2d/v_2ddrawer.cpp b/src/rendering/2d/v_2ddrawer.cpp index f36ee05c4..beec88745 100644 --- a/src/rendering/2d/v_2ddrawer.cpp +++ b/src/rendering/2d/v_2ddrawer.cpp @@ -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()) diff --git a/src/rendering/2d/v_2ddrawer.h b/src/rendering/2d/v_2ddrawer.h index 23aae88d7..53ea596c9 100644 --- a/src/rendering/2d/v_2ddrawer.h +++ b/src/rendering/2d/v_2ddrawer.h @@ -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)) && diff --git a/src/rendering/2d/v_draw.cpp b/src/rendering/2d/v_draw.cpp index 095cf780e..473db44a8 100644 --- a/src/rendering/2d/v_draw.cpp +++ b/src/rendering/2d/v_draw.cpp @@ -558,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; @@ -756,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: @@ -971,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) { diff --git a/src/rendering/2d/v_drawtext.cpp b/src/rendering/2d/v_drawtext.cpp index 46dea6561..4dff23df3 100644 --- a/src/rendering/2d/v_drawtext.cpp +++ b/src/rendering/2d/v_drawtext.cpp @@ -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) { diff --git a/src/rendering/gl/textures/gl_hwtexture.cpp b/src/rendering/gl/textures/gl_hwtexture.cpp index 74799fc88..c864eedd2 100644 --- a/src/rendering/gl/textures/gl_hwtexture.cpp +++ b/src/rendering/gl/textures/gl_hwtexture.cpp @@ -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); diff --git a/src/rendering/hwrenderer/textures/hw_texcontainer.h b/src/rendering/hwrenderer/textures/hw_texcontainer.h index 755fecb6b..87abb95ae 100644 --- a/src/rendering/hwrenderer/textures/hw_texcontainer.h +++ b/src/rendering/hwrenderer/textures/hw_texcontainer.h @@ -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 diff --git a/src/rendering/hwrenderer/utility/hw_draw2d.cpp b/src/rendering/hwrenderer/utility/hw_draw2d.cpp index 18955c2cd..d34742c03 100644 --- a/src/rendering/hwrenderer/utility/hw_draw2d.cpp +++ b/src/rendering/hwrenderer/utility/hw_draw2d.cpp @@ -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 diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index a9d03e904..f7b1bc6fd 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -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); diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index 479b5d145..285d8d4c6 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -284,7 +284,7 @@ struct DrawParms double left; float Alpha; PalEntry fillcolor; - FRemapTable *remap; + int TranslationId; PalEntry colorOverlay; PalEntry color; INTBOOL alphaChannel; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 27882402e..125cc441d 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -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); diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 02e6d4fce..64884c018 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1047,6 +1047,7 @@ enum ETranslationTable TRANSLATION_Blood, TRANSLATION_RainPillar, TRANSLATION_Custom, + TRANSLATION_Font, }; enum EFindFloorCeiling From 15d4fb8fcd86052216e0fd75f2bed5defb3bb961 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Mar 2020 07:57:59 +0100 Subject: [PATCH 29/30] - fixed file existence check in TRNSLATE parser. --- src/r_data/r_translate.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index f22402720..ed5ce9bc3 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1550,29 +1550,29 @@ void R_ParseTrnslate() do { sc.MustGetToken(TK_StringConst); - try + int pallump = Wads.CheckNumForFullName(sc.String, true, ns_global); + if (pallump >= 0) // { - int pallump = Wads.CheckNumForFullName(sc.String, true, ns_global); - if (pallump) // + int start = 0; + if (sc.CheckToken(',')) { - 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); + sc.MustGetValue(false); + start = sc.Number; } - else + uint8_t palette[768]; + int numcolors = ReadPalette(pallump, palette); + NewTranslation.AddColors(start, numcolors, palette); + } + else + { + try { NewTranslation.AddToTranslation(sc.String); } - } - catch (CRecoverableError & err) - { - sc.ScriptMessage("Error in translation '%s':\n" TEXTCOLOR_YELLOW "%s\n", sc.String, err.GetMessage()); + catch (CRecoverableError & err) + { + sc.ScriptMessage("Error in translation '%s':\n" TEXTCOLOR_YELLOW "%s\n", sc.String, err.GetMessage()); + } } } while (sc.CheckToken(',')); From d32e0b91c2eb7bbd4dd354f90b5160438ea7ada0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Mar 2020 08:50:00 +0100 Subject: [PATCH 30/30] - clear the screen before drawing content, not afterward. The intermission screens got it wrong and drew the black border over the image. --- src/intermission/intermission.cpp | 4 +--- src/wi_stuff.cpp | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 2db845748..2012d9c34 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -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); } } @@ -756,7 +754,6 @@ void DIntermissionScreenScroller::Drawer () DTA_Masked, false, TAG_DONE); - screen->FillBorder (NULL); mBackground = mSecondPic; } else @@ -921,6 +918,7 @@ void DIntermissionController::Drawer () { if (mScreen != NULL) { + screen->FillBorder(nullptr); mScreen->Drawer(); } } diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 9c666fec9..4a5cf4866 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -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.