From 5907ff662d6cd3a5f574150cfb93fb5794a30456 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Fri, 1 Jul 2016 05:41:14 +0200 Subject: [PATCH 01/26] Added a new state that the weapon jumps to when it is lowered all the way and the player is currently dead The state is undefined by default to preserve the original behavior of having the weapon layer deleted which modders can now avoid by defining it properly --- src/namedef.h | 1 + src/p_pspr.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/namedef.h b/src/namedef.h index 17fa9e291..cd0d5615b 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -214,6 +214,7 @@ xx(Brainexplode) // Weapon animator names. xx(Select) xx(Deselect) +xx(DeadLowered) xx(Ready) xx(Fire) xx(Hold) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 350acc3fd..48ead3699 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -1087,7 +1087,7 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) { // Player is dead, so don't bring up a pending weapon // Player is dead, so keep the weapon off screen P_SetPsprite(player, PSP_FLASH, nullptr); - psp->SetState(nullptr); + psp->SetState(player->ReadyWeapon->FindState(NAME_DeadLowered)); return 0; } // [RH] Clear the flash state. Only needed for Strife. From 6ada8aa6444039b76321dc39bcc92b3d2ed9c710 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Thu, 28 Jul 2016 15:55:49 -0500 Subject: [PATCH 02/26] Fixed A_CopySpriteFrame not working under certain circumstances. --- src/thingdef/thingdef_codeptr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d1933e142..bf2a5983b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -7202,7 +7202,7 @@ enum CPSFFlags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) { - PARAM_SELF_PROLOGUE(AActor); + PARAM_ACTION_PROLOGUE; PARAM_INT(from); PARAM_INT(to); PARAM_INT_OPT(flags) { flags = 0; } From dfed6ac1fb93ac182cb62deb347fa65ae00fe034 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Thu, 28 Jul 2016 15:52:20 -0500 Subject: [PATCH 03/26] Added SpriteAngle and SpriteRotation properties. - Includes four functions, A_SetSprite(Angle/Rotation) and GetSprite(Angle/Rotation). - SpriteRotation offsets the angle of the sprite, allowing for actors to move backwards or sideways for example. - SpriteAngle requires +SPRITEANGLE and sets the actor's sprite to the absolute rotation found at that angle. Overrides SpriteRotation once the flag is on. --- src/actor.h | 3 + src/p_mobj.cpp | 5 ++ src/r_things.cpp | 20 ++++-- src/thingdef/thingdef_codeptr.cpp | 104 +++++++++++++++++++++++++++ src/thingdef/thingdef_data.cpp | 1 + src/thingdef/thingdef_properties.cpp | 18 +++++ src/version.h | 2 +- wadsrc/static/actors/actor.txt | 6 ++ 8 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/actor.h b/src/actor.h index a9ce18a57..154d14289 100644 --- a/src/actor.h +++ b/src/actor.h @@ -382,6 +382,7 @@ enum ActorFlag7 MF7_ALLOWTHRUFLAGS = 0x00400000, // [MC] Allow THRUACTORS and the likes on puffs to prevent mod breakage. MF7_USEKILLSCRIPTS = 0x00800000, // [JM] Use "KILL" Script on death if not forced by GameInfo. MF7_NOKILLSCRIPTS = 0x01000000, // [JM] No "KILL" Script on death whatsoever, even if forced by GameInfo. + MF7_SPRITEANGLE = 0x02000000, // [MC] Utilize the SpriteAngle property and lock the rotation to the degrees specified. }; // --- mobj.renderflags --- @@ -978,6 +979,8 @@ public: DVector3 __Pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions. DVector3 OldRenderPos; + DAngle SpriteAngle; + DAngle SpriteRotation; DRotator Angles; DVector3 Vel; double Speed; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index be875b951..94df4c3bf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -383,6 +383,11 @@ void AActor::Serialize(FArchive &arc) << RipLevelMin << RipLevelMax; arc << DefThreshold; + if (SaveVersion >= 4549) + { + arc << SpriteAngle; + arc << SpriteRotation; + } { FString tagstr; diff --git a/src/r_things.cpp b/src/r_things.cpp index 3d2133398..78d72fbc8 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -809,11 +809,17 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor angle_t rot; if (sprframe->Texture[0] == sprframe->Texture[1]) { - rot = (ang - thing->Angles.Yaw + 45.0/2*9).BAMs() >> 28; + if (thing->flags7 & MF7_SPRITEANGLE) + rot = (thing->SpriteAngle + 45.0 / 2 * 9).BAMs() >> 28; + else + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + 45.0 / 2 * 9).BAMs() >> 28; } else { - rot = (ang - thing->Angles.Yaw + (45.0/2*9-180.0/16)).BAMs() >> 28; + if (thing->flags7 & MF7_SPRITEANGLE) + rot = (thing->SpriteAngle + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + else + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; } picnum = sprframe->Texture[rot]; if (sprframe->Flip & (1 << rot)) @@ -848,11 +854,17 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor angle_t rot; if (sprframe->Texture[0] == sprframe->Texture[1]) { - rot = (ang - thing->Angles.Yaw + 45.0 / 2 * 9).BAMs() >> 28; + if (thing->flags7 & MF7_SPRITEANGLE) + rot = (thing->SpriteAngle + 45.0 / 2 * 9).BAMs() >> 28; + else + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + 45.0 / 2 * 9).BAMs() >> 28; } else { - rot = (ang - thing->Angles.Yaw + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + if (thing->flags7 & MF7_SPRITEANGLE) + rot = (thing->SpriteAngle + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; + else + rot = (ang - (thing->Angles.Yaw + thing->SpriteRotation) + (45.0 / 2 * 9 - 180.0 / 16)).BAMs() >> 28; } picnum = sprframe->Texture[rot]; if (sprframe->Flip & (1 << rot)) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index bf2a5983b..17c5b5cf5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -395,6 +395,64 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth) return 0; } +//========================================================================== +// +// GetSpriteAngle +// +// NON-ACTION function returns the sprite angle of a pointer. +//========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteAngle) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *target = COPY_AAPTR(self, ptr); + if (target == nullptr) + { + ret->SetFloat(0.0); + } + else + { + const double ang = target->SpriteAngle.Degrees; + ret->SetFloat(ang); + } + return 1; + } + return 0; +} + +//========================================================================== +// +// GetSpriteRotation +// +// NON-ACTION function returns the sprite rotation of a pointer. +//========================================================================== +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetSpriteRotation) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *target = COPY_AAPTR(self, ptr); + if (target == nullptr) + { + ret->SetFloat(0.0); + } + else + { + const double ang = target->SpriteRotation.Degrees; + ret->SetFloat(ang); + } + return 1; + } + return 0; +} + //========================================================================== // // GetZAt @@ -7219,3 +7277,49 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopySpriteFrame) if (!(flags & CPSF_NOFRAME)) copyto->frame = copyfrom->frame; ACTION_RETURN_BOOL(true); } + +//========================================================================== +// +// A_SetSpriteAngle(angle, ptr) +// +// Specifies which angle the actor must always draw its sprite from. +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteAngle) +{ + PARAM_ACTION_PROLOGUE; + PARAM_FLOAT_OPT(angle) { angle = 0.; } + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (mobj == nullptr) + { + ACTION_RETURN_BOOL(false); + } + mobj->SpriteAngle = angle; + ACTION_RETURN_BOOL(true); +} + +//========================================================================== +// +// A_SetSpriteRotation(angle, ptr) +// +// Specifies how much to fake a sprite rotation. +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpriteRotation) +{ + PARAM_ACTION_PROLOGUE; + PARAM_ANGLE_OPT(angle) { angle = 0.; } + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *mobj = COPY_AAPTR(self, ptr); + + if (mobj == nullptr) + { + ACTION_RETURN_BOOL(false); + } + mobj->SpriteRotation = angle; + ACTION_RETURN_BOOL(true); +} diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 0768f80c8..3b114fbee 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -259,6 +259,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF7, ALLOWTHRUFLAGS, AActor, flags7), DEFINE_FLAG(MF7, USEKILLSCRIPTS, AActor, flags7), DEFINE_FLAG(MF7, NOKILLSCRIPTS, AActor, flags7), + DEFINE_FLAG(MF7, SPRITEANGLE, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index db6ef14a0..372f444cd 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1345,6 +1345,24 @@ DEFINE_PROPERTY(gravity, F, Actor) defaults->Gravity = i; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(spriteangle, F, Actor) +{ + PROP_DOUBLE_PARM(i, 0); + defaults->SpriteAngle = i; +} + +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(spriterotation, F, Actor) +{ + PROP_DOUBLE_PARM(i, 0); + defaults->SpriteRotation = i; +} + //========================================================================== // //========================================================================== diff --git a/src/version.h b/src/version.h index 9aa4ad799..cffa25bdd 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4548 +#define SAVEVER 4549 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 77250b3df..1d27ad01a 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -35,6 +35,8 @@ ACTOR Actor native //: Thinker BloodType "Blood", "BloodSplatter", "AxeBlood" ExplosionDamage 128 MissileHeight 32 + SpriteAngle 0 + SpriteRotation 0 // Functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); @@ -48,6 +50,8 @@ ACTOR Actor native //: Thinker native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); native float GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); + native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); + native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. @@ -331,6 +335,8 @@ ACTOR Actor native //: Thinker action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); action native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); action native bool A_CopySpriteFrame(int from, int to, int flags = 0); + action native bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); + action native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); 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 c4eafc1c38c9da6502a3971c2e379821673d3bc8 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Tue, 26 Jul 2016 23:57:26 +0200 Subject: [PATCH 04/26] DECORATE can now handle jump statements break and continue were added but are not yet useable anywhere This was made general enough so that loops and switch statements that accept breaks/continues can be done without much difficulty as well as goto statements with explicit labels if those are ever wanted --- src/thingdef/thingdef_exp.h | 41 +++++++++---- src/thingdef/thingdef_expression.cpp | 90 +++++++++++++++++++++++++--- src/thingdef/thingdef_states.cpp | 12 ++++ 3 files changed, 121 insertions(+), 22 deletions(-) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 58820ea15..3353cad46 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -50,6 +50,7 @@ #define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p) class VMFunctionBuilder; +class FxJumpStatement; //========================================================================== // @@ -59,21 +60,15 @@ class VMFunctionBuilder; struct FCompileContext { - PClassActor *cls; + TArray Jumps; + PClassActor *Class; - FCompileContext(PClassActor *_cls = NULL) - { - cls = _cls; - } + FCompileContext(PClassActor *cls = nullptr); - PSymbol *FindInClass(FName identifier) - { - return cls ? cls->Symbols.FindSymbol(identifier, true) : NULL; - } - PSymbol *FindGlobal(FName identifier) - { - return GlobalSymbols.FindSymbol(identifier, true); - } + PSymbol *FindInClass(FName identifier); + PSymbol *FindGlobal(FName identifier); + + void HandleJumps(int token, FxExpression *handler); }; //========================================================================== @@ -212,6 +207,8 @@ public: virtual ExpEmit Emit(VMFunctionBuilder *build); + TArray JumpAddresses; + FScriptPosition ScriptPosition; PType *ValueType; @@ -930,6 +927,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxJumpStatement +// +//========================================================================== + +class FxJumpStatement : public FxExpression +{ +public: + FxJumpStatement(int token, const FScriptPosition &pos); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); + + int Token; + size_t Address; + FxExpression *AddressResolver; +}; + //========================================================================== // // FxReturnStatement diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index b4a0b3fda..4e13b7beb 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -85,6 +85,45 @@ static const FLOP FxFlops[] = { NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } }, }; +//========================================================================== +// +// FCompileContext +// +//========================================================================== + +FCompileContext::FCompileContext(PClassActor *cls) : Class(cls) +{ +} + +PSymbol *FCompileContext::FindInClass(FName identifier) +{ + return Class ? Class->Symbols.FindSymbol(identifier, true) : nullptr; +} +PSymbol *FCompileContext::FindGlobal(FName identifier) +{ + return GlobalSymbols.FindSymbol(identifier, true); +} + +void FCompileContext::HandleJumps(int token, FxExpression *handler) +{ + for (unsigned int i = 0; i < Jumps.Size(); i++) + { + if (Jumps[i]->Token == token) + { + Jumps[i]->AddressResolver = handler; + handler->JumpAddresses.Push(Jumps[i]); + Jumps.Delete(i); + i--; + } + } +} + +//========================================================================== +// +// ExpEmit +// +//========================================================================== + ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) : RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false) { @@ -2838,14 +2877,14 @@ FxSelf::FxSelf(const FScriptPosition &pos) FxExpression *FxSelf::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); - if (!ctx.cls) + if (!ctx.Class) { // can't really happen with DECORATE's expression evaluator. ScriptPosition.Message(MSG_ERROR, "self used outside of a member function"); delete this; return NULL; } - ValueType = ctx.cls; + ValueType = ctx.Class; ValueType = NewPointer(RUNTIME_CLASS(DObject)); return this; } @@ -3818,6 +3857,39 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) return ExpEmit(); } +//========================================================================== +// +// FxJumpStatement +// +//========================================================================== + +FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos) +: FxExpression(pos), Token(token), AddressResolver(nullptr) +{ + ValueType = TypeVoid; +} + +FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + + ctx.Jumps.Push(this); + + return this; +} + +ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build) +{ + if (AddressResolver == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Jump statement %s has nowhere to go!", FScanner::TokenName(Token)); + } + + Address = build->Emit(OP_JMP, 0); + + return ExpEmit(); +} + //========================================================================== // //========================================================================== @@ -4008,19 +4080,19 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); - if (ctx.cls->NumOwnedStates == 0) + if (ctx.Class->NumOwnedStates == 0) { // This can't really happen assert(false); } - if (ctx.cls->NumOwnedStates <= index) + if (ctx.Class->NumOwnedStates <= index) { ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d", - ctx.cls->TypeName.GetChars(), index); + ctx.Class->TypeName.GetChars(), index); delete this; return NULL; } - FxExpression *x = new FxConstant(ctx.cls->OwnedStates + index, ScriptPosition); + FxExpression *x = new FxConstant(ctx.Class->OwnedStates + index, ScriptPosition); delete this; return x; } @@ -4068,7 +4140,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) } else if (names[0] == NAME_Super) { - scope = dyn_cast(ctx.cls->ParentClass); + scope = dyn_cast(ctx.Class->ParentClass); } else { @@ -4079,9 +4151,9 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) delete this; return NULL; } - else if (!scope->IsDescendantOf(ctx.cls)) + else if (!scope->IsDescendantOf(ctx.Class)) { - ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.cls->TypeName.GetChars()); + ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.Class->TypeName.GetChars()); delete this; return NULL; } diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index ae1805119..464221714 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -529,6 +529,18 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg sc.MustGetString(); add = new FxReturnStatement(retexp, sc); } + else if (sc.Compare("break")) + { + add = new FxJumpStatement(TK_Break, sc); + sc.MustGetStringName(";"); + sc.MustGetString(); + } + else if (sc.Compare("continue")) + { + add = new FxJumpStatement(TK_Continue, sc); + sc.MustGetStringName(";"); + sc.MustGetString(); + } else { // Handle a regular action function call add = ParseAction(sc, state, statestring, bag); From d1749233ec64983e2baa278d75174149f7656f45 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Mon, 25 Jul 2016 06:38:02 +0200 Subject: [PATCH 05/26] Added while loops to DECORATE --- src/thingdef/thingdef_exp.h | 19 +++++ src/thingdef/thingdef_expression.cpp | 101 +++++++++++++++++++++++++++ src/thingdef/thingdef_states.cpp | 27 ++++++- src/zscript/vmbuilder.cpp | 11 +++ src/zscript/vmbuilder.h | 3 + 5 files changed, 160 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 3353cad46..bf32d02f6 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -48,6 +48,7 @@ #define RESOLVE(p,c) if (p!=NULL) p = p->Resolve(c) #define ABORT(p) if (!(p)) { delete this; return NULL; } #define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p) +#define SAFE_RESOLVE_OPT(p,c) if (p!=NULL) { SAFE_RESOLVE(p,c) } class VMFunctionBuilder; class FxJumpStatement; @@ -927,6 +928,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxWhileLoop +// +//========================================================================== + +class FxWhileLoop : public FxExpression +{ + FxExpression *Condition; + FxExpression *Code; + +public: + FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); + ~FxWhileLoop(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 4e13b7beb..b5eabe7d1 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3857,6 +3857,107 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) return ExpEmit(); } +//========================================================================== +// +// FxWhileLoop +// +//========================================================================== + +FxWhileLoop::FxWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) +: FxExpression(pos), Condition(condition), Code(code) +{ + ValueType = TypeVoid; +} + +FxWhileLoop::~FxWhileLoop() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(Code); +} + +FxExpression *FxWhileLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + ctx.HandleJumps(TK_Break, this); + ctx.HandleJumps(TK_Continue, this); + + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // Nothing happens + FxExpression *nop = new FxNop(ScriptPosition); + delete this; + return nop; + } + else if (Code == nullptr) + { // "while (true) { }" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + } + + return this; +} + +ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) +{ + assert(Condition->ValueType == TypeBool); + + size_t loopstart, loopend; + size_t jumpspot; + + // Evaluate the condition and execute/break out of the loop. + loopstart = build->GetAddress(); + if (!Condition->isConstant()) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 0); + jumpspot = build->Emit(OP_JMP, 0); + cond.Free(build); + } + else assert(static_cast(Condition)->GetValue().GetBool() == true); + + // Execute the loop's content. + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Loop back. + build->Backpatch(build->Emit(OP_JMP, 0), loopstart); + loopend = build->GetAddress(); + + if (!Condition->isConstant()) + { + build->Backpatch(jumpspot, loopend); + } + + // Give a proper address to any break/continue statement within this loop. + for (unsigned int i = 0; i < JumpAddresses.Size(); i++) + { + if (JumpAddresses[i]->Token == TK_Break) + { + build->Backpatch(JumpAddresses[i]->Address, loopend); + } + else + { // Continue statement. + build->Backpatch(JumpAddresses[i]->Address, loopstart); + } + } + + return ExpEmit(); +} + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 464221714..6e71f628e 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -480,6 +480,27 @@ static FxExpression *ParseIf(FScanner &sc, FState state, FString statestring, Ba return add; } +static FxExpression *ParseWhile(FScanner &sc, FState state, FString statestring, Baggage &bag, + PPrototype *&retproto, bool &lastwasret) +{ + FxExpression *cond, *code; + PPrototype *proto; + bool ret; + + sc.MustGetStringName("("); + cond = ParseExpression(sc, bag.Info); + sc.MustGetStringName(")"); + sc.MustGetStringName("{"); // Enforce braces like for if statements. + + code = ParseActions(sc, state, statestring, bag, proto, ret); + sc.MustGetString(); + + retproto = ReturnCheck(retproto, proto, sc); + lastwasret = false; // A while loop always jumps back. + + return new FxWhileLoop(cond, code, sc); +} + FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, PPrototype *&retproto, bool &endswithret) { @@ -505,9 +526,13 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg FxExpression *add; lastwasret = false; if (sc.Compare("if")) - { // Hangle an if statement + { // Handle an if statement add = ParseIf(sc, state, statestring, bag, proto, lastwasret); } + else if (sc.Compare("while")) + { // Handle a while loop + add = ParseWhile(sc, state, statestring, bag, proto, lastwasret); + } else if (sc.Compare("return")) { // Handle a return statement lastwasret = true; diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 2a4f6b1a8..eb49ffb14 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -436,6 +436,17 @@ bool VMFunctionBuilder::RegAvailability::Reuse(int reg) return true; } +//========================================================================== +// +// VMFunctionBuilder :: GetAddress +// +//========================================================================== + +size_t VMFunctionBuilder::GetAddress() +{ + return Code.Size(); +} + //========================================================================== // // VMFunctionBuilder :: Emit diff --git a/src/zscript/vmbuilder.h b/src/zscript/vmbuilder.h index 89b626c18..2d8721acc 100644 --- a/src/zscript/vmbuilder.h +++ b/src/zscript/vmbuilder.h @@ -34,6 +34,9 @@ public: int GetConstantAddress(void *ptr, VM_ATAG tag); int GetConstantString(FString str); + // Returns the address of the next instruction to be emitted. + size_t GetAddress(); + // Returns the address of the newly-emitted instruction. size_t Emit(int opcode, int opa, int opb, int opc); size_t Emit(int opcode, int opa, VM_SHALF opbc); From e2fa8c2257244283afa13793844d50c3b1fcea2a Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Wed, 27 Jul 2016 17:14:54 +0200 Subject: [PATCH 06/26] Added do-while loops to DECORATE --- src/thingdef/thingdef_exp.h | 18 +++++ src/thingdef/thingdef_expression.cpp | 102 +++++++++++++++++++++++++++ src/thingdef/thingdef_states.cpp | 27 +++++++ 3 files changed, 147 insertions(+) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index bf32d02f6..c9eca78cf 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -946,6 +946,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxDoWhileLoop +// +//========================================================================== + +class FxDoWhileLoop : public FxExpression +{ + FxExpression *Condition; + FxExpression *Code; + +public: + FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos); + ~FxDoWhileLoop(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index b5eabe7d1..27de1381c 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3958,6 +3958,108 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build) return ExpEmit(); } +//========================================================================== +// +// FxDoWhileLoop +// +//========================================================================== + +FxDoWhileLoop::FxDoWhileLoop(FxExpression *condition, FxExpression *code, const FScriptPosition &pos) +: FxExpression(pos), Condition(condition), Code(code) +{ + ValueType = TypeVoid; +} + +FxDoWhileLoop::~FxDoWhileLoop() +{ + SAFE_DELETE(Condition); + SAFE_DELETE(Code); +} + +FxExpression *FxDoWhileLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Condition, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + ctx.HandleJumps(TK_Break, this); + ctx.HandleJumps(TK_Continue, this); + + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // The code executes once, if any. + if (JumpAddresses.Size() == 0) + { // We would still have to handle the jumps however. + FxExpression *e = Code; + if (e == nullptr) e = new FxNop(ScriptPosition); + Code = nullptr; + delete this; + return e; + } + } + else if (Code == nullptr) + { // "do { } while (true);" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + } + + return this; +} + +ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) +{ + assert(Condition->ValueType == TypeBool); + + size_t loopstart, loopend; + size_t codestart; + + // Execute the loop's content. + codestart = build->GetAddress(); + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Evaluate the condition and execute/break out of the loop. + loopstart = build->GetAddress(); + if (!Condition->isConstant()) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 1); + cond.Free(build); + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + } + else if (static_cast(Condition)->GetValue().GetBool() == true) + { // Always looping + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + } + loopend = build->GetAddress(); + + // Give a proper address to any break/continue statement within this loop. + for (unsigned int i = 0; i < JumpAddresses.Size(); i++) + { + if (JumpAddresses[i]->Token == TK_Break) + { + build->Backpatch(JumpAddresses[i]->Address, loopend); + } + else + { // Continue statement. + build->Backpatch(JumpAddresses[i]->Address, loopstart); + } + } + + return ExpEmit(); +} + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 6e71f628e..dc5687211 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -501,6 +501,29 @@ static FxExpression *ParseWhile(FScanner &sc, FState state, FString statestring, return new FxWhileLoop(cond, code, sc); } +static FxExpression *ParseDoWhile(FScanner &sc, FState state, FString statestring, Baggage &bag, + PPrototype *&retproto, bool &lastwasret) +{ + FxExpression *cond, *code; + PPrototype *proto; + bool ret; + + sc.MustGetStringName("{"); // Enforce braces like for if statements. + code = ParseActions(sc, state, statestring, bag, proto, ret); + + sc.MustGetStringName("while"); + sc.MustGetStringName("("); + cond = ParseExpression(sc, bag.Info); + sc.MustGetStringName(")"); + sc.MustGetStringName(";"); + sc.MustGetString(); + + retproto = ReturnCheck(retproto, proto, sc); + lastwasret = false; + + return new FxDoWhileLoop(cond, code, sc); +} + FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, PPrototype *&retproto, bool &endswithret) { @@ -533,6 +556,10 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg { // Handle a while loop add = ParseWhile(sc, state, statestring, bag, proto, lastwasret); } + else if (sc.Compare("do")) + { // Handle a do-while loop + add = ParseDoWhile(sc, state, statestring, bag, proto, lastwasret); + } else if (sc.Compare("return")) { // Handle a return statement lastwasret = true; From d0b953cbb7ea855f5bf596e9ec6cbc3cb9309b16 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Thu, 28 Jul 2016 17:36:05 +0200 Subject: [PATCH 07/26] Added for loops to DECORATE --- src/thingdef/thingdef_exp.h | 20 +++++ src/thingdef/thingdef_expression.cpp | 127 +++++++++++++++++++++++++++ src/thingdef/thingdef_states.cpp | 47 ++++++++++ 3 files changed, 194 insertions(+) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index c9eca78cf..b878e50f1 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -964,6 +964,26 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxForLoop +// +//========================================================================== + +class FxForLoop : public FxExpression +{ + FxExpression *Init; + FxExpression *Condition; + FxExpression *Iteration; + FxExpression *Code; + +public: + FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos); + ~FxForLoop(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 27de1381c..5017ae421 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4060,6 +4060,133 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build) return ExpEmit(); } +//========================================================================== +// +// FxForLoop +// +//========================================================================== + +FxForLoop::FxForLoop(FxExpression *init, FxExpression *condition, FxExpression *iteration, FxExpression *code, const FScriptPosition &pos) +: FxExpression(pos), Init(init), Condition(condition), Iteration(iteration), Code(code) +{ + ValueType = TypeVoid; +} + +FxForLoop::~FxForLoop() +{ + SAFE_DELETE(Init); + SAFE_DELETE(Condition); + SAFE_DELETE(Iteration); + SAFE_DELETE(Code); +} + +FxExpression *FxForLoop::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE_OPT(Init, ctx); + SAFE_RESOLVE_OPT(Condition, ctx); + SAFE_RESOLVE_OPT(Iteration, ctx); + SAFE_RESOLVE_OPT(Code, ctx); + + ctx.HandleJumps(TK_Break, this); + ctx.HandleJumps(TK_Continue, this); + + if (Condition != nullptr) + { + if (Condition->ValueType != TypeBool) + { + Condition = new FxBoolCast(Condition); + SAFE_RESOLVE(Condition, ctx); + } + + if (Condition->isConstant()) + { + if (static_cast(Condition)->GetValue().GetBool() == false) + { // Nothing happens + FxExpression *nop = new FxNop(ScriptPosition); + delete this; + return nop; + } + else + { // "for (..; true; ..)" + delete Condition; + Condition = nullptr; + } + } + } + if (Condition == nullptr && Code == nullptr) + { // "for (..; ; ..) { }" + // Someone could be using this for testing. + ScriptPosition.Message(MSG_WARNING, "Infinite empty loop"); + } + + return this; +} + +ExpEmit FxForLoop::Emit(VMFunctionBuilder *build) +{ + assert((Condition && Condition->ValueType == TypeBool && !Condition->isConstant()) || Condition == nullptr); + + size_t loopstart, loopend; + size_t codestart; + size_t jumpspot; + + // Init statement. + if (Init != nullptr) + { + ExpEmit init = Init->Emit(build); + init.Free(build); + } + + // Evaluate the condition and execute/break out of the loop. + codestart = build->GetAddress(); + if (Condition != nullptr) + { + ExpEmit cond = Condition->Emit(build); + build->Emit(OP_TEST, cond.RegNum, 0); + cond.Free(build); + jumpspot = build->Emit(OP_JMP, 0); + } + + // Execute the loop's content. + if (Code != nullptr) + { + ExpEmit code = Code->Emit(build); + code.Free(build); + } + + // Iteration statement. + loopstart = build->GetAddress(); + if (Iteration != nullptr) + { + ExpEmit iter = Iteration->Emit(build); + iter.Free(build); + } + build->Backpatch(build->Emit(OP_JMP, 0), codestart); + + // End of loop. + loopend = build->GetAddress(); + if (Condition != nullptr) + { + build->Backpatch(jumpspot, loopend); + } + + // Give a proper address to any break/continue statement within this loop. + for (unsigned int i = 0; i < JumpAddresses.Size(); i++) + { + if (JumpAddresses[i]->Token == TK_Break) + { + build->Backpatch(JumpAddresses[i]->Address, loopend); + } + else + { // Continue statement. + build->Backpatch(JumpAddresses[i]->Address, loopstart); + } + } + + return ExpEmit(); +} + //========================================================================== // // FxJumpStatement diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index dc5687211..ecc62bf29 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -524,6 +524,49 @@ static FxExpression *ParseDoWhile(FScanner &sc, FState state, FString statestrin return new FxDoWhileLoop(cond, code, sc); } +static FxExpression *ParseFor(FScanner &sc, FState state, FString statestring, Baggage &bag, + PPrototype *&retproto, bool &lastwasret) +{ + FxExpression *init = nullptr; + FxExpression *cond = nullptr; + FxExpression *iter = nullptr; + FxExpression *code = nullptr; + PPrototype *proto; + bool ret; + + // Parse the statements. + sc.MustGetStringName("("); + sc.MustGetString(); + if (!sc.Compare(";")) + { + init = ParseAction(sc, state, statestring, bag); // That's all DECORATE can handle for now. + sc.MustGetStringName(";"); + } + sc.MustGetString(); + if (!sc.Compare(";")) + { + sc.UnGet(); + cond = ParseExpression(sc, bag.Info); + sc.MustGetStringName(";"); + } + sc.MustGetString(); + if (!sc.Compare(")")) + { + iter = ParseAction(sc, state, statestring, bag); + sc.MustGetStringName(")"); + } + + // Now parse the loop's content. + sc.MustGetStringName("{"); // Enforce braces like for if statements. + code = ParseActions(sc, state, statestring, bag, proto, ret); + sc.MustGetString(); + + retproto = ReturnCheck(retproto, proto, sc); + lastwasret = false; + + return new FxForLoop(init, cond, iter, code, sc); +} + FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, PPrototype *&retproto, bool &endswithret) { @@ -560,6 +603,10 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg { // Handle a do-while loop add = ParseDoWhile(sc, state, statestring, bag, proto, lastwasret); } + else if (sc.Compare("for")) + { // Handle a for loop + add = ParseFor(sc, state, statestring, bag, proto, lastwasret); + } else if (sc.Compare("return")) { // Handle a return statement lastwasret = true; From 167cb285635b136d89a92bf95ecb768f72dfc34d Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 29 Jul 2016 12:50:15 -0500 Subject: [PATCH 08/26] Added GetProximity(classname, distance, flags, ptr). - Behaves similarly to A_CheckProximity but returns the count of classname instead of true/false. # Conflicts: # wadsrc/static/actors/actor.txt --- src/p_local.h | 2 +- src/p_things.cpp | 32 ++++++++++++++++--------------- src/thingdef/thingdef_codeptr.cpp | 32 +++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 4b8b40a85..ebbaeace5 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -161,7 +161,7 @@ PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); int P_Thing_CheckInputNum(player_t *p, int inputnum); int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch); -bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr); +int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting = false); enum { diff --git a/src/p_things.cpp b/src/p_things.cpp index 6f01715ad..d94ba6a01 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -696,16 +696,16 @@ int P_Thing_CheckInputNum(player_t *p, int inputnum) } return renum; } -bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr) +int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting) { AActor *ref = COPY_AAPTR(self, ptr); // We need these to check out. if (!ref || !classname || distance <= 0) - return false; + return 0; int counter = 0; - bool result = false; + int result = 0; double closer = distance, farther = 0, current = distance; const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); @@ -740,7 +740,7 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in if ((ref->Distance2D(mo) < distance && ((flags & CPXF_NOZ) || ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || - (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) + (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) { if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) continue; @@ -766,19 +766,19 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in { if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) continue; - counter++; } else { if (flags & CPXF_DEADONLY) continue; - counter++; } + counter++; // Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal. - if (counter > count) - { - result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true; + // Don't abort if calling the counting version CheckProximity non-action function. + if (!counting && counter > count) + { + result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? 0 : 1; // However, if we have one SET* flag and either the closest or farthest flags, keep the function going. if (ptrWillChange && ptrDistPref) @@ -805,12 +805,14 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in } } - if (counter == count) - result = true; - else if (counter < count) - result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); - - return result; + if (!counting) + { + if (counter == count) + result = 1; + else if (counter < count) + result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)) ? 1 : 0; + } + return counting ? counter : result; } int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 17c5b5cf5..cd90e08e5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -643,6 +643,38 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) return 0; } +//========================================================================== +// +// GetProximity +// +// NON-ACTION function of A_CheckProximity that returns how much it counts. +// Takes a pointer as anyone may or may not be a player. +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetProximity) +{ + if (numret > 0) + { + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(classname, AActor); + PARAM_FLOAT(distance); + PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *mobj = COPY_AAPTR(self, ptr); + if (mobj == nullptr) + { + ret->SetInt(0); + } + else + { + ret->SetInt(P_Thing_CheckProximity(self, classname, distance, 0, flags, ptr, true)); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 1d27ad01a..d28c8ebc3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -50,6 +50,7 @@ ACTOR Actor native //: Thinker native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); native float GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); + native int GetProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); From 13fa06fe7a4c9c3d97a89bdb43175c960f710153 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 29 Jul 2016 13:07:26 -0500 Subject: [PATCH 09/26] Renamed GetProximity to CountProximity. # Conflicts: # wadsrc/static/actors/actor.txt --- src/thingdef/thingdef_codeptr.cpp | 4 ++-- wadsrc/static/actors/actor.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index cd90e08e5..16f9e2482 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -645,13 +645,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) //========================================================================== // -// GetProximity +// CountProximity // // NON-ACTION function of A_CheckProximity that returns how much it counts. // Takes a pointer as anyone may or may not be a player. //========================================================================== -DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetProximity) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, CountProximity) { if (numret > 0) { diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index d28c8ebc3..868925c3d 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -50,7 +50,7 @@ ACTOR Actor native //: Thinker native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); native float GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); - native int GetProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); + native int CountProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); From a1a0da1f13ea142228c1b375c52885ce7a678757 Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Fri, 29 Jul 2016 18:48:54 -0500 Subject: [PATCH 10/26] added SWF_SELECTPRIORITY flag to A_SelectWeapon --- src/thingdef/thingdef_codeptr.cpp | 17 ++++++++++++++++- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/constants.txt | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 16f9e2482..6904a05d4 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3103,12 +3103,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Recoil) // A_SelectWeapon // //=========================================================================== +enum SW_Flags +{ + SWF_SELECTPRIORITY = 1, +}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS(cls, AWeapon); + PARAM_INT_OPT(flags) { flags = 0; } - if (cls == NULL || self->player == NULL) + bool selectPriority = !!(flags & SWF_SELECTPRIORITY); + + if ((!selectPriority && cls == NULL) || self->player == NULL) { ACTION_RETURN_BOOL(false); } @@ -3123,6 +3130,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SelectWeapon) } ACTION_RETURN_BOOL(true); } + else if (selectPriority) + { + // [XA] if the named weapon cannot be found (or is a dummy like 'None'), + // select the next highest priority weapon. This is basically + // the same as A_CheckReload minus the ammo check. Handy. + self->player->mo->PickNewWeapon(NULL); + ACTION_RETURN_BOOL(true); + } else { ACTION_RETURN_BOOL(false); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 868925c3d..23ac3d19c 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -265,7 +265,7 @@ ACTOR Actor native //: Thinker native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0); native state A_JumpIfTargetInLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); native state A_JumpIfInTargetLOS (state label, float/*angle*/ fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0); - native bool A_SelectWeapon(class whichweapon); + native bool A_SelectWeapon(class whichweapon, int flags = 0); action native A_Punch(); action native A_Feathers(); action native A_ClassBossHealth(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 76bdcf9eb..30afd1064 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -150,6 +150,9 @@ const int WRF_ALLOWUSER2 = 256; const int WRF_ALLOWUSER3 = 512; const int WRF_ALLOWUSER4 = 1024; +// Flags for A_SelectWeapon +const int SWF_SELECTPRIORITY = 1; + // Morph constants const int MRF_ADDSTAMINA = 1; const int MRF_FULLHEALTH = 2; From 0648ef693f8e02d1aed69e08d2590c72dbff59be Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 30 Jul 2016 10:09:00 +0300 Subject: [PATCH 11/26] Fixed compilation with Clang and GCC No more "error: cannot pass object of non-trivial type 'FString' through variadic method; call will abort at runtime" --- src/thingdef/thingdef_expression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 5017ae421..acb26d05b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4212,7 +4212,7 @@ ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build) { if (AddressResolver == nullptr) { - ScriptPosition.Message(MSG_ERROR, "Jump statement %s has nowhere to go!", FScanner::TokenName(Token)); + ScriptPosition.Message(MSG_ERROR, "Jump statement %s has nowhere to go!", FScanner::TokenName(Token).GetChars()); } Address = build->Emit(OP_JMP, 0); From 5ddee98e70c2ad37e43cd93165084e1ccc31f6f2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jul 2016 13:19:02 +0200 Subject: [PATCH 12/26] - fixed: Voxels with scaled to 0 caused a division by zero crash. --- src/r_things.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index 78d72fbc8..248e50c18 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2751,6 +2751,11 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle, // Also do some magic voodoo scaling to make them the right size. daxscale = daxscale / (0xC000 >> 6); dayscale = dayscale / (0xC000 >> 6); + if (daxscale <= 0 || dayscale <= 0) + { + // won't be visible. + return; + } angle_t viewang = viewangle.BAMs(); cosang = FLOAT2FIXED(viewangle.Cos()) >> 2; From cbe0a34f0b54a3362f78fb105541e5eb74c33797 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 30 Jul 2016 10:15:13 +0300 Subject: [PATCH 13/26] Fixed usages of abs() function with double arguments Clang no longer issues "warning: using integer absolute value function 'abs' when argument is of floating point type" --- src/p_map.cpp | 2 +- src/r_things.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 106c93152..110ae5235 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1566,7 +1566,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo tm.floorpic = *rover->top.texture; tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling); } - if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + if (ff_bottom < tm.ceilingz && fabs(delta1) >= fabs(delta2)) { tm.ceilingz = ff_bottom; tm.ceilingpic = *rover->bottom.texture; diff --git a/src/r_things.cpp b/src/r_things.cpp index 248e50c18..aad8fb501 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -916,7 +916,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor // too far off the side? // if it's a voxel, it can be further off the side if ((voxel == NULL && (fabs(tx / 64) > fabs(tz))) || - (voxel != NULL && (fabs(tx / 128) > abs(tz)))) + (voxel != NULL && (fabs(tx / 128) > fabs(tz)))) { return; } From bd3fd22ac9ccfb2c977a50f63b5d634dad677e3b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 30 Jul 2016 16:21:48 +0300 Subject: [PATCH 14/26] Do not use unicode characters in macOS console window The same characters as in stdout are now used to draw bars in console window on macOS All messages are treated as in ISO Latin 1 encoding and bars looked like garbage output --- src/posix/cocoa/st_console.mm | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index e38a5cc85..b037fe6dd 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -248,9 +248,6 @@ void FConsoleWindow::AddText(const char* message) AddText(color, buffer); } -#define CHECK_BUFFER_SPACE \ - if (pos >= sizeof buffer - 3) { reset = true; continue; } - if (TEXTCOLOR_ESCAPE == *message) { const BYTE* colorID = reinterpret_cast(message) + 1; @@ -268,42 +265,20 @@ void FConsoleWindow::AddText(const char* message) message += 2; } - else if (0x1d == *message) // Opening bar character + else if (0x1d == *message || 0x1f == *message) // Opening and closing bar characters { - CHECK_BUFFER_SPACE; - - // Insert BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT - buffer[pos++] = '\xe2'; - buffer[pos++] = '\x95'; - buffer[pos++] = '\xbc'; + buffer[pos++] = '-'; ++message; } else if (0x1e == *message) // Middle bar character { - CHECK_BUFFER_SPACE; - - // Insert BOX DRAWINGS HEAVY HORIZONTAL - buffer[pos++] = '\xe2'; - buffer[pos++] = '\x94'; - buffer[pos++] = '\x81'; - ++message; - } - else if (0x1f == *message) // Closing bar character - { - CHECK_BUFFER_SPACE; - - // Insert BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT - buffer[pos++] = '\xe2'; - buffer[pos++] = '\x95'; - buffer[pos++] = '\xbe'; + buffer[pos++] = '='; ++message; } else { buffer[pos++] = *message++; } - -#undef CHECK_BUFFER_SPACE } if (0 != pos) From c0d3eb997aca79f69ffe04950fcb258d09c19abe Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sat, 30 Jul 2016 23:50:14 +0200 Subject: [PATCH 15/26] Fixed: the instant weapon switch flag didn't work anymore --- src/p_pspr.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 48ead3699..9f1233609 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -237,8 +237,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) pspr->y = WEAPONTOP; } - pspr->oldx = pspr->x; - pspr->oldy = pspr->y; + pspr->firstTic = true; } return pspr; From 8068792f4b54f7d906cebba3acda21d517b6c33b Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 31 Jul 2016 00:03:17 +0200 Subject: [PATCH 16/26] Fixed: A_RadiusGive had an incorrect definition --- wadsrc/static/actors/actor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 23ac3d19c..fa8932050 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -244,7 +244,7 @@ ACTOR Actor native //: Thinker native state A_JumpIfInTargetInventory(class itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); native bool A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); native bool A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); - native int A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", int mindist = 0, int limit = 0); + native int A_RadiusGive(class itemtype, float distance, int flags, int amount = 0, class filter = "None", name species = "None", float mindist = 0, int limit = 0); native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT); native void A_CountdownArg(int argnum, state targstate = ""); action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); From 95c346497371395b401be2c9e4e37c8eaa3c8c60 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 3 Aug 2016 12:17:22 +0200 Subject: [PATCH 17/26] - properly handle 3D floors with inverted planes in the list sorter. --- src/p_3dfloors.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 5e2117b9b..d27ebe4d1 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -514,6 +514,17 @@ void P_Recalculate3DFloors(sector_t * sector) clipped_bottom = pick_bottom; } } + else if (pick_bottom > height) // do not allow inverted planes + { + F3DFloor * dyn = new F3DFloor; + *dyn = *pick; + pick->flags |= FF_CLIPPED; + pick->flags &= ~FF_EXISTS; + dyn->flags |= FF_DYNAMIC; + dyn->bottom.copyPlane(&pick->top); + ffloors.Push(pick); + ffloors.Push(dyn); + } else { clipped = pick; From c1a4dd74c46bad62a8ba7aca7f45b8267edeb2f2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 3 Aug 2016 12:59:40 +0200 Subject: [PATCH 18/26] - added handling for Eternity's 'gap' parameter to: Ceiling_LowerToFloor Ceiling_LowerToHighestFloor Ceiling_ToFloorInstant Floor_RaiseToCeiling Floor_RaiseToLowestCeiling Floor_ToCeilingInstant --- src/actionspecials.h | 12 ++++++------ src/p_ceiling.cpp | 6 +++--- src/p_floor.cpp | 6 +++--- src/p_lnspec.cpp | 22 +++++++++++----------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/actionspecials.h b/src/actionspecials.h index 6d9d2feb8..4ab222b2c 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -176,7 +176,7 @@ DEFINE_SPECIAL(Sector_SetCeilingScale, 188, 5, 5, 5) DEFINE_SPECIAL(Sector_SetFloorScale, 189, 5, 5, 5) DEFINE_SPECIAL(Static_Init, 190, -1, -1, 4) DEFINE_SPECIAL(SetPlayerProperty, 191, 3, 3, 3) -DEFINE_SPECIAL(Ceiling_LowerToHighestFloor, 192, 2, 4, 4) +DEFINE_SPECIAL(Ceiling_LowerToHighestFloor, 192, 2, 4, 5) DEFINE_SPECIAL(Ceiling_LowerInstant, 193, 3, 5, 5) DEFINE_SPECIAL(Ceiling_RaiseInstant, 194, 3, 4, 4) DEFINE_SPECIAL(Ceiling_CrushRaiseAndStayA, 195, 4, 5, 5) @@ -222,7 +222,7 @@ DEFINE_SPECIAL(Light_MaxNeighbor, 234, 1, 1, 1) DEFINE_SPECIAL(Floor_TransferTrigger, 235, 1, 1, 1) DEFINE_SPECIAL(Floor_TransferNumeric, 236, 1, 1, 1) DEFINE_SPECIAL(ChangeCamera, 237, 3, 3, 3) -DEFINE_SPECIAL(Floor_RaiseToLowestCeiling, 238, 2, 4, 4) +DEFINE_SPECIAL(Floor_RaiseToLowestCeiling, 238, 2, 4, 5) DEFINE_SPECIAL(Floor_RaiseByValueTxTy, 239, 3, 3, 3) DEFINE_SPECIAL(Floor_RaiseByTexture, 240, 2, 4, 4) DEFINE_SPECIAL(Floor_LowerToLowestTxTy, 241, 2, 2, 2) @@ -238,21 +238,21 @@ DEFINE_SPECIAL(Floor_Donut, 250, 3, 3, 3) DEFINE_SPECIAL(FloorAndCeiling_LowerRaise, 251, 3, 4, 4) DEFINE_SPECIAL(Ceiling_RaiseToNearest, 252, 2, 3, 3) DEFINE_SPECIAL(Ceiling_LowerToLowest, 253, 2, 4, 4) -DEFINE_SPECIAL(Ceiling_LowerToFloor, 254, 2, 4, 4) +DEFINE_SPECIAL(Ceiling_LowerToFloor, 254, 2, 4, 5) DEFINE_SPECIAL(Ceiling_CrushRaiseAndStaySilA, 255, 4, 5, 5) DEFINE_SPECIAL(Floor_LowerToHighestEE, 256, 2, 3, 3) DEFINE_SPECIAL(Floor_RaiseToLowest, 257, 1, 3, 3) DEFINE_SPECIAL(Floor_LowerToLowestCeiling, 258, 2, 3, 3) -DEFINE_SPECIAL(Floor_RaiseToCeiling, 259, 2, 4, 4) -DEFINE_SPECIAL(Floor_ToCeilingInstant, 260, 1, 3, 3) +DEFINE_SPECIAL(Floor_RaiseToCeiling, 259, 2, 4, 5) +DEFINE_SPECIAL(Floor_ToCeilingInstant, 260, 1, 3, 4) DEFINE_SPECIAL(Floor_LowerByTexture, 261, 2, 3, 3) DEFINE_SPECIAL(Ceiling_RaiseToHighest, 262, 2, 3, 3) DEFINE_SPECIAL(Ceiling_ToHighestInstant, 263, 1, 3, 3) DEFINE_SPECIAL(Ceiling_LowerToNearest, 264, 2, 4, 4) DEFINE_SPECIAL(Ceiling_RaiseToLowest, 265, 2, 3, 3) DEFINE_SPECIAL(Ceiling_RaiseToHighestFloor, 266, 2, 3, 3) -DEFINE_SPECIAL(Ceiling_ToFloorInstant, 267, 1, 3, 3) +DEFINE_SPECIAL(Ceiling_ToFloorInstant, 267, 1, 3, 4) DEFINE_SPECIAL(Ceiling_RaiseByTexture, 268, 2, 3, 3) DEFINE_SPECIAL(Ceiling_LowerByTexture, 269, 2, 4, 4) DEFINE_SPECIAL(Stairs_BuildDownDoom, 270, 5, 5, 5) diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 8a0c8f9ef..c635d9743 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -309,7 +309,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t break; case DCeiling::ceilLowerToHighestFloor: - targheight = sec->FindHighestFloorSurrounding (&spot); + targheight = sec->FindHighestFloorSurrounding (&spot) + height; ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight); ceiling->m_Direction = -1; break; @@ -359,13 +359,13 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t break; case DCeiling::ceilLowerToFloor: - targheight = sec->FindHighestFloorPoint (&spot); + targheight = sec->FindHighestFloorPoint (&spot) + height; ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight); ceiling->m_Direction = -1; break; case DCeiling::ceilRaiseToFloor: // [RH] What's this for? - targheight = sec->FindHighestFloorPoint (&spot); + targheight = sec->FindHighestFloorPoint (&spot) + height; ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight); ceiling->m_Direction = 1; break; diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 3f2b06f95..10bcf6d7e 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -387,13 +387,13 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, case DFloor::floorRaiseToCeiling: floor->m_Direction = 1; - newheight = sec->FindLowestCeilingPoint(&spot); + newheight = sec->FindLowestCeilingPoint(&spot) - height; floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight); break; case DFloor::floorLowerToLowestCeiling: floor->m_Direction = -1; - newheight = sec->FindLowestCeilingSurrounding(&spot); + newheight = sec->FindLowestCeilingSurrounding(&spot) - height; floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight); break; @@ -406,7 +406,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, case DFloor::floorLowerToCeiling: // [RH] Essentially instantly raises the floor to the ceiling floor->m_Direction = -1; - newheight = sec->FindLowestCeilingPoint(&spot); + newheight = sec->FindLowestCeilingPoint(&spot) - height; floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight); break; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 307529636..dc6170c24 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -420,9 +420,9 @@ FUNC(LS_Floor_RaiseInstant) } FUNC(LS_Floor_ToCeilingInstant) -// Floor_ToCeilingInstant (tag, change, crush) +// Floor_ToCeilingInstant (tag, change, crush, gap) { - return EV_DoFloor (DFloor::floorLowerToCeiling, ln, arg0, 0, 0, CRUSH(arg2), CHANGE(arg1), true); + return EV_DoFloor (DFloor::floorLowerToCeiling, ln, arg0, 0, arg3, CRUSH(arg2), CHANGE(arg1), true); } FUNC(LS_Floor_MoveToValueTimes8) @@ -448,7 +448,7 @@ FUNC(LS_Floor_RaiseToLowestCeiling) FUNC(LS_Floor_LowerToLowestCeiling) // Floor_LowerToLowestCeiling (tag, speed, change) { - return EV_DoFloor (DFloor::floorLowerToLowestCeiling, ln, arg0, SPEED(arg1), 0, -1, CHANGE(arg2), true); + return EV_DoFloor (DFloor::floorLowerToLowestCeiling, ln, arg0, SPEED(arg1), arg4, -1, CHANGE(arg2), true); } FUNC(LS_Floor_RaiseByTexture) @@ -464,9 +464,9 @@ FUNC(LS_Floor_LowerByTexture) } FUNC(LS_Floor_RaiseToCeiling) -// Floor_RaiseToCeiling (tag, speed, change, crush) +// Floor_RaiseToCeiling (tag, speed, change, crush, gap) { - return EV_DoFloor (DFloor::floorRaiseToCeiling, ln, arg0, SPEED(arg1), 0, CRUSH(arg3), CHANGE(arg2), true); + return EV_DoFloor (DFloor::floorRaiseToCeiling, ln, arg0, SPEED(arg1), arg4, CRUSH(arg3), CHANGE(arg2), true); } FUNC(LS_Floor_RaiseByValueTxTy) @@ -706,9 +706,9 @@ FUNC(LS_Ceiling_MoveToValue) } FUNC(LS_Ceiling_LowerToHighestFloor) -// Ceiling_LowerToHighestFloor (tag, speed, change, crush) +// Ceiling_LowerToHighestFloor (tag, speed, change, crush, gap) { - return EV_DoCeiling (DCeiling::ceilLowerToHighestFloor, ln, arg0, SPEED(arg1), 0, 0, CRUSH(arg3), 0, CHANGE(arg2)); + return EV_DoCeiling (DCeiling::ceilLowerToHighestFloor, ln, arg0, SPEED(arg1), 0, arg4, CRUSH(arg3), 0, CHANGE(arg2)); } FUNC(LS_Ceiling_LowerInstant) @@ -808,15 +808,15 @@ FUNC(LS_Ceiling_ToHighestInstant) } FUNC(LS_Ceiling_ToFloorInstant) -// Ceiling_ToFloorInstant (tag, change, crush) +// Ceiling_ToFloorInstant (tag, change, crush, gap) { - return EV_DoCeiling (DCeiling::ceilRaiseToFloor, ln, arg0, 2, 0, 0, CRUSH(arg2), 0, CHANGE(arg1)); + return EV_DoCeiling (DCeiling::ceilRaiseToFloor, ln, arg0, 2, 0, arg3, CRUSH(arg2), 0, CHANGE(arg1)); } FUNC(LS_Ceiling_LowerToFloor) -// Ceiling_LowerToFloor (tag, speed, change, crush) +// Ceiling_LowerToFloor (tag, speed, change, crush, gap) { - return EV_DoCeiling (DCeiling::ceilLowerToFloor, ln, arg0, SPEED(arg1), 0, 0, CRUSH(arg3), 0, CHANGE(arg4)); + return EV_DoCeiling (DCeiling::ceilLowerToFloor, ln, arg0, SPEED(arg1), 0, arg4, CRUSH(arg3), 0, CHANGE(arg4)); } FUNC(LS_Ceiling_LowerByTexture) From 2c38e203525a0c8f158c42a32a6e7673e6dd3de9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 3 Aug 2016 13:16:14 +0200 Subject: [PATCH 19/26] - update xlat/eternity.txt for reference. --- wadsrc/static/xlat/eternity.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wadsrc/static/xlat/eternity.txt b/wadsrc/static/xlat/eternity.txt index 4db96f2da..90a41a4e8 100644 --- a/wadsrc/static/xlat/eternity.txt +++ b/wadsrc/static/xlat/eternity.txt @@ -251,3 +251,13 @@ enum 466 = 0, Floor_TransferTrigger(0) 467 = 0, Floor_TransferNumeric(0) 468 = 0, FloorAndCeiling_LowerRaise(0) +469 = 0, HealThing(0) +470 = 0, Sector_SetRotation(0) +471 = 0, Sector_SetFloorPanning(0) +472 = 0, Sector_SetCeilingPanning(0) +473 = 0, Light_MinNeighbor(0) +474 = 0, Polyobj_Stop(0) +475 = 0, Plat_RaiseAndStayTx0(0) +476 = 0, Plat_UpByValueStayTx(0) +477 = 0, ACS_ExecuteAlways(0) +478 = 0, Thing_Remove(0) From 1d434add503894c63f3e8bf1496d591b09854fb0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 4 Aug 2016 17:14:31 +0200 Subject: [PATCH 20/26] - fixed: monsters which were made friendly by the MBF map flag lost their friendliness when being revived with Thing_Raise. --- src/p_mobj.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 94df4c3bf..8971efe25 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6404,6 +6404,7 @@ void AActor::Revive() flags5 = info->flags5; flags6 = info->flags6; flags7 = info->flags7; + if (SpawnFlags & MTF_FRIENDLY) flags |= MF_FRIENDLY; DamageType = info->DamageType; health = SpawnHealth(); target = NULL; From 9229146eeb1dfaf867e3e5e6f053f8718a81f864 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 5 Aug 2016 12:13:47 +0200 Subject: [PATCH 21/26] - fixed: DFloor set the 'gap' for one wrong movement type. --- src/p_floor.cpp | 10 ++++------ src/p_lnspec.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 10bcf6d7e..ccb1c82e9 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -349,16 +349,14 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, break; case DFloor::floorRaiseAndCrushDoom: + height = 8; case DFloor::floorRaiseToLowestCeiling: floor->m_Direction = 1; - newheight = sec->FindLowestCeilingSurrounding(&spot); - if (floortype == DFloor::floorRaiseAndCrushDoom) - newheight -= 8; + newheight = sec->FindLowestCeilingSurrounding(&spot) - height; ceilingheight = sec->FindLowestCeilingPoint(&spot2); floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight); if (sec->floorplane.ZatPointDist(spot2, floor->m_FloorDestDist) > ceilingheight) - floor->m_FloorDestDist = sec->floorplane.PointToDist(spot2, - floortype == DFloor::floorRaiseAndCrushDoom ? ceilingheight - 8 : ceilingheight); + floor->m_FloorDestDist = sec->floorplane.PointToDist(spot2, floortype == ceilingheight - height); break; case DFloor::floorRaiseToHighest: @@ -393,7 +391,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, case DFloor::floorLowerToLowestCeiling: floor->m_Direction = -1; - newheight = sec->FindLowestCeilingSurrounding(&spot) - height; + newheight = sec->FindLowestCeilingSurrounding(&spot); floor->m_FloorDestDist = sec->floorplane.PointToDist(spot, newheight); break; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index dc6170c24..d0a56ee87 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -260,7 +260,13 @@ FUNC(LS_Door_Raise) FUNC(LS_Door_LockedRaise) // Door_LockedRaise (tag, speed, delay, lock, lighttag) { +#if 0 + // In Hexen this originally created a thinker running for nearly 4 years. + // Let's not do this unless it becomes necessary because this can hang tagwait. + return EV_DoDoor (arg2 || (level.flags2 & LEVEL2_HEXENHACK) ? DDoor::doorRaise : DDoor::doorOpen, ln, it, +#else return EV_DoDoor (arg2 ? DDoor::doorRaise : DDoor::doorOpen, ln, it, +#endif arg0, SPEED(arg1), TICS(arg2), arg3, arg4); } From 4a859393fe1ddac1c023f47a094c2b77da6a9f98 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Thu, 4 Aug 2016 19:45:24 +0200 Subject: [PATCH 22/26] Fixed: the game could crash while parsing expressions in some places --- src/thingdef/thingdef_exp.cpp | 2 +- src/thingdef/thingdef_expression.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 35932e0be..6a756d9b5 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -392,7 +392,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) return ParseAtan2(sc, identifier, cls); default: args = new FArgumentList; - func = dyn_cast(cls->Symbols.FindSymbol(identifier, true)); + func = (cls == nullptr) ? nullptr : dyn_cast(cls->Symbols.FindSymbol(identifier, true)); try { // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index acb26d05b..fee31a6e9 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -4410,6 +4410,8 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + ABORT(ctx.Class); + if (ctx.Class->NumOwnedStates == 0) { // This can't really happen @@ -4464,6 +4466,8 @@ FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPositi FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + ABORT(ctx.Class); + if (names[0] == NAME_None) { scope = NULL; From 73d0ed78fef46438581882c32014209d32ef4c0f Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Thu, 4 Aug 2016 19:58:57 +0200 Subject: [PATCH 23/26] Fixed: the game could crash while resolving expressions in some places --- src/thingdef/thingdef.cpp | 24 ++++++++++++++---------- src/thingdef/thingdef_parse.cpp | 33 ++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 4bb247f94..04ac21890 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -361,16 +361,20 @@ static void FinishThingdef() if (sfunc == NULL) { FCompileContext ctx(ti); - dmg->Resolve(ctx); - VMFunctionBuilder buildit; - buildit.Registers[REGT_POINTER].Get(1); // The self pointer - dmg->Emit(&buildit); - sfunc = buildit.MakeFunction(); - sfunc->NumArgs = 1; - sfunc->Proto = NULL; ///FIXME: Need a proper prototype here - // Save this function in case this damage value was reused - // (which happens quite easily with inheritance). - dmg->SetFunction(sfunc); + dmg = static_cast(dmg->Resolve(ctx)); + + if (dmg != nullptr) + { + VMFunctionBuilder buildit; + buildit.Registers[REGT_POINTER].Get(1); // The self pointer + dmg->Emit(&buildit); + sfunc = buildit.MakeFunction(); + sfunc->NumArgs = 1; + sfunc->Proto = NULL; ///FIXME: Need a proper prototype here + // Save this function in case this damage value was reused + // (which happens quite easily with inheritance). + dmg->SetFunction(sfunc); + } } def->Damage = sfunc; diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index f4bad69bb..566643b8e 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -191,7 +191,12 @@ static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls) FxExpression *expr = ParseExpression (sc, cls, true); sc.MustGetToken(';'); - if (!expr->isConstant()) + if (expr == nullptr) + { + sc.ScriptMessage("Error while resolving constant definition"); + FScriptPosition::ErrorCounter++; + } + else if (!expr->isConstant()) { sc.ScriptMessage("Constant definition is not a constant"); FScriptPosition::ErrorCounter++; @@ -247,16 +252,24 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls) if (sc.CheckToken('=')) { FxExpression *expr = ParseExpression (sc, cls, true); - if (!expr->isConstant()) + if (expr != nullptr) { - sc.ScriptMessage("'%s' must be constant", symname.GetChars()); - FScriptPosition::ErrorCounter++; + if (!expr->isConstant()) + { + sc.ScriptMessage("'%s' must be constant", symname.GetChars()); + FScriptPosition::ErrorCounter++; + } + else + { + currvalue = static_cast(expr)->GetValue().GetInt(); + } + delete expr; } else { - currvalue = static_cast(expr)->GetValue().GetInt(); + sc.ScriptMessage("Error while resolving expression of '%s'", symname.GetChars()); + FScriptPosition::ErrorCounter++; } - delete expr; } PSymbolConstNumeric *sym = new PSymbolConstNumeric(symname, TypeSInt32); sym->Value = currvalue; @@ -568,7 +581,13 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl if (sc.CheckToken('[')) { FxExpression *expr = ParseExpression(sc, cls, true); - if (!expr->isConstant()) + if (expr == nullptr) + { + sc.ScriptMessage("Error while resolving array size"); + FScriptPosition::ErrorCounter++; + maxelems = 1; + } + else if (!expr->isConstant()) { sc.ScriptMessage("Array size must be a constant"); FScriptPosition::ErrorCounter++; From 01fb2eaecc567818c798951b02e6425084a35ced Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Wed, 3 Aug 2016 19:37:19 +0200 Subject: [PATCH 24/26] Fixed a typo in FxBoolCast::Emit --- src/thingdef/thingdef_expression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index fee31a6e9..b57618575 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -414,7 +414,7 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) { build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.)); } - else if (from.RegNum == REGT_POINTER) + else if (from.RegType == REGT_POINTER) { build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); } From a893013dbbfd68895f9a44476a4b67368420f2c8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 5 Aug 2016 01:43:56 +0200 Subject: [PATCH 25/26] Adds HUD quadruple scale and a scale slider for the crosshair --- src/c_console.cpp | 28 +++++++++++++++-- src/ct_chat.cpp | 24 +++++++++++++-- src/g_shared/hudmessages.cpp | 58 ++++++++++++++++++++++++++++++++++-- src/g_shared/shared_hud.cpp | 28 +++++++++++++++-- src/g_shared/shared_sbar.cpp | 20 +++++++++++-- wadsrc/static/language.enu | 2 ++ wadsrc/static/menudef.txt | 4 ++- 7 files changed, 150 insertions(+), 14 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 2f221e319..9a9274aa1 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -162,7 +162,7 @@ CVAR (Bool, con_centernotify, false, CVAR_ARCHIVE) CUSTOM_CVAR (Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high resolutions? { if (self < 0) self = 0; - if (self > 2) self = 2; + if (self > 3) self = 3; } CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE) @@ -493,7 +493,14 @@ void C_AddNotifyString (int printlevel, const char *source) return; } - width = con_scaletext > 1 ? DisplayWidth/2 : con_scaletext == 1 ? DisplayWidth / CleanXfac : DisplayWidth; + switch (con_scaletext) + { + default: + case 0: width = DisplayWidth; break; + case 1: width = DisplayWidth / CleanXfac; break; + case 2: width = DisplayWidth / 2; break; + case 3: width = DisplayWidth / 4; break; + } if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].PrintLevel == printlevel) { @@ -770,6 +777,23 @@ static void C_DrawNotifyText () line, NotifyStrings[i].Text, DTA_AlphaF, alpha, TAG_DONE); } + else if (con_scaletext == 3) + { + if (!center) + screen->DrawText (SmallFont, color, 0, line, NotifyStrings[i].Text, + DTA_VirtualWidth, screen->GetWidth() / 4, + DTA_VirtualHeight, screen->GetHeight() / 4, + DTA_KeepRatio, true, + DTA_AlphaF, alpha, TAG_DONE); + else + screen->DrawText (SmallFont, color, (screen->GetWidth() / 4 - + SmallFont->StringWidth (NotifyStrings[i].Text))/4, + line, NotifyStrings[i].Text, + DTA_VirtualWidth, screen->GetWidth() / 4, + DTA_VirtualHeight, screen->GetHeight() / 4, + DTA_KeepRatio, true, + DTA_AlphaF, alpha, TAG_DONE); + } else { if (!center) diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index d814717c9..b053d8bd8 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -234,9 +234,27 @@ void CT_Drawer (void) scalex = 1; } - int screen_width = con_scaletext > 1? SCREENWIDTH/2 : SCREENWIDTH; - int screen_height = con_scaletext > 1? SCREENHEIGHT/2 : SCREENHEIGHT; - int st_y = con_scaletext > 1? ST_Y/2 : ST_Y; + int screen_width, screen_height, st_y; + switch (con_scaletext) + { + default: + case 0: + case 1: + screen_width = SCREENWIDTH; + screen_height = SCREENHEIGHT; + st_y = ST_Y; + break; + case 2: + screen_width = SCREENWIDTH / 2; + screen_height = SCREENHEIGHT / 2; + st_y = ST_Y / 2; + break; + case 3: + screen_width = SCREENWIDTH / 4; + screen_height = SCREENHEIGHT / 4; + st_y = ST_Y / 4; + break; + } y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y; diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 0ee61f942..9f13d3d9e 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -260,7 +260,14 @@ void DHUDMessage::ResetText (const char *text) } else { - width = con_scaletext >= 2 ? SCREENWIDTH/2 : (con_scaletext ? SCREENWIDTH / CleanXfac : SCREENWIDTH); + switch (con_scaletext) + { + default: + case 0: width = SCREENWIDTH; break; + case 1: width = SCREENWIDTH / CleanXfac; break; + case 2: width = SCREENWIDTH / 2; break; + case 3: width = SCREENWIDTH / 4; break; + } } if (Lines != NULL) @@ -334,12 +341,18 @@ void DHUDMessage::Draw (int bottom, int visibility) else { xscale = yscale = 1; - if (HUDWidth==0 && con_scaletext>1) + if (HUDWidth==0 && con_scaletext==2) { screen_width/=2; screen_height/=2; bottom/=2; } + else if (HUDWidth==0 && con_scaletext==3) + { + screen_width/=4; + screen_height/=4; + bottom/=4; + } } if (HUDWidth == 0) @@ -448,6 +461,16 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) DTA_RenderStyle, Style, TAG_DONE); } + else if (con_scaletext == 3) + { + screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, + DTA_VirtualWidth, SCREENWIDTH/4, + DTA_VirtualHeight, SCREENHEIGHT/4, + DTA_AlphaF, Alpha, + DTA_RenderStyle, Style, + DTA_KeepRatio, true, + TAG_DONE); + } else { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, @@ -551,6 +574,16 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh DTA_RenderStyle, Style, TAG_DONE); } + else if (con_scaletext == 3) + { + screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, + DTA_VirtualWidth, SCREENWIDTH/4, + DTA_VirtualHeight, SCREENHEIGHT/4, + DTA_AlphaF, trans, + DTA_RenderStyle, Style, + DTA_KeepRatio, true, + TAG_DONE); + } else { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, @@ -651,6 +684,16 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu DTA_RenderStyle, Style, TAG_DONE); } + else if (con_scaletext == 3) + { + screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, + DTA_VirtualWidth, SCREENWIDTH/4, + DTA_VirtualHeight, SCREENHEIGHT/4, + DTA_AlphaF, trans, + DTA_RenderStyle, Style, + DTA_KeepRatio, true, + TAG_DONE); + } else { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, @@ -830,6 +873,17 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in DTA_RenderStyle, Style, TAG_DONE); } + else if (con_scaletext == 3) + { + screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, + DTA_VirtualWidth, SCREENWIDTH/4, + DTA_VirtualHeight, SCREENHEIGHT/4, + DTA_KeepRatio, true, + DTA_TextLen, LineVisible, + DTA_AlphaF, Alpha, + DTA_RenderStyle, Style, + TAG_DONE); + } else { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 3a8dc388c..c9e87d642 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -885,8 +885,25 @@ static void DrawCoordinates(player_t * CPlayer) pos = DVector3(apos, z); } - int vwidth = con_scaletext==0? SCREENWIDTH : SCREENWIDTH/2; - int vheight = con_scaletext==0? SCREENHEIGHT : SCREENHEIGHT/2; + int vwidth, vheight; + switch (con_scaletext) + { + default: + case 0: + vwidth = SCREENWIDTH; + vheight = SCREENWIDTH; + break; + case 1: + case 2: + vwidth = SCREENWIDTH/2; + vheight = SCREENWIDTH/2; + break; + case 3: + vwidth = SCREENWIDTH/4; + vheight = SCREENWIDTH/4; + break; + } + int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6; int ypos = 18; @@ -1073,7 +1090,12 @@ void DrawHUD() if (hud_althudscale && SCREENWIDTH>640) { hudwidth=SCREENWIDTH/2; - if (hud_althudscale == 2) + if (hud_althudscale == 3) + { + hudwidth = SCREENWIDTH / 4; + hudheight = SCREENHEIGHT / 4; + } + else if (hud_althudscale == 2) { // Optionally just double the pixels to reduce scaling artifacts. hudheight=SCREENHEIGHT/2; diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index b48c04893..c3b1fd262 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -108,7 +108,7 @@ CVAR (Int, crosshair, 0, CVAR_ARCHIVE) CVAR (Bool, crosshairforce, false, CVAR_ARCHIVE) CVAR (Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE); CVAR (Bool, crosshairhealth, true, CVAR_ARCHIVE); -CVAR (Bool, crosshairscale, false, CVAR_ARCHIVE); +CVAR (Float, crosshairscale, 1.0, CVAR_ARCHIVE); CVAR (Bool, crosshairgrow, false, CVAR_ARCHIVE); CUSTOM_CVAR(Int, am_showmaplabel, 2, CVAR_ARCHIVE) { @@ -1106,9 +1106,9 @@ void DBaseStatusBar::DrawCrosshair () return; } - if (crosshairscale) + if (crosshairscale > 0.0f) { - size = SCREENHEIGHT / 200.; + size = SCREENHEIGHT * crosshairscale / 200.; } else { @@ -1247,6 +1247,13 @@ void DBaseStatusBar::Draw (EHudState state) xpos = vwidth - 80; y = ::ST_Y - height; } + else if (con_scaletext == 3) + { + vwidth = SCREENWIDTH/4; + vheight = SCREENHEIGHT/4; + xpos = vwidth - SmallFont->StringWidth("X: -00000")-6; + y = ::ST_Y/4 - height; + } else { vwidth = SCREENWIDTH/2; @@ -1259,6 +1266,8 @@ void DBaseStatusBar::Draw (EHudState state) { if (con_scaletext == 0) y -= height * 4; + else if (con_scaletext == 3) + y -= height; else y -= height * 2; } @@ -1407,6 +1416,11 @@ void DBaseStatusBar::DrawLog () hudwidth = SCREENWIDTH / 2; hudheight = SCREENHEIGHT / 2; break; + + case 3: + hudwidth = SCREENWIDTH / 4; + hudheight = SCREENHEIGHT / 4; + break; } int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560; diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index cef67aca9..03a3ffb1a 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2197,6 +2197,7 @@ OPTVAL_PLAYER = "Player"; OPTVAL_MAP = "Map"; OPTVAL_SCALETO640X400 = "Scale to 640x400"; OPTVAL_PIXELDOUBLE = "Pixel double"; +OPTVAL_PIXELQUADRUPLE = "Pixel quadruple"; OPTVAL_CURRENTWEAPON = "Current weapon"; OPTVAL_AVAILABLEWEAPONS = "Available weapons"; OPTVAL_ALLWEAPONS = "All weapons"; @@ -2231,6 +2232,7 @@ OPTVAL_ANIMATED = "Animated"; OPTVAL_ROTATED = "Rotated"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only"; OPTVAL_DOUBLE = "Double"; +OPTVAL_QUADRUPLE = "Quadruple"; OPTVAL_ITEMPICKUP = "Item Pickup"; OPTVAL_OBITUARIES = "Obituaries"; OPTVAL_CRITICALMESSAGES = "Critical Messages"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 2a59c4103..ca36c1975 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -760,7 +760,7 @@ OptionMenu "HUDOptions" Option "$HUDMNU_GROWCROSSHAIR", "crosshairgrow", "OnOff" ColorPicker "$HUDMNU_CROSSHAIRCOLOR", "crosshaircolor" Option "$HUDMNU_CROSSHAIRHEALTH", "crosshairhealth", "OnOff" - Option "$HUDMNU_CROSSHAIRSCALE", "crosshairscale", "OnOff" + Slider "$HUDMNU_CROSSHAIRSCALE", "crosshairscale", 0.0, 2.0, 0.05, 2 StaticText " " Option "$HUDMNU_NAMETAGS", "displaynametags", "DisplayTagsTypes" Option "$HUDMNU_NAMETAGCOLOR", "nametagcolor", "TextColors", "displaynametags" @@ -791,6 +791,7 @@ OptionValue "AltHUDScale" 0, "$OPTVAL_OFF" 1, "$OPTVAL_SCALETO640X400" 2, "$OPTVAL_PIXELDOUBLE" + 3, "$OPTVAL_PIXELQUADRUPLE" } OptionValue "AltHUDAmmo" @@ -1107,6 +1108,7 @@ OptionValue ScaleValues 0, "$OPTVAL_OFF" 1, "$OPTVAL_ON" 2, "$OPTVAL_DOUBLE" + 3, "$OPTVAL_QUADRUPLE" } OptionValue MessageLevels From fd7b833ad568386086d2101f7f8403dda405d919 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 6 Aug 2016 19:20:41 +0200 Subject: [PATCH 26/26] - added some helper code mainly designed to help GZDoom maintain the vertex buffer for the textured automap. --- src/am_map.cpp | 2 ++ src/v_draw.cpp | 13 +++++++++++++ src/v_video.h | 3 +++ 3 files changed, 18 insertions(+) diff --git a/src/am_map.cpp b/src/am_map.cpp index 3a4e0aaa1..7e346843b 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1897,6 +1897,7 @@ void AM_drawSubsectors() FDynamicColormap *colormap; mpoint_t originpt; + screen->StartSimplePolys(); for (int i = 0; i < numsubsectors; ++i) { if (subsectors[i].flags & SSECF_POLYORG) @@ -2049,6 +2050,7 @@ void AM_drawSubsectors() ); } } + screen->FinishSimplePolys(); } //============================================================================= diff --git a/src/v_draw.cpp b/src/v_draw.cpp index c7b62b0a6..89023d4bd 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1244,6 +1244,19 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin } } +//========================================================================== +// +// no-ops. This is so that renderer backends can better manage the +// processing of the subsector drawing in the automap +// +//========================================================================== + +void DCanvas::StartSimplePolys() +{} + +void DCanvas::FinishSimplePolys() +{} + //========================================================================== // // DCanvas :: FillSimplePoly diff --git a/src/v_video.h b/src/v_video.h index fa1ce83df..7091c518d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -216,6 +216,9 @@ public: // Fill an area with a texture virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); + virtual void StartSimplePolys(); + virtual void FinishSimplePolys(); + // Fill a simple polygon with a texture virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation,