From 89016020a8e518c82ded49f6e82c3ca877d3b86d Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 29 May 2016 10:43:21 +0300 Subject: [PATCH 01/19] Used ISO Latin 1 encoding for title text in startup window on OS X Windows version uses ANSI_CHARSET to handle the corresponding text This solves the problem like in https://github.com/alexey-lysiuk/gzdoom/issues/63: *** Assertion failure in -[NSTextFieldCell _objectValue:forString:errorDescription:], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1404.47/AppKit.subproj/NSCell.m:1684 Invalid parameter not satisfying: aString != nil --- src/posix/cocoa/st_console.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 5d82551bc..e38a5cc85 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -373,7 +373,8 @@ void FConsoleWindow::SetTitleText() } NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect]; - [titleText setStringValue:[NSString stringWithUTF8String:DoomStartupInfo.Name]]; + [titleText setStringValue:[NSString stringWithCString:DoomStartupInfo.Name + encoding:NSISOLatin1StringEncoding]]; [titleText setAlignment:NSCenterTextAlignment]; [titleText setTextColor:RGB(DoomStartupInfo.FgColor)]; [titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)]; From 334962da2c563e7bd02c57f56b6fb7a95595abe9 Mon Sep 17 00:00:00 2001 From: Roadcrosser Date: Fri, 18 Mar 2016 02:27:13 +0800 Subject: [PATCH 02/19] Corrected death message not being gender neutral. --- wadsrc/static/language.enu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 62761a417..d27374ed2 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -786,7 +786,7 @@ OB_MPPGAUNTLETS = "%o was bled dry by %k's gauntlets."; OB_MPPGOLDWAND = "%o was assaulted by %k's elven wand."; OB_MPPCROSSBOW = "%o was shafted by %k's ethereal crossbow."; OB_MPPBLASTER = "%o was ripped apart by %k's dragon claw."; -OB_MPPSKULLROD = "%k poured his hellstaff on %o."; +OB_MPPSKULLROD = "%k poured %p hellstaff on %o."; OB_MPPPHOENIXROD = "%o was burned down by %k's phoenix staff."; OB_MPPMACE = "%o was squished by %k's giant mace sphere."; From 6633e41ccaeb5381c88410297467a400fc1c07ae Mon Sep 17 00:00:00 2001 From: Benjamin Moir Date: Mon, 9 May 2016 16:41:35 +1000 Subject: [PATCH 03/19] added CheckProximity to ACS --- src/p_acs.cpp | 17 +++- src/p_local.h | 19 +++++ src/p_things.cpp | 117 +++++++++++++++++++++++++++ src/thingdef/thingdef_codeptr.cpp | 130 +----------------------------- 4 files changed, 152 insertions(+), 131 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 3248e738c..d66d0f8f8 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4464,7 +4464,8 @@ enum EACSFunctions ACSF_SetSectorTerrain, ACSF_SpawnParticle, ACSF_SetMusicVolume, - // 2 more left... + ACSF_CheckProximity, + // 1 more left... /* Zandronum's - these must be skipped when we reach 99! -100:ResetMap(0), @@ -6063,7 +6064,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_SetMusicVolume: I_SetMusicVolume(ACSToFloat(args[0])); break; - + + case ACSF_CheckProximity: + { + // [zombie] ACS version of A_CheckProximity + actor = SingleActorFromTID(args[0], activator); + PClass *classname = PClass::FindClass(FBehavior::StaticLookupString(args[1])); + double distance = ACSToDouble(args[2]); + int count = argCount >= 4 ? args[3] : 1; + int flags = argCount >= 5 ? args[4] : 0; + int ptr = argCount >= 6 ? args[5] : AAPTR_DEFAULT; + return P_Thing_CheckProximity(actor, classname, distance, count, flags, ptr); + } + default: break; } diff --git a/src/p_local.h b/src/p_local.h index 8e64c3414..f7862d45f 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -26,6 +26,7 @@ #include #include "doomtype.h" #include "vectors.h" +#include "dobject.h" const double NO_VALUE = FLT_MAX; @@ -160,6 +161,24 @@ bool P_Thing_CanRaise(AActor *thing); PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); 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); + +enum CPXF +{ + CPXF_ANCESTOR = 1 << 0, + CPXF_LESSOREQUAL = 1 << 1, + CPXF_NOZ = 1 << 2, + CPXF_COUNTDEAD = 1 << 3, + CPXF_DEADONLY = 1 << 4, + CPXF_EXACT = 1 << 5, + CPXF_SETTARGET = 1 << 6, + CPXF_SETMASTER = 1 << 7, + CPXF_SETTRACER = 1 << 8, + CPXF_FARTHEST = 1 << 9, + CPXF_CLOSEST = 1 << 10, + CPXF_SETONPTR = 1 << 11, + CPXF_CHECKSIGHT = 1 << 12, +}; enum WARPF { diff --git a/src/p_things.cpp b/src/p_things.cpp index ba1b29a1a..cad3022b0 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -50,6 +50,7 @@ #include "r_utility.h" #include "p_spec.h" #include "math/cmath.h" +#include "actorptrselect.h" // Set of spawnable things for the Thing_Spawn and Thing_Projectile specials. FClassMap SpawnableThings; @@ -666,6 +667,122 @@ void InitSpawnablesFromMapinfo() InitClassMap(StrifeTypes, ConversationIDsFromMapinfo); } +bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr) +{ + AActor *ref = COPY_AAPTR(self, ptr); + + // We need these to check out. + if (!ref || !classname || distance <= 0) + return nullptr; + + int counter = 0; + bool result = false; + 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)); + + TThinkerIterator it; + AActor *mo, *dist = nullptr; + + // [MC] Process of elimination, I think, will get through this as quickly and + // efficiently as possible. + while ((mo = it.Next())) + { + if (mo == ref) //Don't count self. + continue; + + // no unmorphed versions of currently morphed players. + if (mo->flags & MF_UNMORPHED) + continue; + + // Check inheritance for the classname. Taken partly from CheckClass DECORATE function. + if (flags & CPXF_ANCESTOR) + { + if (!(mo->IsKindOf(classname))) + continue; + } + // Otherwise, just check for the regular class name. + else if (classname != mo->GetClass()) + continue; + + // [MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use + // Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. + // Ripped from sphere checking in A_RadiusGive (along with a number of things). + 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))))) + { + if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) + continue; + + if (ptrWillChange) + { + current = ref->Distance2D(mo); + + if ((flags & CPXF_CLOSEST) && (current < closer)) + { + dist = mo; + closer = current; // This actor's closer. Set the new standard. + } + else if ((flags & CPXF_FARTHEST) && (current > farther)) + { + dist = mo; + farther = current; + } + else if (!dist) + dist = mo; // Just get the first one and call it quits if there's nothing selected. + } + if (mo->flags6 & MF6_KILLED) + { + if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) + continue; + counter++; + } + else + { + if (flags & CPXF_DEADONLY) + continue; + 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; + + // However, if we have one SET* flag and either the closest or farthest flags, keep the function going. + if (ptrWillChange && ptrDistPref) + continue; + else + break; + } + } + } + + if (ptrWillChange && dist != 0) + { + if (flags & CPXF_SETONPTR) + { + if (flags & CPXF_SETTARGET) ref->target = dist; + if (flags & CPXF_SETMASTER) ref->master = dist; + if (flags & CPXF_SETTRACER) ref->tracer = dist; + } + else + { + if (flags & CPXF_SETTARGET) self->target = dist; + if (flags & CPXF_SETMASTER) self->master = dist; + if (flags & CPXF_SETTRACER) self->tracer = dist; + } + } + + if (counter == count) + result = true; + else if (counter < count) + result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); + + return 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 86de07b5d..92514bff1 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -6605,22 +6605,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) // Checks to see if a certain actor class is close to the // actor/pointer within distance, in numbers. //========================================================================== -enum CPXFflags -{ - CPXF_ANCESTOR = 1 << 0, - CPXF_LESSOREQUAL = 1 << 1, - CPXF_NOZ = 1 << 2, - CPXF_COUNTDEAD = 1 << 3, - CPXF_DEADONLY = 1 << 4, - CPXF_EXACT = 1 << 5, - CPXF_SETTARGET = 1 << 6, - CPXF_SETMASTER = 1 << 7, - CPXF_SETTRACER = 1 << 8, - CPXF_FARTHEST = 1 << 9, - CPXF_CLOSEST = 1 << 10, - CPXF_SETONPTR = 1 << 11, - CPXF_CHECKSIGHT = 1 << 12, -}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { PARAM_SELF_PROLOGUE(AActor); @@ -6638,120 +6622,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) ACTION_RETURN_STATE(NULL); } } - AActor *ref = COPY_AAPTR(self, ptr); - // We need these to check out. - if (!ref || !classname || distance <= 0) - { - ACTION_RETURN_STATE(NULL); - } - int counter = 0; - bool result = false; - 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)); - - TThinkerIterator it; - AActor *mo, *dist = NULL; - - //[MC] Process of elimination, I think, will get through this as quickly and - //efficiently as possible. - while ((mo = it.Next())) - { - if (mo == ref) //Don't count self. - continue; - - // no unmorphed versions of currently morphed players. - if (mo->flags & MF_UNMORPHED) - continue; - - //Check inheritance for the classname. Taken partly from CheckClass DECORATE function. - if (flags & CPXF_ANCESTOR) - { - if (!(mo->IsKindOf(classname))) - continue; - } - //Otherwise, just check for the regular class name. - else if (classname != mo->GetClass()) - continue; - - //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use - //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. - //Ripped from sphere checking in A_RadiusGive (along with a number of things). - 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))))) - { - if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) - continue; - - if (ptrWillChange) - { - current = ref->Distance2D(mo); - - if ((flags & CPXF_CLOSEST) && (current < closer)) - { - dist = mo; - closer = current; //This actor's closer. Set the new standard. - } - else if ((flags & CPXF_FARTHEST) && (current > farther)) - { - dist = mo; - farther = current; - } - else if (!dist) - dist = mo; //Just get the first one and call it quits if there's nothing selected. - } - if (mo->flags6 & MF6_KILLED) - { - if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) - continue; - counter++; - } - else - { - if (flags & CPXF_DEADONLY) - continue; - 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; - - //However, if we have one SET* flag and either the closest or farthest flags, keep the function going. - if (ptrWillChange && ptrDistPref) - continue; - else - break; - } - } - } - - if (ptrWillChange && dist != NULL) - { - if (flags & CPXF_SETONPTR) - { - if (flags & CPXF_SETTARGET) ref->target = dist; - if (flags & CPXF_SETMASTER) ref->master = dist; - if (flags & CPXF_SETTRACER) ref->tracer = dist; - } - else - { - if (flags & CPXF_SETTARGET) self->target = dist; - if (flags & CPXF_SETMASTER) self->master = dist; - if (flags & CPXF_SETTRACER) self->tracer = dist; - } - } - - if (counter == count) - result = true; - else if (counter < count) - result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); - - if (result && jump) + if (P_Thing_CheckProximity(self, classname, distance, count, flags, ptr) && jump) { ACTION_RETURN_STATE(jump); } From 33ddbe8ab3889caf41e9b73b7b4a6160d0a24f28 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 7 May 2016 13:10:08 -0500 Subject: [PATCH 04/19] Added SKYEXPLODE support for P_LineAttack on horizons. --- src/p_map.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index ce3fd9af2..69d18ce18 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4105,6 +4105,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, AActor *puff = NULL; int pflag = 0; int puffFlags = (flags & LAF_ISMELEEATTACK) ? PF_MELEERANGE : 0; + bool spawnSky = false; if (flags & LAF_NORANDOMPUFFZ) puffFlags |= PF_NORANDOMZ; @@ -4144,7 +4145,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) || (puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST)); - + + spawnSky = (puffDefaults && (puffDefaults->flags3 & MF3_SKYEXPLODE)); TData.MThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES)); TData.PuffSpecies = NAME_None; @@ -4210,7 +4212,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (trace.HitType != TRACE_HitActor) { // position a bit closer for puffs - if (trace.HitType != TRACE_HitWall || trace.Line->special != Line_Horizon) + if (trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky)) { DVector2 pos = P_GetOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4); puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget, From 2719905ade9c7cd4e774e0f02d75cf554ba2d319 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 17 May 2016 11:22:29 -0500 Subject: [PATCH 05/19] - Added source and inflictor parameters to all A_Damage/Kill functions. - Source is the actor to blame for the cause of damage (monster infighting for example). For missiles, modders should consider setting to AAPTR_TARGET. - Inflictor is the actor doing the damage itself. Note that by changing this, it will take into account the flags on the pointed actor. --- src/thingdef/thingdef_codeptr.cpp | 85 +++++++++++++++++++++++++------ wadsrc/static/actors/actor.txt | 22 ++++---- 2 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 92514bff1..9f5eb02bd 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5848,7 +5848,7 @@ enum DMSS DMSS_EITHER = 256, //Allow either type or species to be affected. }; -static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags, PClassActor *filter, FName species) +static void DoDamage(AActor *dmgtarget, AActor *inflictor, AActor *source, int amount, FName DamageType, int flags, PClassActor *filter, FName species) { bool filterpass = DoCheckClass(dmgtarget, filter, !!(flags & DMSS_EXFILTER)), speciespass = DoCheckSpecies(dmgtarget, species, !!(flags & DMSS_EXSPECIES)); @@ -5870,7 +5870,7 @@ static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageTy if (amount > 0) { //Should wind up passing them through just fine. - P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); + P_DamageMobj(dmgtarget, inflictor, source, amount, DamageType, dmgFlags); } else if (amount < 0) { @@ -5893,8 +5893,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } - DoDamage(self, self, amount, damagetype, flags, filter, species); + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); + + DoDamage(self, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5911,9 +5916,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->target != NULL) - DoDamage(self->target, self, amount, damagetype, flags, filter, species); + DoDamage(self->target, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5930,9 +5940,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->tracer != NULL) - DoDamage(self->tracer, self, amount, damagetype, flags, filter, species); + DoDamage(self->tracer, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5949,9 +5964,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) - DoDamage(self->master, self, amount, damagetype, flags, filter, species); + DoDamage(self->master, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5968,6 +5988,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -5975,7 +6000,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) while ( (mo = it.Next()) ) { if (mo->master == self) - DoDamage(mo, self, amount, damagetype, flags, filter, species); + DoDamage(mo, inflictor, source, amount, damagetype, flags, filter, species); } return 0; } @@ -5993,6 +6018,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6002,7 +6032,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) while ((mo = it.Next())) { if (mo->master == self->master && mo != self) - DoDamage(mo, self, amount, damagetype, flags, filter, species); + DoDamage(mo, inflictor, source, amount, damagetype, flags, filter, species); } } return 0; @@ -6025,7 +6055,7 @@ enum KILS KILS_EITHER = 1 << 6, }; -static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags, PClassActor *filter, FName species) +static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName damagetype, int flags, PClassActor *filter, FName species) { bool filterpass = DoCheckClass(killtarget, filter, !!(flags & KILS_EXFILTER)), speciespass = DoCheckSpecies(killtarget, species, !!(flags & KILS_EXSPECIES)); @@ -6052,7 +6082,7 @@ static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags } if (!(flags & KILS_NOMONSTERS)) { - P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags); + P_DamageMobj(killtarget, inflictor, source, killtarget->health, damagetype, dmgFlags); } } } @@ -6070,9 +6100,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->target != NULL) - DoKill(self->target, self, damagetype, flags, filter, species); + DoKill(self->target, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6088,9 +6123,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->tracer != NULL) - DoKill(self->tracer, self, damagetype, flags, filter, species); + DoKill(self->tracer, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6106,9 +6146,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) - DoKill(self->master, self, damagetype, flags, filter, species); + DoKill(self->master, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6124,6 +6169,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6132,7 +6182,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { if (mo->master == self) { - DoKill(mo, self, damagetype, flags, filter, species); + DoKill(mo, inflictor, source, damagetype, flags, filter, species); } } return 0; @@ -6150,6 +6200,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6160,7 +6215,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { if (mo->master == self->master && mo != self) { - DoKill(mo, self, damagetype, flags, filter, species); + DoKill(mo, inflictor, source, damagetype, flags, filter, species); } } } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index fbb16dc80..98abcbe88 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -289,17 +289,17 @@ ACTOR Actor native //: Thinker native void A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT); native void A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT); native void A_SetPainThreshold(int threshold, int ptr = AAPTR_DEFAULT); - native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); + native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); action native A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); action native A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); action native A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); From bb91723174e65bd5bb40f5738638be9259ec4234 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 28 May 2016 11:26:04 -0500 Subject: [PATCH 06/19] - Added GetCrouchFactor(ptr). Gets the crouch factor of a player. Can be set to target/master/tracer, as long as it's a player. Defaults to the first player. --- src/thingdef/thingdef_codeptr.cpp | 30 ++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 2 files changed, 31 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 9f5eb02bd..87516a858 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -483,6 +483,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) return 0; } +//========================================================================== +// +// GetCrouchFactor +// +// NON-ACTION function to retrieve a player's crouching factor. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(ptr) { ptr = AAPTR_PLAYER1; } + AActor *mobj = COPY_AAPTR(self, ptr); + + if (!mobj || !mobj->player) + { + ret->SetFloat(0); + } + else + { + ret->SetFloat(mobj->player->crouchfactor); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 98abcbe88..cc0569fff 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -46,6 +46,7 @@ ACTOR Actor native //: Thinker native float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); native int GetGibHealth(); + native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. From 44f09edf4ca753994cfb6b224592e3a9320d7239 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 29 May 2016 12:48:27 +0200 Subject: [PATCH 07/19] - fixed: monsters cannot crouch, so their crouch factor has to be 1, as 0 would yield incorrect results if the value is used in subsequent calculations (e.g. adjusting a trajectory to a target which can be or may not be a player.) --- 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 87516a858..f171edaeb 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -502,7 +502,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) if (!mobj || !mobj->player) { - ret->SetFloat(0); + ret->SetFloat(1); } else { From 243030046a2b3e0f52f27fa591a7d300f457bb79 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 18 May 2016 09:37:00 +0200 Subject: [PATCH 08/19] - Fixed issues with invalid GetMaxInventory calls. --- src/p_acs.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d66d0f8f8..2de959be6 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1328,6 +1328,18 @@ static int CheckInventory (AActor *activator, const char *type, bool max) } PClassActor *info = PClass::FindActor (type); + + if (info == NULL) + { + Printf ("ACS: I don't know what '%s' is.\n", type); + return 0; + } + else if (!info->IsDescendantOf(RUNTIME_CLASS(AInventory))) + { + Printf ("ACS: '%s' is not an inventory item.\n", type); + return 0; + } + AInventory *item = activator->FindInventory (info); if (max) From 5348a15b75333f37f7f7c83f3dca31eece092824 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 11 Feb 2016 14:07:01 +0200 Subject: [PATCH 09/19] Added option to control dynamic loading of OpenAL Dynamic loading is enabled by default, set DYN_OPENAL to OFF to link with static or dynamic library # Conflicts: # src/sound/oalsound.cpp # src/sound/oalsound.h --- src/CMakeLists.txt | 21 ++++++++++++++++----- src/sound/oalload.h | 2 +- src/sound/oalsound.cpp | 32 +++++++++++++++++--------------- src/sound/oalsound.h | 2 ++ 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 84d6f06b9..93a165fb1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif() option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON ) +option( DYN_OPENAL "Dynamically load OpenAL" ON ) if( APPLE ) option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON ) @@ -226,13 +227,23 @@ endif() if( NOT NO_OPENAL ) - find_package( OpenAL ) + find_package( OpenAL ) mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR) - if( OPENAL_INCLUDE_DIR ) - include_directories( ${OPENAL_INCLUDE_DIR} ) - else() + if( OPENAL_INCLUDE_DIR ) + include_directories( ${OPENAL_INCLUDE_DIR} ) + if( DYN_OPENAL ) + add_definitions( -DDYN_OPENAL ) + else() + mark_as_advanced(CLEAR OPENAL_LIBRARY) + if( OPENAL_LIBRARY ) + set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} ) + else() + set( NO_OPENAL ON ) + endif() + endif() + else() set( NO_OPENAL ON ) - endif() + endif() endif() if( NOT NO_FMOD ) diff --git a/src/sound/oalload.h b/src/sound/oalload.h index 3cee30d58..ca02d25d9 100644 --- a/src/sound/oalload.h +++ b/src/sound/oalload.h @@ -1,7 +1,7 @@ #ifndef OALDEF_H #define OALDEF_H -#ifndef NO_OPENAL +#if !defined NO_OPENAL && defined DYN_OPENAL #ifndef _WIN32 typedef void* FARPROC; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 8ac41a04b..6dd204c86 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -83,6 +83,8 @@ bool IsOpenALPresent() { #ifdef NO_OPENAL return false; +#elif !defined DYN_OPENAL + return true; #else static bool cached_result = false; static bool done = false; @@ -425,10 +427,10 @@ public: virtual bool IsEnded() { return !Playing.load(); - } + } virtual FString GetStats() - { + { FString stats; size_t pos, len; ALfloat volume; @@ -1538,24 +1540,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } else { FVector3 dir = pos; if(AL.EXT_SOURCE_RADIUS) alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f); - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { dir -= listener->position; - float mindist = rolloff->MinDistance/distscale; - FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); - float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; + float mindist = rolloff->MinDistance/distscale; + FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); + float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; - dir += listener->position; + dir += listener->position; } if(dist_sqr < (0.0004f*0.0004f)) { @@ -1566,8 +1568,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); @@ -1799,7 +1801,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh { float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale); dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); - } + } } else if(!AL.EXT_SOURCE_RADIUS && areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) @@ -1822,7 +1824,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); getALError(); diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 09fe64d92..d69e2e367 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -12,7 +12,9 @@ #ifndef NO_OPENAL +#ifdef DYN_OPENAL #define AL_NO_PROTOTYPES +#endif // DYN_OPENAL #include "al.h" #include "alc.h" From 14e4a64c82d664925507adddd1c45c1b1d122d77 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jun 2016 10:10:18 +0200 Subject: [PATCH 10/19] - fixed: Destroying a SkyViewpoint disabled all sector portals. --- src/g_shared/a_skies.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 6e85bd886..1da7cd712 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -61,10 +61,13 @@ void ASkyViewpoint::Destroy () // remove all sector references to ourselves. for (auto &s : sectorPortals) { - if (s.mSkybox == this) s.mSkybox = 0; - // This is necessary to entirely disable EE-style skyboxes - // if their viewpoint gets deleted. - s.mFlags |= PORTSF_SKYFLATONLY; + if (s.mSkybox == this) + { + s.mSkybox = 0; + // This is necessary to entirely disable EE-style skyboxes + // if their viewpoint gets deleted. + s.mFlags |= PORTSF_SKYFLATONLY; + } } Super::Destroy(); From 978e522fb4b009fff4e6c2dd456a6b38b06c283f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jun 2016 11:14:25 +0200 Subject: [PATCH 11/19] - fixed: portal-related sound calculations offset the sound in the wrong direction. --- src/s_sound.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 7915fdccc..321cbce1b 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -684,9 +684,9 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, { sector_t *sec = P_PointInSector(pt[0], pt[2]); DVector2 disp = Displacements.getOffset(pgroup, sec->PortalGroup); - pos->X = pt[0] + (float)disp.X; + pos->X = pt[0] - (float)disp.X; pos->Y = !(chanflags & CHAN_LISTENERZ) ? pt[1] : (float)listenpos.Z; - pos->Z = pt[2] + (float)disp.Y; + pos->Z = pt[2] - (float)disp.Y; } else { @@ -701,7 +701,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (actor != NULL) { DVector2 disp = Displacements.getOffset(pgroup, actor->Sector->PortalGroup); - DVector3 posi = actor->Pos() + disp; + DVector3 posi = actor->Pos() - disp; *pos = { (float)posi.X, (float)posi.Z, (float)posi.Y }; } break; @@ -714,15 +714,15 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (chanflags & CHAN_AREA) { // listener must be reversely offset to calculate the proper sound origin. - CalcSectorSoundOrg(listenpos-disp, sector, channum, *pos); + CalcSectorSoundOrg(listenpos + disp, sector, channum, *pos); pos->X += (float)disp.X; pos->Z += (float)disp.Y; } else { - pos->X = (float)(sector->centerspot.X + disp.X); - pos->Z = (float)(sector->centerspot.Y + disp.Y); + pos->X = (float)(sector->centerspot.X - disp.X); + pos->Z = (float)(sector->centerspot.Y - disp.Y); chanflags |= CHAN_LISTENERZ; } } @@ -733,7 +733,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (poly != NULL) { DVector2 disp = Displacements.getOffset(pgroup, poly->CenterSubsector->sector->PortalGroup); - CalcPolyobjSoundOrg(listenpos-disp, poly, *pos); + CalcPolyobjSoundOrg(listenpos + disp, poly, *pos); pos->X += (float)disp.X; pos->Z += (float)disp.Y; } From 26a15d0ccc907516fdb65a68dae7590fd77cb243 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jun 2016 11:43:56 +0200 Subject: [PATCH 12/19] - delete thinkers before starting to restore the savegame data to avoid interference of the old thinkers' Destroy() method with the newly loaded data. Note that even with this change it is still not possible to unarchive any thinker pointers before the thinker list has been loaded as it would create broken lists. --- src/dthinker.cpp | 5 ----- src/g_level.cpp | 1 + src/p_saveg.cpp | 8 ++++++++ src/p_saveg.h | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 230d0dd41..176df6c18 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -152,11 +152,6 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad) } else { - if (hubLoad) - DestroyMostThinkers(); - else - DestroyAllThinkers(); - // Prevent the constructor from inserting thinkers into a list. bSerialOverride = true; diff --git a/src/g_level.cpp b/src/g_level.cpp index 141932c22..66d4ad422 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1479,6 +1479,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) int i = level.totaltime; Renderer->StartSerialize(arc); + if (arc.IsLoading()) P_DestroyThinkers(hubLoad); arc << level.flags << level.flags2 diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index b6e3b28ca..e64a97fca 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -519,6 +519,14 @@ void P_SerializeThinkers (FArchive &arc, bool hubLoad) DThinker::SerializeAll (arc, hubLoad); } +void P_DestroyThinkers(bool hubLoad) +{ + if (hubLoad) + DThinker::DestroyMostThinkers(); + else + DThinker::DestroyAllThinkers(); +} + //========================================================================== // // ArchiveSounds diff --git a/src/p_saveg.h b/src/p_saveg.h index c6c056004..eb3e4de2b 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -43,6 +43,7 @@ struct PNGHandle; void P_SerializePlayers (FArchive &arc, bool fakeload); void P_SerializeWorldActors(FArchive &arc); void P_SerializeWorld (FArchive &arc); +void P_DestroyThinkers(bool hubLoad); void P_SerializeThinkers (FArchive &arc, bool); void P_SerializePolyobjs (FArchive &arc); void P_SerializeSubsectors(FArchive &arc); From 2afadb010807326d20642d035e2f1f89ea9db8b8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jun 2016 23:41:34 +0200 Subject: [PATCH 13/19] - 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 14/19] - 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 15/19] - 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 16/19] - 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 17/19] - 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 18/19] - 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 19/19] - 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);