From ff0b87932356181232e9912c512d98288e91596d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 00:31:25 +0200 Subject: [PATCH 01/16] - added UDMF portal flags. Names are identical with Eternity for compatibility reasons. --- specs/udmf_zdoom.txt | 13 +++++++++++ src/namedef.h | 15 ++++++++++++ src/p_udmf.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 611a667af..9662af1bb 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -214,6 +214,19 @@ Note: All fields default to false unless mentioned otherwise. damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' + + portal_ceil_alpha = // translucency of ceiling portal (default is 0 (not visible)) + portal_ceil_blocksound = // ceiling portal blocks sound. + portal_ceil_disabled = // ceiling portal disabled. + portal_ceil_nopass = // ceiling portal blocks movement if true. + portal_ceil_norender = // ceiling portal not rendered. + portal_ceil_overlaytype = // defines translucency style, can either be "translucent" or "additive". Default is "translucent". + portal_floor_alpha = // translucency of floor portal (default is 0 (not visible)) + portal_floor_blocksound = // floor portal blocks sound. + portal_floor_disabled = // floor portal disabled. + portal_floor_nopass = // ceiling portal blocks movement if true. + portal_floor_norender = // ceiling portal not rendered. + portal_floor_overlaytype = // defines translucency style, can either be "translucent" or "additive". Default is "translucent". * Note about dropactors diff --git a/src/namedef.h b/src/namedef.h index c8b0d1524..36953e385 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -507,6 +507,21 @@ xx(Alphaceiling) xx(Renderstylefloor) xx(Renderstyleceiling) xx(Waterzone) +xx(portal_ceil_alpha) +xx(portal_ceil_blocksound) +xx(portal_ceil_disabled) +xx(portal_ceil_nopass) +xx(portal_ceil_norender) +xx(portal_ceil_overlaytype) +xx(portal_ceil_useglobaltex) +xx(portal_floor_alpha) +xx(portal_floor_blocksound) +xx(portal_floor_disabled) +xx(portal_floor_nopass) +xx(portal_floor_norender) +xx(portal_floor_overlaytype) +xx(portal_floor_useglobaltex) + xx(offsetx_top) xx(offsety_top) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index c09debc51..c1a64f84b 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1568,6 +1568,60 @@ public: tagstring = CheckString(key); break; + case NAME_portal_ceil_alpha: + sec->planes[sector_t::ceiling].alpha = CheckFloat(key); + break; + + case NAME_portal_ceil_blocksound: + Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_BLOCKSOUND, key); + break; + + case NAME_portal_ceil_disabled: + Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_DISABLED, key); + break; + + case NAME_portal_ceil_nopass: + Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_NOPASS, key); + break; + + case NAME_portal_ceil_norender: + Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_NORENDER, key); + break; + + case NAME_portal_ceil_overlaytype: + if (!stricmp(CheckString(key), "translucent")) sec->planes[sector_t::ceiling].Flags &= ~PLANEF_ADDITIVE; + else if (!stricmp(CheckString(key), "additive")) sec->planes[sector_t::ceiling].Flags |= PLANEF_ADDITIVE; + break; + + case NAME_portal_floor_alpha: + sec->planes[sector_t::floor].alpha = CheckFloat(key); + break; + + case NAME_portal_floor_blocksound: + Flag(sec->planes[sector_t::floor].Flags, PLANEF_BLOCKSOUND, key); + break; + + case NAME_portal_floor_disabled: + Flag(sec->planes[sector_t::floor].Flags, PLANEF_DISABLED, key); + break; + + case NAME_portal_floor_nopass: + Flag(sec->planes[sector_t::floor].Flags, PLANEF_NOPASS, key); + break; + + case NAME_portal_floor_norender: + Flag(sec->planes[sector_t::floor].Flags, PLANEF_NORENDER, key); + break; + + case NAME_portal_floor_overlaytype: + if (!stricmp(CheckString(key), "translucent")) sec->planes[sector_t::floor].Flags &= ~PLANEF_ADDITIVE; + else if (!stricmp(CheckString(key), "additive")) sec->planes[sector_t::floor].Flags |= PLANEF_ADDITIVE; + break; + + // These two are used by Eternity for something I do not understand. + //case NAME_portal_ceil_useglobaltex: + //case NAME_portal_floor_useglobaltex: + default: break; } From 80f2f5829f50a6ae7094c6b8989d680dee59375e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 00:43:05 +0200 Subject: [PATCH 02/16] - added A_SetRenderStyle function which replaces A_SetTranslucent. A_SetTranslucent had to be deprecated due to obsolete semantics of the renderstyle argument. --- src/thingdef/thingdef_codeptr.cpp | 16 ++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + wadsrc/static/actors/constants.txt | 20 +++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 153c3b597..ee64df4d0 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3322,6 +3322,22 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslucent) return 0; } +//=========================================================================== +// +// A_SetRenderStyle +// +//=========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRenderStyle) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(alpha); + PARAM_INT_OPT(mode) { mode = 0; } + + self->Alpha = clamp(alpha, 0., 1.); + self->RenderStyle = ERenderStyle(mode); + return 0; +} + //=========================================================================== // // A_FadeIn diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 3354b91d6..fc73b02f3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -218,6 +218,7 @@ ACTOR Actor native //: Thinker native void A_LogInt(int whattoprint); native void A_LogFloat(float whattoprint); native void A_SetTranslucent(float alpha, int style = 0); + native void A_SetRenderStyle(float alpha, int style = 0); action native A_FadeIn(float reduce = 0.1, int flags = 0); action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true native void A_FadeTo(float target, float amount = 0.1, int flags = 0); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index bd6d65643..dce2488c2 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -689,4 +689,22 @@ enum VRF_NOANGLE = VRF_NOANGLESTART|VRF_NOANGLEEND, VRF_NOPITCH = VRF_NOPITCHSTART|VRF_NOPITCHEND, -}; \ No newline at end of file +}; + +enum +{ + STYLE_None, + STYLE_Normal, + STYLE_Fuzzy, + STYLE_SoulTrans, + STYLE_OptFuzzy, + STYLE_Stencil, + STYLE_Translucent, + STYLE_Add, + STYLE_Shaded, + STYLE_TranslucentStencil, + STYLE_Shadow, + STYLE_Subtract, + STYLE_AddStencil, + STYLE_AddShaded, +}; From 51ffd6d9c64eb2ae5fdf572c32087337ab1042c8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 01:00:07 +0200 Subject: [PATCH 03/16] - fixed some warnings. - A_SetRenderStyle should not default to STYLE_None. --- src/p_mobj.cpp | 2 +- src/serializer.cpp | 1 - wadsrc/static/actors/actor.txt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 90a800fa7..e39a07b2d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3526,7 +3526,7 @@ void AActor::Tick () sector_t *sec = node->m_sector; DVector2 scrollv; - if (level.Scrolls.Size() > (sec-sectors)) + if (level.Scrolls.Size() > unsigned(sec-sectors)) { scrollv = level.Scrolls[sec - sectors]; } diff --git a/src/serializer.cpp b/src/serializer.cpp index 47e096b7b..a4714292a 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -821,7 +821,6 @@ void FSerializer::WriteObjects() for (unsigned i = 0; i < w->mDObjects.Size(); i++) { auto obj = w->mDObjects[i]; - player_t *player; BeginObject(nullptr); w->Key("classtype"); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index fc73b02f3..713e1497f 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -218,7 +218,7 @@ ACTOR Actor native //: Thinker native void A_LogInt(int whattoprint); native void A_LogFloat(float whattoprint); native void A_SetTranslucent(float alpha, int style = 0); - native void A_SetRenderStyle(float alpha, int style = 0); + native void A_SetRenderStyle(float alpha, int style); action native A_FadeIn(float reduce = 0.1, int flags = 0); action native A_FadeOut(float reduce = 0.1, int flags = 1); //bool remove == true native void A_FadeTo(float target, float amount = 0.1, int flags = 0); From 944ae2bc09497f52ad6e81354b4f74bc6ece67d5 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 1 Oct 2016 21:47:15 -0500 Subject: [PATCH 04/16] Only generate the self==stateowner check inside action functions --- src/thingdef/thingdef.cpp | 2 +- src/thingdef/thingdef_expression.cpp | 2 +- src/zscript/vmbuilder.cpp | 3 ++- src/zscript/vmbuilder.h | 5 ++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 635637149..32d4f1ce0 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -288,7 +288,7 @@ static void FinishThingdef() if (func == nullptr) { - VMFunctionBuilder buildit; + VMFunctionBuilder buildit(true); assert(tcall->Proto != nullptr); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 695b12799..72a4ae30b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3373,7 +3373,7 @@ FxExpression *FxClassMember::Resolve(FCompileContext &ctx) ExpEmit FxClassMember::Emit(VMFunctionBuilder *build) { - if (~membervar->Flags & VARF_Native) + if (build->IsActionFunc && ~membervar->Flags & VARF_Native) { // Check if this is a user-defined variable. // As of right now, FxClassMember is only ever used with FxSelf. // This very user variable was defined in stateowner so if diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index eb49ffb14..8d7b5a8c1 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -6,7 +6,7 @@ // //========================================================================== -VMFunctionBuilder::VMFunctionBuilder() +VMFunctionBuilder::VMFunctionBuilder(bool selfcheck) { NumIntConstants = 0; NumFloatConstants = 0; @@ -14,6 +14,7 @@ VMFunctionBuilder::VMFunctionBuilder() NumStringConstants = 0; MaxParam = 0; ActiveParam = 0; + IsActionFunc = selfcheck; } //========================================================================== diff --git a/src/zscript/vmbuilder.h b/src/zscript/vmbuilder.h index 2d8721acc..ed2516c2a 100644 --- a/src/zscript/vmbuilder.h +++ b/src/zscript/vmbuilder.h @@ -23,7 +23,7 @@ public: friend class VMFunctionBuilder; }; - VMFunctionBuilder(); + VMFunctionBuilder(bool checkself = false); ~VMFunctionBuilder(); VMScriptFunction *MakeFunction(); @@ -60,6 +60,9 @@ public: // Track available registers. RegAvailability Registers[4]; + // For use by DECORATE's self/stateowner sanitizer. + bool IsActionFunc; + private: struct AddrKonst { From eb2ee339503112a0db5059c866b925cb49bdbb43 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 1 Oct 2016 22:29:57 -0500 Subject: [PATCH 05/16] FxVMFunctionCall must pass null pointers when calling an action function from a non-action function --- src/thingdef/thingdef_expression.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 72a4ae30b..3851d05cc 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3948,15 +3948,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) //========================================================================== // -// Assumption: This call is being made to generate code inside an action -// method, so the first three address registers are all set up for such a -// function. (self, stateowner, callingstate) +// Assumption: This call is being generated inside a function whose a0 +// register is a self pointer. For action functions, a1 maps to stateowner +// and a2 maps to callingstate. (self, stateowner, callingstate) // //========================================================================== ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { - assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3); + assert((build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= NAP) || + (!build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 1)); int count = (ArgList ? ArgList->Size() : 0); if (count == 1) @@ -3975,8 +3976,18 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) } if (Function->Flags & VARF_Action) { - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); - build->Emit(OP_PARAM, 0, REGT_POINTER, 2); + static_assert(NAP == 3, "This code needs to be updated if NAP changes"); + if (build->IsActionFunc) + { + build->Emit(OP_PARAM, 0, REGT_POINTER, 1); + build->Emit(OP_PARAM, 0, REGT_POINTER, 2); + } + else + { + int null = build->GetConstantAddress(nullptr, ATAG_GENERIC); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null); + } count += 2; } // Emit code to pass explicit parameters From efc9ed2fe9685a448af32065935eb33228c011c3 Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Sat, 1 Oct 2016 22:31:07 -0500 Subject: [PATCH 06/16] Fix state lookup from non-action functions (i.e. Damage functions) --- src/thingdef/thingdef_expression.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 3851d05cc..700ac94bb 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4978,7 +4978,8 @@ static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numpa ExpEmit FxRuntimeStateIndex::Emit(VMFunctionBuilder *build) { - assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3); + assert(build->IsActionFunc && build->Registers[REGT_POINTER].GetMostUsed() >= 3 && + "FxRuntimeStateIndex is only valid inside action functions"); ExpEmit out(build, REGT_POINTER); @@ -5150,7 +5151,14 @@ int DecoFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, V ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) { ExpEmit dest(build, REGT_POINTER); - build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner + if (build->IsActionFunc) + { + build->Emit(OP_PARAM, 0, REGT_POINTER, 1); // pass stateowner + } + else + { + build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self + } for (unsigned i = 0; i < names.Size(); ++i) { build->EmitParamInt(names[i]); From d7683a8c552fc38720967dedb4a89b0f0908c06f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 2 Oct 2016 10:13:45 +0300 Subject: [PATCH 07/16] Fixed crash on early fatal error exit Process terminates correctly if zdoom.pk3 is missing --- src/dobject.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index 8fba75aa6..4acb86ce4 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -330,7 +330,11 @@ DObject::~DObject () } } } - type->DestroySpecials(this); + + if (nullptr != type) + { + type->DestroySpecials(this); + } } } From a505e910321cc55f03e1fd3211ed68761bfb1bc8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 13:35:25 +0200 Subject: [PATCH 08/16] - added TRNSLATE lump for defining global translations which are accessible by name. This is only the definition part, manipulation functions for ACS and DECORATE still to do. --- src/d_main.cpp | 1 + src/r_data/r_translate.cpp | 101 +++++++++++++++++++++++++-- src/r_data/r_translate.h | 6 +- src/thingdef/thingdef_properties.cpp | 7 +- 4 files changed, 104 insertions(+), 11 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 2dbf1273c..dad2b86d9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2439,6 +2439,7 @@ void D_DoomMain (void) if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); TeamLibrary.ParseTeamInfo (); + R_ParseTrnslate(); PClassActor::StaticInit (); // [GRB] Initialize player class list diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index c55f69016..bf9365002 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -609,26 +609,26 @@ void FRemapTable::AddToTranslation(const char *range) // //---------------------------------------------------------------------------- -int FRemapTable::StoreTranslation() +int FRemapTable::StoreTranslation(int slot) { unsigned int i; - for (i = 0; i < translationtables[TRANSLATION_Decorate].Size(); i++) + for (i = 0; i < translationtables[slot].Size(); i++) { - if (*this == *translationtables[TRANSLATION_Decorate][i]) + if (*this == *translationtables[slot][i]) { // A duplicate of this translation already exists - return TRANSLATION(TRANSLATION_Decorate, i); + return TRANSLATION(slot, i); } } - if (translationtables[TRANSLATION_Decorate].Size() >= MAX_DECORATE_TRANSLATIONS) + if (translationtables[slot].Size() >= MAX_DECORATE_TRANSLATIONS) { I_Error("Too many DECORATE translations"); } FRemapTable *newtrans = new FRemapTable; *newtrans = *this; - i = translationtables[TRANSLATION_Decorate].Push(newtrans); - return TRANSLATION(TRANSLATION_Decorate, i); + i = translationtables[slot].Push(newtrans); + return TRANSLATION(slot, i); } @@ -1188,3 +1188,90 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL); } + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- +static TMap customTranslationMap; + +int R_FindCustomTranslation(const char *name) +{ + if (name == nullptr) + { + return -1; + } + // Ice is a special case which will remain in its original slot. + if (!stricmp(name, "Ice")) + { + return TRANSLATION(TRANSLATION_Standard, 7); + } + int *t = customTranslationMap.CheckKey(FName(name, true)); + return (t != nullptr)? *t : -1; +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +void R_ParseTrnslate() +{ + customTranslationMap.Clear(); + translationtables[TRANSLATION_Custom].Clear(); + + int lump; + int lastlump = 0; + while (-1 != (lump = Wads.FindLump("TRNSLATE", &lastlump))) + { + FScanner sc(lump); + while (sc.GetToken()) + { + sc.TokenMustBe(TK_Identifier); + + FName newtrans = sc.String; + FRemapTable *base = nullptr; + if (sc.CheckToken(':')) + { + sc.MustGetAnyToken(); + if (sc.TokenType == TK_IntConst) + { + int max = 6; + if (sc.Number < 0 || sc.Number > max) + { + sc.ScriptError("Translation must be in the range [0,%d]", max); + } + base = translationtables[TRANSLATION_Standard][sc.Number]; + } + else if (sc.TokenType == TK_Identifier) + { + int tnum = R_FindCustomTranslation(sc.String); + if (tnum == -1) + { + sc.ScriptError("Base translation '%s' not found in '%s'", sc.String, newtrans.GetChars()); + } + base = translationtables[GetTranslationType(tnum)][GetTranslationIndex(tnum)]; + } + else + { + // error out. + sc.TokenMustBe(TK_Identifier); + } + } + sc.MustGetToken('='); + FRemapTable NewTranslation; + if (base != nullptr) NewTranslation = *base; + else NewTranslation.MakeIdentity(); + do + { + sc.MustGetToken(TK_StringConst); + NewTranslation.AddToTranslation(sc.String); + } while (sc.CheckToken(',')); + + int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom); + customTranslationMap[newtrans] = trans; + } + } +} diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index a549f0759..4ca2f203f 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -19,6 +19,7 @@ enum TRANSLATION_Decorate, TRANSLATION_Blood, TRANSLATION_RainPillar, + TRANSLATION_Custom, NUM_TRANSLATION_TABLES }; @@ -42,7 +43,7 @@ struct FRemapTable void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2); void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2); void AddToTranslation(const char * range); - int StoreTranslation(); + int StoreTranslation(int slot); BYTE *Remap; // For the software renderer PalEntry *Palette; // The ideal palette this maps to @@ -109,6 +110,9 @@ extern TArray BloodTranslationColors; int CreateBloodTranslation(PalEntry color); +int R_FindCustomTranslation(const char *name); +void R_ParseTrnslate(); + #endif // __R_TRANSLATE_H diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 927e3e537..d60cda823 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1100,9 +1100,10 @@ DEFINE_PROPERTY(translation, L, Actor) for(int i = 1; i < PROP_PARM_COUNT; i++) { PROP_STRING_PARM(str, i); - if (i== 1 && PROP_PARM_COUNT == 2 && !stricmp(str, "Ice")) + int tnum; + if (i== 1 && PROP_PARM_COUNT == 2 && (tnum = R_FindCustomTranslation(str)) != -1) { - defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7); + defaults->Translation = tnum; return; } else @@ -1110,7 +1111,7 @@ DEFINE_PROPERTY(translation, L, Actor) CurrentTranslation.AddToTranslation(str); } } - defaults->Translation = CurrentTranslation.StoreTranslation (); + defaults->Translation = CurrentTranslation.StoreTranslation (TRANSLATION_Decorate); } } From 0bce6e39256c7054918dfe0302b83b574051e034 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 14:09:45 +0200 Subject: [PATCH 09/16] - added ACS and DECORATE setter functions for named translations. --- src/actor.h | 3 +++ src/p_acs.cpp | 23 ++++++++++++++++++++++- src/p_mobj.cpp | 17 +++++++++++++++++ src/thingdef/thingdef_codeptr.cpp | 15 +++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/actor.h b/src/actor.h index dbb308258..3f7c1178e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -755,6 +755,9 @@ public: // What species am I? virtual FName GetSpecies(); + // set translation + void SetTranslation(const char *trname); + double GetBobOffset(double ticfrac = 0) const { if (!(flags2 & MF2_FLOATBOB)) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1b52f5a93..0a2ccddac 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4379,10 +4379,11 @@ enum EACSFunctions ACSF_CheckClass = 200, ACSF_DamageActor, // [arookas] ACSF_SetActorFlag, + ACSF_SetTranslation, // ZDaemon ACSF_GetTeamScore = 19620, // (int team) - ACSF_SetTeamScore, // (int team, int value) + ACSF_SetTeamScore, // (int team, int value }; int DLevelScript::SideFromID(int id, int side) @@ -6002,6 +6003,26 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) return count; } + case ACSF_SetTranslation: + { + int tid = args[0]; + const char *trname = FBehavior::StaticLookupString(args[1]); + if (tid == 0) + { + if (activator != nullptr) + activator->SetTranslation(trname); + } + else + { + FActorIterator it(tid); + while ((actor = it.Next()) != nullptr) + { + actor->SetTranslation(trname); + } + } + return 1; + } + default: break; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e39a07b2d..496f52e86 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6525,6 +6525,23 @@ int AActor::ApplyDamageFactor(FName damagetype, int damage) const } +void AActor::SetTranslation(const char *trname) +{ + if (*trname == 0) + { + // an empty string resets to the default + Translation = GetDefault()->Translation; + return; + } + + int tnum = R_FindCustomTranslation(trname); + if (tnum >= 0) + { + Translation = tnum; + } + // silently ignore if the name does not exist, this would create some insane message spam otherwise. +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index ee64df4d0..3b4e6203e 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -7412,3 +7412,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetVisibleRotation) ACTION_RETURN_BOOL(true); } + +//========================================================================== +// +// +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTranslation) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(trname); + + self->SetTranslation(trname); + return 0; +} diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 713e1497f..c82be96cd 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -344,6 +344,7 @@ ACTOR Actor native //: Thinker action native bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); action native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); action native bool A_SetVisibleRotation(float anglestart = 0, float angleend = 0, float pitchstart = 0, float pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); + native void A_SetTranslation(string transname); native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); From 865863ab6fb2d8cd464bc6637955eaf11bb41b57 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 14:37:26 +0200 Subject: [PATCH 10/16] - fixed: AFastProjectile did not work properly for perfectly vertically moving missiles. Like AActor::Tick it needs to ensure that a tiny bit of lateral movement is present so that collision detection and the Effect() function work as intended. --- src/g_shared/a_fastprojectile.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index c1253f966..ec736bfea 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -54,6 +54,12 @@ void AFastProjectile::Tick () // Handle movement if (!Vel.isZero() || (Z() != floorz)) { + // force some lateral movement so that collision detection works as intended. + if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage()) + { + Vel.X = MinVel; + } + frac = Vel / count; changexy = frac.X != 0 || frac.Y != 0; int ripcount = count / 8; From 3418710a383d18323d0e9aa37e171a1ca0b15db9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 14:38:48 +0200 Subject: [PATCH 11/16] - be a bit more thorough and also call Effect() on vertically moving missiles with zero damage. --- src/g_shared/a_fastprojectile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index ec736bfea..82349c1a7 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -130,7 +130,7 @@ void AFastProjectile::Tick () P_ExplodeMissile (this, NULL, NULL); return; } - if (changexy && ripcount <= 0) + if (!frac.isZero() && ripcount <= 0) { ripcount = count >> 3; Effect(); From 37d61167ea80e3d7985e984ff9259b5dc7108831 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 18:50:37 +0200 Subject: [PATCH 12/16] - hotfix for a RapidJSON bug: If the Writer tries to process an INF or NaN value, it aborts and leaves the writer in a broken state, unable to recover. Changed so that it writes a 0 value so that the resulting JSON at least parses correctly. --- src/rapidjson/writer.h | 42 +++++++++++++++++++++++++----------------- src/serializer.cpp | 4 ++-- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/rapidjson/writer.h b/src/rapidjson/writer.h index c5a3b98a9..369e7e6ff 100644 --- a/src/rapidjson/writer.h +++ b/src/rapidjson/writer.h @@ -322,22 +322,30 @@ protected: bool WriteDouble(double d) { if (internal::Double(d).IsNanOrInf()) { - if (!(writeFlags & kWriteNanAndInfFlag)) - return false; - if (internal::Double(d).IsNan()) { - PutReserve(*os_, 3); - PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); - return true; - } - if (internal::Double(d).Sign()) { - PutReserve(*os_, 9); - PutUnsafe(*os_, '-'); - } - else - PutReserve(*os_, 8); - PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); - PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); - return true; + bool ret = true; + if (!(writeFlags & kWriteNanAndInfFlag)) + { + // if we abort here, the writer is left in a broken state, unable to recover, so better write a 0 in addition to returning an error. + ret = false; + d = 0; + } + else + { + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } } char buffer[25]; @@ -345,7 +353,7 @@ protected: PutReserve(*os_, static_cast(end - buffer)); for (char* p = buffer; p != end; ++p) PutUnsafe(*os_, static_cast(*p)); - return true; + return ret; } bool WriteString(const Ch* str, SizeType length) { diff --git a/src/serializer.cpp b/src/serializer.cpp index a4714292a..7861701c0 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -217,11 +217,11 @@ struct FWriter { if (mWriter1) { - if (!mWriter1->Double(k)) mWriter1->Double(0); + mWriter1->Double(k); } else if (mWriter2) { - if (!mWriter2->Double(k)) mWriter2->Double(0); + mWriter2->Double(k); } } From e84a7de390f1b9de1d178d18f76f1a534bb3afee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Oct 2016 18:56:04 +0200 Subject: [PATCH 13/16] - variable was in the wrong scope. --- src/rapidjson/writer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rapidjson/writer.h b/src/rapidjson/writer.h index 369e7e6ff..a8eeab66d 100644 --- a/src/rapidjson/writer.h +++ b/src/rapidjson/writer.h @@ -321,8 +321,8 @@ protected: } bool WriteDouble(double d) { - if (internal::Double(d).IsNanOrInf()) { - bool ret = true; + bool ret = true; + if (internal::Double(d).IsNanOrInf()) { if (!(writeFlags & kWriteNanAndInfFlag)) { // if we abort here, the writer is left in a broken state, unable to recover, so better write a 0 in addition to returning an error. From 1620ff58c8f5f3f63bf3a71ff9f1320164545d1d Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 2 Oct 2016 12:24:48 -0500 Subject: [PATCH 14/16] Added INTCVAR to DrawNumber. - Allows retrieval and displaying of an int/bool user/server cvar. --- src/g_shared/sbarinfo_commands.cpp | 53 +++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index b7827f6bd..13c98d833 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1021,7 +1021,7 @@ class CommandDrawNumber : public CommandDrawString usePrefix(false), interpolationSpeed(0), drawValue(0), length(3), lowValue(-1), lowTranslation(CR_UNTRANSLATED), highValue(-1), highTranslation(CR_UNTRANSLATED), value(CONSTANT), - inventoryItem(NULL) + inventoryItem(NULL), cvarName(nullptr) { } @@ -1166,6 +1166,37 @@ class CommandDrawNumber : public CommandDrawString if(parenthesized) sc.MustGetToken(')'); } + else if (sc.Compare("intcvar")) + { + bool parenthesized = sc.CheckToken('('); + + value = INTCVAR; + + if (!parenthesized || !sc.CheckToken(TK_StringConst)) + sc.MustGetToken(TK_Identifier); + + cvarName = sc.String; + + // We have a name, but make sure it exists. If not, send notification so modders + // are aware of the situation. + FBaseCVar *CVar = FindCVar(cvarName, nullptr); + + if (CVar != nullptr) + { + ECVarType cvartype = CVar->GetRealType(); + + if (!(cvartype == CVAR_Bool || cvartype == CVAR_Int)) + { + sc.ScriptMessage("CVar '%s' is not an int or bool", cvarName); + } + } + else + { + sc.ScriptMessage("CVar '%s' does not exist", cvarName); + } + + if (parenthesized) sc.MustGetToken(')'); + } } if(value == INVENTORY) { @@ -1444,6 +1475,24 @@ class CommandDrawNumber : public CommandDrawString num++; } break; + case INTCVAR: + { + FBaseCVar *CVar = GetCVar(statusBar->CPlayer->mo, cvarName); + if (CVar != nullptr) + { + ECVarType cvartype = CVar->GetRealType(); + + if (cvartype == CVAR_Bool || cvartype == CVAR_Int) + { + num = CVar->GetGenericRep(CVAR_Int).Int; + break; + } + } + + // Fallback in case of bad cvar/type. Unset can remove a cvar at will. + num = 0; + break; + } default: break; } if(interpolationSpeed != 0 && (!hudChanged || level.time == 1)) @@ -1522,6 +1571,7 @@ class CommandDrawNumber : public CommandDrawString ACCURACY, STAMINA, KEYS, + INTCVAR, CONSTANT }; @@ -1544,6 +1594,7 @@ class CommandDrawNumber : public CommandDrawString PClassActor *inventoryItem; FString prefixPadding; + FString cvarName; friend class CommandDrawInventoryBar; }; From 671646be26ef8d6cdcef12f198a92d297f7b215f Mon Sep 17 00:00:00 2001 From: "N.E.C" Date: Sun, 2 Oct 2016 13:05:26 -0700 Subject: [PATCH 15/16] Fix errors encountered when compiling for v140_xp target --- src/CMakeLists.txt | 45 +++++++++++++++++++++++++++++------------- src/win32/i_xinput.cpp | 6 ++++++ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab5f137ef..03299bb0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,8 @@ endif() include( CheckCXXSourceCompiles ) include( CheckFunctionExists ) include( CheckCXXCompilerFlag ) +include( CheckIncludeFile ) +include( CheckIncludeFiles ) include( CheckLibraryExists ) include( FindPkgConfig ) @@ -118,7 +120,13 @@ if( WIN32 ) PATHS ENV DXSDK_DIR PATH_SUFFIXES Include ) if( NOT D3D_INCLUDE_DIR ) - message( SEND_ERROR "Could not find DirectX 9 header files" ) + # Modern versions of the Windows SDK include d3d9.h. Unfortunately, + # CMake cannot find this file via find_path, so we check for it using + # CHECK_INCLUDE_FILE. + CHECK_INCLUDE_FILE( d3d9.h D3D9_H_FOUND ) + if ( NOT D3D9_H_FOUND ) + message( SEND_ERROR "Could not find DirectX 9 header files" ) + endif() else() include_directories( ${D3D_INCLUDE_DIR} ) endif() @@ -127,35 +135,41 @@ if( WIN32 ) PATHS ENV DXSDK_DIR PATH_SUFFIXES Include ) if( NOT XINPUT_INCLUDE_DIR ) - message( WARNING "Could not find xinput.h. XInput will be disabled." ) - add_definitions( -DNO_XINPUT ) + # Modern versions of the Windows SDK include xinput.h. Unfortunately, + # CMake cannot find this file via find_path, so we check for it using + # CHECK_INCLUDE_FILES. windows.h must be included before xinput.h. + CHECK_INCLUDE_FILES( "windows.h;xinput.h" XINPUT_H_FOUND ) + if( NOT XINPUT_H_FOUND ) + message( WARNING "Could not find xinput.h. XInput will be disabled." ) + add_definitions( -DNO_XINPUT ) + endif() else() include_directories( ${XINPUT_INCLUDE_DIR} ) endif() - find_library( DX_dxguid_LIBRARY dxguid - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) find_library( DX_dinput8_LIBRARY dinput8 PATHS ENV DXSDK_DIR PATH_SUFFIXES Lib Lib/${XBITS} ) + find_library( DX_dxguid_LIBRARY dxguid + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Lib Lib/${XBITS} ) - set( DX_LIBS_FOUND YES ) - if( NOT DX_dxguid_LIBRARY ) - set( DX_LIBS_FOUND NO ) - endif() + # Modern versions of the Windows SDK include dinput8.lib. Unfortunately, + # CMake cannot find these libraries via find_library. if( NOT DX_dinput8_LIBRARY ) - set( DX_LIBS_FOUND NO ) + # If we got this far, assume dinput8.lib is in the system library path. + set( DX_dinput8_LIBRARY dinput8 ) endif() - if( NOT DX_LIBS_FOUND ) - message( FATAL_ERROR "Could not find DirectX 9 libraries" ) + # Modern versions of the Windows SDK do NOT include dxguid.lib. Its contents + # were moved to dinput8.lib. + if( NOT DX_dxguid_LIBRARY ) + message( STATUS "Could not find dxguid.lib. Build may fail on old Windows SDKs.") endif() set( ZDOOM_LIBS wsock32 winmm - "${DX_dxguid_LIBRARY}" "${DX_dinput8_LIBRARY}" ole32 user32 @@ -166,6 +180,9 @@ if( WIN32 ) setupapi oleaut32 DelayImp ) + if( DX_dxguid_LIBRARY ) + list( APPEND ZDOOM_LIBS "${DX_dxguid_LIBRARY}" ) + endif() else() if( APPLE ) set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) diff --git a/src/win32/i_xinput.cpp b/src/win32/i_xinput.cpp index b00b4c510..1180f9f32 100644 --- a/src/win32/i_xinput.cpp +++ b/src/win32/i_xinput.cpp @@ -27,6 +27,12 @@ // MACROS ------------------------------------------------------------------ +// This macro is defined by newer versions of xinput.h. In case we are +// compiling with an older version, define it here. +#ifndef XUSER_MAX_COUNT +#define XUSER_MAX_COUNT 4 +#endif + // TYPES ------------------------------------------------------------------- typedef DWORD (WINAPI *XInputGetStateType)(DWORD index, XINPUT_STATE *state); From 201ae3c60f22be1bfd80a33c3968401c7ae804ce Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 30 Sep 2016 15:02:22 -0500 Subject: [PATCH 16/16] Added OverlayID() for retrieving psprite layer numbers. --- src/p_pspr.cpp | 19 +++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 2 files changed, 20 insertions(+) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 67a447f61..fab7e38d8 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1049,6 +1049,25 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) return 0; } +//--------------------------------------------------------------------------- +// +// PROC OverlayID +// Because non-action functions cannot acquire the ID of the overlay... +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, OverlayID) +{ + PARAM_ACTION_PROLOGUE; + + if (ACTION_CALL_FROM_PSPRITE()) + { + ACTION_RETURN_INT(stateinfo->mPSPIndex); + } + ACTION_RETURN_INT(0); +} + + + //--------------------------------------------------------------------------- // // PROC A_Lower diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index c82be96cd..44b801f51 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -57,6 +57,7 @@ ACTOR Actor native //: Thinker native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); + action native int OverlayID(); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support.