From 2afadb010807326d20642d035e2f1f89ea9db8b8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jun 2016 23:41:34 +0200 Subject: [PATCH 01/11] - fixed: ADehackedPickup was missing NULL pointer checks in nearly all methods that used RealPickup. Some DECORATE hacks make it possible that this does not contain a valid pointer when these methods are called. --- src/d_dehacked.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index a7a378375..e4acc75a6 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3123,22 +3123,29 @@ bool ADehackedPickup::TryPickup (AActor *&toucher) const char *ADehackedPickup::PickupMessage () { - return RealPickup->PickupMessage (); + if (RealPickup != nullptr) + return RealPickup->PickupMessage (); + else return ""; } bool ADehackedPickup::ShouldStay () { - return RealPickup->ShouldStay (); + if (RealPickup != nullptr) + return RealPickup->ShouldStay (); + else return true; } bool ADehackedPickup::ShouldRespawn () { - return RealPickup->ShouldRespawn (); + if (RealPickup != nullptr) + return RealPickup->ShouldRespawn (); + else return false; } void ADehackedPickup::PlayPickupSound (AActor *toucher) { - RealPickup->PlayPickupSound (toucher); + if (RealPickup != nullptr) + RealPickup->PlayPickupSound (toucher); } void ADehackedPickup::DoPickupSpecial (AActor *toucher) @@ -3146,19 +3153,19 @@ void ADehackedPickup::DoPickupSpecial (AActor *toucher) Super::DoPickupSpecial (toucher); // If the real pickup hasn't joined the toucher's inventory, make sure it // doesn't stick around. - if (RealPickup->Owner != toucher) + if (RealPickup != nullptr && RealPickup->Owner != toucher) { RealPickup->Destroy (); } - RealPickup = NULL; + RealPickup = nullptr; } void ADehackedPickup::Destroy () { - if (RealPickup != NULL) + if (RealPickup != nullptr) { RealPickup->Destroy (); - RealPickup = NULL; + RealPickup = nullptr; } Super::Destroy (); } From 9cf1d9669871bc100367638d02220404fd2ebac4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Jun 2016 12:04:35 +0200 Subject: [PATCH 02/11] - added identification for delaweare.wad to the list of supported IWADs. --- wadsrc/static/iwadinfo.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index 8fafdcfa4..d0fb1a157 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -1,5 +1,16 @@ // Must be sorted in identification order (easiest to recognize first!) +IWad +{ + Name = "Delaweare" + Autoname = "delaweare" + Game = "Doom" + Config = "Delaweare" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "TITLEMAP", "ROVEA0", "GRLURD01", "SQOUI01" + BannerColors = "00 00 00", "ff ff ff" +} + IWad { Name = "The Adventures of Square" @@ -393,4 +404,5 @@ Names "hacx.wad" "hacx2.wad" "square1.pk3" + "delaweare.wad" } From 8a08fb2f6aa497d583a775cb6ddae191154a15c6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 4 Jun 2016 20:52:56 +0200 Subject: [PATCH 03/11] - fixed nullptr/bool mixup. --- src/p_things.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_things.cpp b/src/p_things.cpp index cad3022b0..374be69d6 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -673,7 +673,7 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in // We need these to check out. if (!ref || !classname || distance <= 0) - return nullptr; + return false; int counter = 0; bool result = false; From 1703842a9404f8c12ced1a2547714f05bfea5873 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 6 Jun 2016 10:48:40 +0200 Subject: [PATCH 04/11] - fixed some issues with teleport fog: * many calls didn't use TELEFOGHEIGHT, mostly those coming from external code submissions that never were tested on anything but Doom. Addressed by adding this value inside P_SpawnTeleportFog and making the distinction between projectiles and non-projectiles from P_Teleport also part of this function. * there were still a few places which spawned the teleport fog directly, skipping all the added features of P_SpawnTeleportFog. --- src/g_heretic/a_dsparil.cpp | 3 +-- src/g_heretic/a_hereticmisc.cpp | 1 + src/g_strife/a_rebels.cpp | 2 +- src/p_mobj.cpp | 6 +++--- src/p_teleport.cpp | 6 +++--- src/p_things.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index a978f3097..124cb1403 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -287,8 +287,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) self->SetState (self->FindState(NAME_Death)); self->flags &= ~MF_MISSILE; mo->master = self->target; - // Heretic did not offset it by TELEFOGHEIGHT, so I won't either. - Spawn (self->Pos(), ALLOW_REPLACE); + P_SpawnTeleportFog(self, self->Pos(), false, true); } } return 0; diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index c8a330536..95c2ae6d0 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -17,6 +17,7 @@ #include "farchive.h" #include "d_player.h" #include "a_morph.h" +#include "p_spec.h" // Include all the other Heretic stuff here to reduce compile time #include "a_chicken.cpp" diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index dd5267c60..f2031a7a3 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon) rebel->SetState (rebel->SeeState); rebel->Angles.Yaw = self->Angles.Yaw; - Spawn (rebel->Vec3Angle(20., self->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); + P_SpawnTeleportFog(rebel, rebel->Vec3Angle(20., self->Angles.Yaw, 0), false, true); if (--self->health < 0) { self->SetState(self->FindState(NAME_Death)); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 97167f245..21455207b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2789,10 +2789,10 @@ void P_NightmareRespawn (AActor *mobj) mo->Prev.Z = z; // Do not interpolate Z position if we changed it since spawning. // spawn a teleport fog at old spot because of removal of the body? - P_SpawnTeleportFog(mobj, mobj->PosPlusZ(TELEFOGHEIGHT), true, true); + P_SpawnTeleportFog(mobj, mobj->Pos(), true, true); // spawn a teleport fog at the new spot - P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint, z + TELEFOGHEIGHT), false, true); + P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint, z), false, true); // remove the old monster mobj->Destroy (); @@ -4685,7 +4685,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) if (multiplayer) { - Spawn ("TeleportFog", mobj->Vec3Angle(20., mobj->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); + P_SpawnTeleportFog(mobj, mobj->Vec3Angle(20., mobj->Angles.Yaw, 0.), false, true); } // "Fix" for one of the starts on exec.wad MAP01: If you start inside the ceiling, diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index a3dbd0899..f65e2f402 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -88,7 +88,8 @@ void P_SpawnTeleportFog(AActor *mobj, const DVector3 &pos, bool beforeTele, bool } else { - mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), pos, ALLOW_REPLACE); + double fogDelta = mobj->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; + mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), DVector3(pos, pos.Z + fogDelta), ALLOW_REPLACE); } if (mo != NULL && setTarget) @@ -191,10 +192,9 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) { if (!predicting) { - double fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; DVector2 vector = angle.ToVector(20); DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y); - P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z() + fogDelta), false, true); + P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true); } if (thing->player) diff --git a/src/p_things.cpp b/src/p_things.cpp index 374be69d6..98826268c 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -98,7 +98,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, i mobj->Angles.Yaw = (angle != 1000000. ? angle : spot->Angles.Yaw); if (fog) { - P_SpawnTeleportFog(mobj, spot->PosPlusZ(TELEFOGHEIGHT), false, true); + P_SpawnTeleportFog(mobj, spot->Pos(), false, true); } if (mobj->flags & MF_SPECIAL) mobj->flags |= MF_DROPPED; // Don't respawn From cf21bb15246d09e0f8becc83a1d8ddd37b1971a7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 8 Jun 2016 10:46:35 +0200 Subject: [PATCH 05/11] - reinstated abort-on-error for any problem that gets reported during DECORATE code generation. - fixed: DECORATE allowed a silent conversion from names to integers. In old versions the name was converted to 0, since the scripting branch to the name index. Reverted to the old behavior but added a warning message. --- src/thingdef/thingdef.cpp | 2 +- src/thingdef/thingdef_exp.h | 2 +- src/thingdef/thingdef_expression.cpp | 49 ++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index a24e8831c..4bb247f94 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -431,11 +431,11 @@ void LoadActors () FScanner sc(lump); ParseDecorate (sc); } + FinishThingdef(); if (FScriptPosition::ErrorCounter > 0) { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } - FinishThingdef(); timer.Unclock(); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 9ec605626..ac6b7eda3 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -208,7 +208,7 @@ public: virtual bool isConstant() const; virtual void RequestAddress(); virtual VMFunction *GetDirectFunction(); - bool IsNumeric() const { return ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT; } + bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } virtual ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index c888f97d5..2e60dfa97 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -358,10 +358,22 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { - FxExpression *x = basex; - basex = NULL; - delete this; - return x; + if (basex->ValueType != TypeName) + { + FxExpression *x = basex; + basex = NULL; + delete this; + return x; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( + if (!basex->isConstant()) ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression * x = new FxConstant(0, ScriptPosition); + delete this; + return x; + } } else if (basex->ValueType->GetRegType() == REGT_FLOAT) { @@ -374,12 +386,9 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) } return this; } - else - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return NULL; } //========================================================================== @@ -443,14 +452,26 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) } else if (basex->ValueType->GetRegType() == REGT_INT) { - if (basex->isConstant()) + if (basex->ValueType != TypeName) { - ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( + if (!basex->isConstant()) ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression *x = new FxConstant(0.0, ScriptPosition); delete this; return x; } - return this; } else { From ef86b3975a23723762b7c2d09414f977f1a72a8d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 8 Jun 2016 10:56:11 +0200 Subject: [PATCH 06/11] - added 'strictdecorate' CVAR. If this is set to 'true', any DECORATE error that had to be demoted to a warning for backwards compatibility will be treated as an actual error. --- src/dobjtype.cpp | 4 +++- src/sc_man.cpp | 6 ++++++ src/sc_man.h | 1 + src/thingdef/thingdef_expression.cpp | 12 ++++++------ src/thingdef/thingdef_properties.cpp | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index febcad0b5..6b963f6d4 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -60,6 +60,7 @@ // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- +EXTERN_CVAR(Bool, strictdecorate); // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -3067,7 +3068,8 @@ void PClass::InsertIntoHash () if (found != NULL) { // This type has already been inserted // ... but there is no need whatsoever to make it a fatal error! - Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); + if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); + else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); TypeTable.ReplaceType(this, found, bucket); } else diff --git a/src/sc_man.cpp b/src/sc_man.cpp index dadbae0ed..da106927e 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1038,11 +1038,17 @@ FScriptPosition &FScriptPosition::operator=(const FScriptPosition &other) // //========================================================================== +CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) + void FScriptPosition::Message (int severity, const char *message, ...) const { FString composed; if ((severity == MSG_DEBUG || severity == MSG_DEBUGLOG) && !developer) return; + if (severity == MSG_OPTERROR) + { + severity = strictdecorate ? MSG_ERROR : MSG_WARNING; + } if (message == NULL) { diff --git a/src/sc_man.h b/src/sc_man.h index b1231e547..359dd8140 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -124,6 +124,7 @@ enum MSG_WARNING, MSG_FATAL, MSG_ERROR, + MSG_OPTERROR, MSG_DEBUG, MSG_LOG, MSG_DEBUGLOG, diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 2e60dfa97..d500458a2 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -368,8 +368,8 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) else { // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( - if (!basex->isConstant()) ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got a name"); - else ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression * x = new FxConstant(0, ScriptPosition); delete this; return x; @@ -466,8 +466,8 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) else { // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( - if (!basex->isConstant()) ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got a name"); - else ScriptPosition.Message(MSG_WARNING, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression *x = new FxConstant(0.0, ScriptPosition); delete this; return x; @@ -3924,7 +3924,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { /* lax */ // Since this happens in released WADs it must pass without a terminal error... :( - ScriptPosition.Message(MSG_WARNING, + ScriptPosition.Message(MSG_OPTERROR, "Unknown class name '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); } @@ -4095,7 +4095,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) destination = scope->FindState(names.Size()-1, &names[1], false); if (destination == NULL) { - ScriptPosition.Message(MSG_WARNING, "Unknown state jump destination"); + ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination"); /* lax */ return this; } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 3ec4c624d..db6ef14a0 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -457,7 +457,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor) } if (bag.StateSet) { - bag.ScriptPosition.Message(MSG_WARNING, + bag.ScriptPosition.Message(MSG_OPTERROR, "'skip_super' must appear before any state definitions."); return; } From c4d8950a7f613e542184e87bc646bca2e23a4ad1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 10 Jun 2016 13:23:23 +0200 Subject: [PATCH 07/11] - fixed: APROP_Friction was missing a 'break'. --- src/p_acs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2de959be6..7c031d243 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3968,6 +3968,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) case APROP_Friction: actor->Friction = ACSToDouble(value); + break; case APROP_MaxStepHeight: actor->MaxStepHeight = ACSToDouble(value); From f78705619826e2f45724715b36148b4e3af99525 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 10 Jun 2016 18:15:43 -0500 Subject: [PATCH 08/11] - Added endsize parameter and SPF_NOTIMEFREEZE for A_SpawnParticle. SPF_NOTIMEFREEZE processes particles with this flag regardless of time freeze. The endsize parameter changes the scale of the particle to that size throughout its lifetime linearly. --- src/p_acs.cpp | 7 ++++--- src/p_effect.cpp | 27 ++++++++++++++++++++------- src/p_effect.h | 6 ++++-- src/p_tick.cpp | 5 +---- src/thingdef/thingdef_codeptr.cpp | 9 +++++---- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/constants.txt | 1 + 7 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 7c031d243..ca5e41757 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6048,7 +6048,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) PalEntry color = args[0]; bool fullbright = argCount > 1 ? !!args[1] : false; int lifetime = argCount > 2 ? args[2] : 35; - int size = argCount > 3 ? args[3] : 1; + double size = argCount > 3 ? args[3] : 1.; int x = argCount > 4 ? args[4] : 0; int y = argCount > 5 ? args[5] : 0; int z = argCount > 6 ? args[6] : 0; @@ -6060,17 +6060,18 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) int accelz = argCount > 12 ? args[12] : 0; int startalpha = argCount > 13 ? args[13] : 0xFF; // Byte trans int fadestep = argCount > 14 ? args[14] : -1; + double endsize = argCount > 15 ? args[15] : -1.; startalpha = clamp(startalpha, 0, 255); // Clamp to byte lifetime = clamp(lifetime, 0, 255); // Clamp to byte fadestep = clamp(fadestep, -1, 255); // Clamp to byte inc. -1 (indicating automatic) - size = clamp(size, 0, 65535); // Clamp to word + size = fabs(size); if (lifetime != 0) P_SpawnParticle(DVector3(ACSToDouble(x), ACSToDouble(y), ACSToDouble(z)), DVector3(ACSToDouble(xvel), ACSToDouble(yvel), ACSToDouble(zvel)), DVector3(ACSToDouble(accelx), ACSToDouble(accely), ACSToDouble(accelz)), - color, fullbright, startalpha/255., lifetime, size, fadestep/255.); + color, startalpha/255., lifetime, size, endsize, fadestep/255., fullbright); } break; diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 25838459d..c678f8def 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -252,7 +252,6 @@ void P_InitEffects () blood2 = ParticleColor(RPART(kind)/3, GPART(kind)/3, BPART(kind)/3); } - void P_ThinkParticles () { int i; @@ -262,13 +261,19 @@ void P_ThinkParticles () prev = NULL; while (i != NO_PARTICLE) { - BYTE oldtrans; - particle = Particles + i; i = particle->tnext; + + if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN))) + { + continue; + } + + BYTE oldtrans; oldtrans = particle->trans; particle->trans -= particle->fade; - if (oldtrans < particle->trans || --particle->ttl == 0) + particle->size += particle->sizestep; + if (oldtrans < particle->trans || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it memset (particle, 0, sizeof(particle_t)); if (prev) @@ -309,8 +314,14 @@ void P_ThinkParticles () } } +enum PSFlag +{ + PS_FULLBRIGHT = 1, + PS_NOTIMEFREEZE = 1 << 5, +}; -void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, bool fullbright, double startalpha, int lifetime, WORD size, double fadestep) +void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, + double fadestep, double endsize, int flags) { particle_t *particle = NewParticle(); @@ -324,8 +335,10 @@ void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &a if (fadestep < 0) particle->fade = FADEFROMTTL(lifetime); else particle->fade = int(fadestep * 255); particle->ttl = lifetime; - particle->bright = fullbright; - particle->size = (WORD)size; + particle->bright = !!(flags & PS_FULLBRIGHT); + particle->size = size; + particle->sizestep = (lifetime == 0) ? 0 : ((endsize - size) / lifetime); + particle->notimefreeze = !!(flags & PS_NOTIMEFREEZE); } } diff --git a/src/p_effect.h b/src/p_effect.h index 033bf042c..2414372c3 100644 --- a/src/p_effect.h +++ b/src/p_effect.h @@ -59,13 +59,15 @@ struct particle_t DVector3 Acc; BYTE ttl; BYTE trans; - WORD size; + double size; + double sizestep; BYTE bright; BYTE fade; int color; WORD tnext; WORD snext; subsector_t * subsector; + bool notimefreeze; }; extern particle_t *Particles; @@ -83,7 +85,7 @@ particle_t *JitterParticle (int ttl); particle_t *JitterParticle (int ttl, double drift); void P_ThinkParticles (void); -void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, bool fullbright, double startalpha, int lifetime, WORD size, double fadestep); +void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double endsize, int flags = 0); void P_InitEffects (void); void P_RunEffects (void); diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 032aa8bf5..f0f1e2ea8 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -117,10 +117,7 @@ void P_Ticker (void) // Since things will be moving, it's okay to interpolate them in the renderer. r_NoInterpolate = false; - if (!bglobal.freeze && !(level.flags2 & LEVEL2_FROZEN)) - { - P_ThinkParticles (); // [RH] make the particles think - } + P_ThinkParticles(); // [RH] make the particles think for (i = 0; i 0) fadestep = clamp(fadestep, 0., 1.); - size = clamp(size, 0, 65535); // Clamp to word - + size = fabs(size); if (lifetime != 0) { if (flags & SPF_RELANG) angle += self->Angles.Yaw; @@ -3199,7 +3200,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) acc.X = accelx * c + accely * s; acc.Y = accelx * s - accely * c; } - P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, !!(flags & SPF_FULLBRIGHT), startalpha, lifetime, size, fadestep); + P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, endsize, flags); } return 0; } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index cc0569fff..6606f8a49 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -214,7 +214,7 @@ ACTOR Actor native //: Thinker native void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false); native void A_SetMass(int mass); native void A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); - native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, int size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1); + native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1, float endsize = -1); native state A_CheckSight(state label); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 911e1036b..f5072d55e 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -539,6 +539,7 @@ enum SPF_RELVEL = 1 << 2, SPF_RELACCEL = 1 << 3, SPF_RELANG = 1 << 4, + SPF_NOTIMEFREEZE = 1 << 5, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From d8bf958a06dbaae03b4fd1ff8a6e12dd4f7dccd0 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 10 Jun 2016 21:41:13 -0500 Subject: [PATCH 09/11] Fixed: Frozen particles would still be deleted when frozen instead of doing nothing with. --- src/p_effect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_effect.cpp b/src/p_effect.cpp index c678f8def..7aff1c5cc 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -263,12 +263,12 @@ void P_ThinkParticles () { particle = Particles + i; i = particle->tnext; - if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN))) { + prev = particle; continue; } - + BYTE oldtrans; oldtrans = particle->trans; particle->trans -= particle->fade; From ebe3f2367756dde5d4fb1a03c5c8a30673ad0fff Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Sun, 5 Jun 2016 19:52:53 +0200 Subject: [PATCH 10/11] Added GetCVar(string name) Works like ACS's GetCVar --- src/c_cvars.cpp | 38 ++++++++++++++++++++++ src/c_cvars.h | 4 +++ src/p_acs.cpp | 52 ++++++------------------------- src/thingdef/thingdef_codeptr.cpp | 30 ++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 5 files changed, 82 insertions(+), 43 deletions(-) diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 36e3d576b..c8f1ee4c6 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1488,6 +1488,44 @@ FBaseCVar *FindCVarSub (const char *var_name, int namelen) return var; } +FBaseCVar *GetCVar(AActor *activator, const char *cvarname) +{ + FBaseCVar *cvar = FindCVar(cvarname, nullptr); + // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return nullptr. + if (cvar == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + else + { + // For userinfo cvars, redirect to GetUserCVar + if (cvar->GetFlags() & CVAR_USERINFO) + { + if (activator == nullptr || activator->player == nullptr) + { + return nullptr; + } + return GetUserCVar(int(activator->player - players), cvarname); + } + return cvar; + } +} + +FBaseCVar *GetUserCVar(int playernum, const char *cvarname) +{ + if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) + { + return nullptr; + } + FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); + FBaseCVar *cvar; + if (cvar_p == nullptr || (cvar = *cvar_p) == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + return cvar; +} + //=========================================================================== // // C_CreateCVar diff --git a/src/c_cvars.h b/src/c_cvars.h index 59a3208d1..be7676e89 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -186,6 +186,10 @@ void C_BackupCVars (void); FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); FBaseCVar *FindCVarSub (const char *var_name, int namelen); +// Used for ACS and DECORATE. +FBaseCVar *GetCVar(AActor *activator, const char *cvarname); +FBaseCVar *GetUserCVar(int playernum, const char *cvarname); + // Create a new cvar with the specified name and type FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, DWORD flags); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index ca5e41757..29c9fe8fe 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4657,7 +4657,11 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) { UCVarValue val; - if (is_string) + if (cvar == nullptr) + { + return 0; + } + else if (is_string) { val = cvar->GetGenericRep(CVAR_String); return GlobalACSStrings.AddString(val.String); @@ -4674,44 +4678,6 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) } } -static int GetUserCVar(int playernum, const char *cvarname, bool is_string) -{ - if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) - { - return 0; - } - FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); - FBaseCVar *cvar; - if (cvar_p == NULL || (cvar = *cvar_p) == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - return DoGetCVar(cvar, is_string); -} - -static int GetCVar(AActor *activator, const char *cvarname, bool is_string) -{ - FBaseCVar *cvar = FindCVar(cvarname, NULL); - // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return 0. - if (cvar == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - else - { - // For userinfo cvars, redirect to GetUserCVar - if (cvar->GetFlags() & CVAR_USERINFO) - { - if (activator == NULL || activator->player == NULL) - { - return 0; - } - return GetUserCVar(int(activator->player - players), cvarname, is_string); - } - return DoGetCVar(cvar, is_string); - } -} - static int SetUserCVar(int playernum, const char *cvarname, int value, bool is_string) { if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) @@ -5396,7 +5362,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetCVarString: if (argCount == 1) { - return GetCVar(activator, FBehavior::StaticLookupString(args[0]), true); + return DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(args[0])), true); } break; @@ -5417,14 +5383,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetUserCVar: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), false); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), false); } break; case ACSF_GetUserCVarString: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), true); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), true); } break; @@ -9132,7 +9098,7 @@ scriptwait: break; case PCD_GETCVAR: - STACK(1) = GetCVar(activator, FBehavior::StaticLookupString(STACK(1)), false); + STACK(1) = DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(STACK(1))), false); break; case PCD_SETHUDSIZE: diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 80e8226f6..dbbb12f6a 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -513,6 +513,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) return 0; } +//========================================================================== +// +// GetCVar +// +// NON-ACTION function that works like ACS's GetCVar. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCVar) +{ + if (numret > 0) + { + assert(ret != nullptr); + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(cvarname); + + FBaseCVar *cvar = GetCVar(self, cvarname); + if (cvar == nullptr) + { + ret->SetFloat(0); + } + else + { + ret->SetFloat(cvar->GetGenericRep(CVAR_Float).Float); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 6606f8a49..5c46d0d4b 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -47,6 +47,7 @@ ACTOR Actor native //: Thinker native int GetSpawnHealth(); native int GetGibHealth(); native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); + native float GetCVar(string cvar); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. From fb286d17378df58c6f3865a0830274782222f736 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 11 Jun 2016 08:05:29 -0500 Subject: [PATCH 11/11] - Changed endsize to sizestep. Endsize affected more things than I thought it would. --- src/p_effect.cpp | 4 ++-- src/p_effect.h | 2 +- src/thingdef/thingdef_codeptr.cpp | 4 ++-- wadsrc/static/actors/actor.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 7aff1c5cc..7919b8d46 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -321,7 +321,7 @@ enum PSFlag }; void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, - double fadestep, double endsize, int flags) + double fadestep, double sizestep, int flags) { particle_t *particle = NewParticle(); @@ -337,7 +337,7 @@ void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &a particle->ttl = lifetime; particle->bright = !!(flags & PS_FULLBRIGHT); particle->size = size; - particle->sizestep = (lifetime == 0) ? 0 : ((endsize - size) / lifetime); + particle->sizestep = sizestep; particle->notimefreeze = !!(flags & PS_NOTIMEFREEZE); } } diff --git a/src/p_effect.h b/src/p_effect.h index 2414372c3..614702a49 100644 --- a/src/p_effect.h +++ b/src/p_effect.h @@ -85,7 +85,7 @@ particle_t *JitterParticle (int ttl); particle_t *JitterParticle (int ttl, double drift); void P_ThinkParticles (void); -void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double endsize, int flags = 0); +void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags = 0); void P_InitEffects (void); void P_RunEffects (void); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index dbbb12f6a..9c8464417 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3199,7 +3199,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) PARAM_FLOAT_OPT (accelz) { accelz = 0; } PARAM_FLOAT_OPT (startalpha) { startalpha = 1.; } PARAM_FLOAT_OPT (fadestep) { fadestep = -1.; } - PARAM_FLOAT_OPT (endsize) { endsize = -1.; } + PARAM_FLOAT_OPT (sizestep) { sizestep = 0.; } startalpha = clamp(startalpha, 0., 1.); if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); @@ -3230,7 +3230,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) acc.X = accelx * c + accely * s; acc.Y = accelx * s - accely * c; } - P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, endsize, flags); + P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, sizestep, flags); } return 0; } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 5c46d0d4b..2ce48b036 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -215,7 +215,7 @@ ACTOR Actor native //: Thinker native void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false); native void A_SetMass(int mass); native void A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); - native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1, float endsize = -1); + native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1, float sizestep = 0); native state A_CheckSight(state label); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype);