From 0c660ff29ca9f2915f9aaea31edaed374c7fd7e5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 10:37:47 +0100 Subject: [PATCH 01/48] - added an option to add elements to an existing options menu. Note that for list menus this does not exist because they require complete setup to work as intended. --- src/menu/menudef.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index dc4fff1a7..239366dcf 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -871,6 +871,25 @@ static void ParseOptionMenu(FScanner &sc) } +//============================================================================= +// +// +// +//============================================================================= + +static void ParseAddOptionMenu(FScanner &sc) +{ + sc.MustGetString(); + + DMenuDescriptor **pOld = MenuDescriptors.CheckKey(sc.String); + if (pOld == nullptr || *pOld == nullptr || !(*pOld)->IsKindOf(RUNTIME_CLASS(DOptionMenuDescriptor))) + { + sc.ScriptError("%s is not an option menu that can be extended", sc.String); + } + ParseOptionMenuBody(sc, (DOptionMenuDescriptor*)(*pOld)); +} + + //============================================================================= // // @@ -935,6 +954,10 @@ void M_ParseMenuDefs() { ParseOptionMenu(sc); } + else if (sc.Compare("ADDOPTIONMENU")) + { + ParseAddOptionMenu(sc); + } else if (sc.Compare("DEFAULTOPTIONMENU")) { ParseOptionMenuBody(sc, DefaultOptionMenuSettings); From 073e63ed045db1e1b3de99a1cd4368606eb8c4a4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 10:50:21 +0100 Subject: [PATCH 02/48] - Added a check for all z-movement for floor huggers so that it doesn't skip all the height checks if +NODROPOFF is also given. --- src/p_map.cpp | 4 ++-- src/p_mobj.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 9b3a257ec..6413b392b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2281,7 +2281,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, } #endif } - if (!(thing->flags & MF_TELEPORT) && !(thing->flags3 & MF3_FLOORHUGGER)) + if (!(thing->flags & MF_TELEPORT) && (!(thing->flags3 & MF3_FLOORHUGGER) || thing->flags5 & MF5_NODROPOFF)) { if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > thing->Z()) { // [RH] Don't let normal missiles climb steps @@ -2772,7 +2772,7 @@ bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags) if (thing->Top() > tm.ceilingz) return false; } - if (!(thing->flags & MF_TELEPORT) && !(thing->flags3 & MF3_FLOORHUGGER)) + if (!(thing->flags & MF_TELEPORT) && (!(thing->flags3 & MF3_FLOORHUGGER) || thing->flags5 & MF5_NODROPOFF)) { if (tm.floorz - newz > thing->MaxStepHeight) { // too big a step up diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d6da38961..dfb0c7312 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2958,7 +2958,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) mo->Vel.Z = 0; return; } - else if (mo->flags3 & MF3_FLOORHUGGER) + else if ((mo->flags3 & MF3_FLOORHUGGER) && !(mo->flags5 & MF5_NODROPOFF)) { // Floor huggers can go up steps return; } From e84a2899f92e09ef87aba574b00acaedaa52779c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 10:52:29 +0100 Subject: [PATCH 03/48] - this needs one more check. --- src/p_map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 6413b392b..70b18df7f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2283,7 +2283,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, } if (!(thing->flags & MF_TELEPORT) && (!(thing->flags3 & MF3_FLOORHUGGER) || thing->flags5 & MF5_NODROPOFF)) { - if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > thing->Z()) + if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > thing->Z() && !(thing->flags3 & MF3_FLOORHUGGER)) { // [RH] Don't let normal missiles climb steps goto pushline; } @@ -2778,7 +2778,7 @@ bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags) { // too big a step up return false; } - else if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > newz) + else if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > newz && !(thing->flags3 & MF3_FLOORHUGGER)) { // [RH] Don't let normal missiles climb steps return false; } From f9f9f2d5fc7b7a0231519db8c78826bc61743053 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 11:22:51 +0100 Subject: [PATCH 04/48] - added selfdamagefactor actor property. --- src/info.cpp | 2 ++ src/info.h | 1 + src/p_interaction.cpp | 5 +++++ src/p_mobj.cpp | 1 + src/scripting/thingdef_properties.cpp | 10 ++++++++++ 5 files changed, 19 insertions(+) diff --git a/src/info.cpp b/src/info.cpp index 81912150b..84d8e26be 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -257,6 +257,7 @@ PClassActor::PClassActor() WoundHealth = 6; FastSpeed = -1.; RDFactor = 1.; + SelfDamageFactor = 1.; CameraHeight = INT_MIN; DropItems = NULL; @@ -317,6 +318,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->WoundHealth = WoundHealth; newa->FastSpeed = FastSpeed; newa->RDFactor = RDFactor; + newa->SelfDamageFactor = SelfDamageFactor; newa->CameraHeight = CameraHeight; newa->HowlSound = HowlSound; newa->BloodType = BloodType; diff --git a/src/info.h b/src/info.h index 50db1e4b6..a9f79182f 100644 --- a/src/info.h +++ b/src/info.h @@ -299,6 +299,7 @@ public: int WoundHealth; // Health needed to enter wound state double FastSpeed; // speed in fast mode double RDFactor; // Radius damage factor + double SelfDamageFactor; double CameraHeight; // Height of camera when used as such FSoundID HowlSound; // Sound being played when electrocuted or poisoned FName BloodType; // Blood replacement type diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 38d9cd375..4c23c8123 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1020,6 +1020,11 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da } return 0; } + if (target == source && damage < TELEFRAG_DAMAGE) + { + damage = int(damage * target->GetClass()->SelfDamageFactor); + } + // [MC] Changed it to check rawdamage here for consistency, even though that doesn't actually do anything // different here. At any rate, invulnerable is being checked before type factoring, which is then being // checked by player cheats/invul/buddha followed by monster buddha. This is inconsistent. Don't let the diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index dfb0c7312..f85f2c9eb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -321,6 +321,7 @@ DEFINE_FIELD(PClassActor, GibHealth) DEFINE_FIELD(PClassActor, WoundHealth) DEFINE_FIELD(PClassActor, FastSpeed) DEFINE_FIELD(PClassActor, RDFactor) +DEFINE_FIELD(PClassActor, SelfDamageFactor) DEFINE_FIELD(PClassActor, CameraHeight) DEFINE_FIELD(PClassActor, HowlSound) DEFINE_FIELD(PClassActor, BloodType) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 50b81310c..6537e2482 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1430,6 +1430,16 @@ DEFINE_PROPERTY(radiusdamagefactor, F, Actor) static_cast(info)->RDFactor = i; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(selfdamagefactor, F, Actor) +{ + PROP_DOUBLE_PARM(i, 0); + assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); + static_cast(info)->SelfDamageFactor = i; +} + //========================================================================== // //========================================================================== From 78538ed9efa1dbd5efa7162f7674aa661649d6ba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 14:53:39 +0100 Subject: [PATCH 05/48] - missed an else. --- src/info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.cpp b/src/info.cpp index 84d8e26be..580abbf1a 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -868,7 +868,7 @@ void FMapInfoParser::ParseDamageDefinition() dtd.DefaultFactor = sc.Float; if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true; } - if (sc.Compare("OBITUARY")) + else if (sc.Compare("OBITUARY")) { sc.MustGetStringName("="); sc.MustGetString(); From cc598dfddeb5ba507249041e95ca9d10498b8929 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 15:16:03 +0100 Subject: [PATCH 06/48] - fixed: To get the final error handling from the serializer, Close must be called before the destructor gets invoked. - added line feeds to all error messages in the serializer. --- src/g_level.cpp | 1 + src/serializer.cpp | 62 ++++++++++++++++++++++++---------------------- src/serializer.h | 1 + 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 01911f742..b0de51b43 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1624,6 +1624,7 @@ void G_UnSnapshotLevel (bool hubLoad) } } } + arc.Close(); } // No reason to keep the snapshot around once the level's been entered. level.info->Snapshot.Clean(); diff --git a/src/serializer.cpp b/src/serializer.cpp index a577056af..fd9af832c 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -486,6 +486,8 @@ bool FSerializer::OpenReader(FCompressedBuffer *input) void FSerializer::Close() { + if (w == nullptr && r == nullptr) return; // double close? This should skip the I_Error at the bottom. + if (w != nullptr) { delete w; @@ -590,7 +592,7 @@ bool FSerializer::BeginObject(const char *name) } else { - Printf(TEXTCOLOR_RED "Object expected for '%s'", name); + Printf(TEXTCOLOR_RED "Object expected for '%s'\n", name); mErrors++; return false; } @@ -656,7 +658,7 @@ bool FSerializer::BeginArray(const char *name) } else { - Printf(TEXTCOLOR_RED "Array expected for '%s'", name); + Printf(TEXTCOLOR_RED "Array expected for '%s'\n", name); mErrors++; return false; } @@ -748,7 +750,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe else { assert(false && "Integer expected"); - Printf(TEXTCOLOR_RED "Integer expected for '%s[%d]'", key, i); + Printf(TEXTCOLOR_RED "Integer expected for '%s[%d]'\n", key, i); mErrors++; } } @@ -756,7 +758,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe else { assert(false && "array expected"); - Printf(TEXTCOLOR_RED "array expected for '%s'", key); + Printf(TEXTCOLOR_RED "array expected for '%s'\n", key); mErrors++; } } @@ -800,7 +802,7 @@ FSerializer &FSerializer::ScriptNum(const char *key, int &num) else { assert(false && "Integer expected"); - Printf(TEXTCOLOR_RED "Integer expected for '%s'", key); + Printf(TEXTCOLOR_RED "Integer expected for '%s'\n", key); mErrors++; } } @@ -1005,7 +1007,7 @@ void FSerializer::ReadObjects(bool hubtravel) PClass *cls = PClass::FindClass(clsname); if (cls == nullptr) { - Printf("Unknown object class '%s' in savegame", clsname.GetChars()); + Printf(TEXTCOLOR_RED "Unknown object class '%s' in savegame\n", clsname.GetChars()); founderrors = true; r->mDObjects[i] = RUNTIME_CLASS(AActor)->CreateNew(); // make sure we got at least a valid pointer for the duration of the loading process. r->mDObjects[i]->Destroy(); // but we do not want to keep this around, so destroy it right away. @@ -1041,7 +1043,7 @@ void FSerializer::ReadObjects(bool hubtravel) catch (CRecoverableError &err) { // In case something in here throws an error, let's continue and deal with it later. - Printf(TEXTCOLOR_RED "'%s'\n while restoring %s", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); + Printf(TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); mErrors++; } } @@ -1055,7 +1057,7 @@ void FSerializer::ReadObjects(bool hubtravel) assert(!founderrors); if (founderrors) { - Printf(TEXTCOLOR_RED "Failed to restore all objects in savegame"); + Printf(TEXTCOLOR_RED "Failed to restore all objects in savegame\n"); mErrors++; } } @@ -1064,7 +1066,7 @@ void FSerializer::ReadObjects(bool hubtravel) // nuke all objects we created here. for (auto obj : r->mDObjects) { - obj->Destroy(); + if (!(obj->ObjectFlags & OF_EuthanizeMe)) obj->Destroy(); } r->mDObjects.Clear(); @@ -1182,7 +1184,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, bool &value, bool *def } else { - Printf(TEXTCOLOR_RED "boolean type expected for '%s'", key); + Printf(TEXTCOLOR_RED "boolean type expected for '%s'\n", key); arc.mErrors++; } } @@ -1218,7 +1220,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, int64_t &value, int64_ } else { - Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); + Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key); arc.mErrors++; } } @@ -1254,7 +1256,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, uint64_t &value, uint6 } else { - Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); + Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key); arc.mErrors++; } } @@ -1291,7 +1293,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, int32_t &value, int32_ } else { - Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); + Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key); arc.mErrors++; } } @@ -1327,7 +1329,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, uint32_t &value, uint3 } else { - Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); + Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key); arc.mErrors++; } } @@ -1405,7 +1407,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, double &value, double } else { - Printf(TEXTCOLOR_RED "float type expected for '%s'", key); + Printf(TEXTCOLOR_RED "float type expected for '%s'\n", key); arc.mErrors++; } } @@ -1548,7 +1550,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe } else { - Printf(TEXTCOLOR_RED "object does not represent a texture for '%s'", key); + Printf(TEXTCOLOR_RED "object does not represent a texture for '%s'\n", key); value.SetNull(); arc.mErrors++; } @@ -1564,7 +1566,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe else { assert(false && "not a texture"); - Printf(TEXTCOLOR_RED "object does not represent a texture for '%s'", key); + Printf(TEXTCOLOR_RED "object does not represent a texture for '%s'\n", key); value.SetNull(); arc.mErrors++; } @@ -1649,7 +1651,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje else { assert(false && "invalid object reference"); - Printf(TEXTCOLOR_RED "Invalid object reference for '%s'", key); + Printf(TEXTCOLOR_RED "Invalid object reference for '%s'\n", key); value = nullptr; arc.mErrors++; if (retcode) *retcode = false; @@ -1698,7 +1700,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d } else { - Printf(TEXTCOLOR_RED "String expected for '%s'", key); + Printf(TEXTCOLOR_RED "String expected for '%s'\n", key); arc.mErrors++; value = NAME_None; } @@ -1746,7 +1748,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDynamicCol } } assert(false && "not a colormap"); - Printf(TEXTCOLOR_RED "object does not represent a colormap for '%s'", key); + Printf(TEXTCOLOR_RED "object does not represent a colormap for '%s'\n", key); cm = &NormalLight; } } @@ -1787,7 +1789,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI } else { - Printf(TEXTCOLOR_RED "string type expected for '%s'", key); + Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key); sid = 0; arc.mErrors++; } @@ -1836,7 +1838,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor } else { - Printf(TEXTCOLOR_RED "string type expected for '%s'", key); + Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key); clst = nullptr; arc.mErrors++; } @@ -1884,7 +1886,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl } else { - Printf(TEXTCOLOR_RED "string type expected for '%s'", key); + Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key); clst = nullptr; arc.mErrors++; } @@ -1960,20 +1962,20 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState { // this can actually happen by changing the DECORATE so treat it as a warning, not an error. state = nullptr; - Printf(TEXTCOLOR_ORANGE "Invalid state '%s+%d' for '%s'", cls.GetString(), ndx.GetInt(), key); + Printf(TEXTCOLOR_ORANGE "Invalid state '%s+%d' for '%s'\n", cls.GetString(), ndx.GetInt(), key); } } else { assert(false && "not a state"); - Printf(TEXTCOLOR_RED "data does not represent a state for '%s'", key); + Printf(TEXTCOLOR_RED "data does not represent a state for '%s'\n", key); arc.mErrors++; } } else if (!retcode) { assert(false && "not an array"); - Printf(TEXTCOLOR_RED "array type expected for '%s'", key); + Printf(TEXTCOLOR_RED "array type expected for '%s'\n", key); arc.mErrors++; } } @@ -2028,7 +2030,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FStrifeDial } else { - Printf(TEXTCOLOR_RED "integer expected for '%s'", key); + Printf(TEXTCOLOR_RED "integer expected for '%s'\n", key); arc.mErrors++; node = nullptr; } @@ -2077,7 +2079,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FString *&p } else { - Printf(TEXTCOLOR_RED "string expected for '%s'", key); + Printf(TEXTCOLOR_RED "string expected for '%s'\n", key); pstr = nullptr; arc.mErrors++; } @@ -2119,7 +2121,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &pstr, FString } else { - Printf(TEXTCOLOR_RED "string expected for '%s'", key); + Printf(TEXTCOLOR_RED "string expected for '%s'\n", key); pstr = ""; arc.mErrors++; } @@ -2168,7 +2170,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr } else { - Printf(TEXTCOLOR_RED "string expected for '%s'", key); + Printf(TEXTCOLOR_RED "string expected for '%s'\n", key); pstr = nullptr; arc.mErrors++; } diff --git a/src/serializer.h b/src/serializer.h index 4f0d90cec..7527eeb3c 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -64,6 +64,7 @@ public: ~FSerializer() { + mErrors = 0; // The destructor may not throw an exception so silence the error checker. Close(); } bool OpenWriter(bool pretty = true); From e9364fccb86f1d06df48a04050a65d5ab6fb0b4b Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 27 Feb 2017 12:02:46 -0500 Subject: [PATCH 07/48] - Fixed: voxels were not properly remapped after "restart" ccmd --- src/d_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index b430c7f04..77e0edda0 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2692,6 +2692,7 @@ void D_DoomMain (void) // These calls from inside V_Init2 are still necessary C_NewModeAdjust(); M_InitVideoModesMenu(); + Renderer->RemapVoxels(); D_StartTitle (); // start up intro loop setmodeneeded = false; // This may be set to true here, but isn't needed for a restart } From 4bcbd5c0117b52d0e4c767d21c3299df3621536a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 18:35:29 +0100 Subject: [PATCH 08/48] - clear WF_WEAPONBOBBING in P_FireWeapon, because otherwise the first frame of the fire animation will be drawn in the current bobbing position and not centered. --- src/p_pspr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 8b8e93f6a..47675699a 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -536,6 +536,7 @@ void P_FireWeapon (player_t *player, FState *state) return; } + player->WeaponState &= ~WF_WEAPONBOBBING; player->mo->PlayAttacking (); weapon->bAltFire = false; if (state == nullptr) @@ -572,6 +573,7 @@ void P_FireWeaponAlt (player_t *player, FState *state) return; } + player->WeaponState &= ~WF_WEAPONBOBBING; player->mo->PlayAttacking (); weapon->bAltFire = true; From f82ab889b21980e0d2c1588aca92bb047f409125 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 18:44:58 +0100 Subject: [PATCH 09/48] - added ACS strarg function which can convert a string into a string argument for ACS specials. --- src/p_acs.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index ad66627f5..4a2ca3fd9 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4367,6 +4367,7 @@ enum EACSFunctions ACSF_SetTranslation, ACSF_GetActorFloorTexture, ACSF_GetActorFloorTerrain, + ACSF_StrArg, // OpenGL stuff @@ -6087,7 +6088,8 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } - + case ACSF_StrArg: + return -FName(FBehavior::StaticLookupString(args[0])); default: break; From 321c846d0123a35c6a3374eb177b47f7e8a15e8c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 19:46:27 +0100 Subject: [PATCH 10/48] - added StealthAlpha actor property for defining a minimum visibility value of a stealth monster. --- src/info.cpp | 2 ++ src/info.h | 1 + src/p_mobj.cpp | 5 +++-- src/scripting/thingdef_properties.cpp | 10 ++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 580abbf1a..7cac3569d 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -258,6 +258,7 @@ PClassActor::PClassActor() FastSpeed = -1.; RDFactor = 1.; SelfDamageFactor = 1.; + StealthAlpha = 0.; CameraHeight = INT_MIN; DropItems = NULL; @@ -319,6 +320,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->FastSpeed = FastSpeed; newa->RDFactor = RDFactor; newa->SelfDamageFactor = SelfDamageFactor; + newa->StealthAlpha = StealthAlpha; newa->CameraHeight = CameraHeight; newa->HowlSound = HowlSound; newa->BloodType = BloodType; diff --git a/src/info.h b/src/info.h index a9f79182f..6d6329f88 100644 --- a/src/info.h +++ b/src/info.h @@ -301,6 +301,7 @@ public: double RDFactor; // Radius damage factor double SelfDamageFactor; double CameraHeight; // Height of camera when used as such + double StealthAlpha; // Minmum alpha for MF_STEALTH. FSoundID HowlSound; // Sound being played when electrocuted or poisoned FName BloodType; // Blood replacement type FName BloodType2; // Bloopsplatter replacement type diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f85f2c9eb..d218d24de 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -322,6 +322,7 @@ DEFINE_FIELD(PClassActor, WoundHealth) DEFINE_FIELD(PClassActor, FastSpeed) DEFINE_FIELD(PClassActor, RDFactor) DEFINE_FIELD(PClassActor, SelfDamageFactor) +DEFINE_FIELD(PClassActor, StealthAlpha) DEFINE_FIELD(PClassActor, CameraHeight) DEFINE_FIELD(PClassActor, HowlSound) DEFINE_FIELD(PClassActor, BloodType) @@ -4100,9 +4101,9 @@ void AActor::Tick () else if (visdir < 0) { Alpha -= 1.5/TICRATE; - if (Alpha < 0) + if (Alpha < GetClass()->StealthAlpha) { - Alpha = 0; + Alpha = GetClass()->StealthAlpha; visdir = 0; } } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 6537e2482..cf70b19ae 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1440,6 +1440,16 @@ DEFINE_PROPERTY(selfdamagefactor, F, Actor) static_cast(info)->SelfDamageFactor = i; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(stealthalpha, F, Actor) +{ + PROP_DOUBLE_PARM(i, 0); + assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); + static_cast(info)->StealthAlpha = i; +} + //========================================================================== // //========================================================================== From ac4074a69a685810bfba58e76c8a76effd4d2149 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 19:51:37 +0100 Subject: [PATCH 11/48] - allow sprites and particles simultaneously for puffs. --- src/p_mobj.cpp | 2 +- wadsrc/static/menudef.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d218d24de..88bb1d40a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6009,7 +6009,7 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 if (cl_pufftype && updown != 3 && (puff->flags4 & MF4_ALLOWPARTICLES)) { P_DrawSplash2 (32, pos, particledir, updown, 1); - puff->renderflags |= RF_INVISIBLE; + if (cl_pufftype == 1) puff->renderflags |= RF_INVISIBLE; } if ((flags & PF_HITTHING) && puff->SeeSound) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 954567d0f..b66b381ba 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -638,6 +638,7 @@ OptionValue PuffTypes { 0.0, "$OPTVAL_SPRITES" 1.0, "$OPTVAL_PARTICLES" + 2.0, "$OPTVAL_SPRITESPARTICLES" } OptionValue Wipes From e511f7f84b96963557947e99325523ef8bf56548 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 20:07:21 +0100 Subject: [PATCH 12/48] - added a damage type parameter to MDK CCMD. --- src/d_net.cpp | 13 +++++++++---- src/d_protocol.h | 3 ++- src/m_cheat.cpp | 21 +++++++++++++++++++-- src/m_cheat.h | 1 + src/version.h | 2 +- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 10ff7d0fc..6ba77bc2a 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2380,6 +2380,11 @@ void Net_DoCommand (int type, BYTE **stream, int player) SprayDecal(players[player].mo, s); break; + case DEM_MDK: + s = ReadString(stream); + cht_DoMDK(&players[player], s); + break; + case DEM_PAUSE: if (gamestate == GS_LEVEL) { @@ -2666,13 +2671,12 @@ void Net_DoCommand (int type, BYTE **stream, int player) case DEM_NETEVENT: { - const char *ename = ReadString(stream); + s = ReadString(stream); int argn = ReadByte(stream); int arg[3] = { 0, 0, 0 }; for (int i = 0; i < 3; i++) arg[i] = ReadLong(stream); - E_Console(player, ename, arg[0], arg[1], arg[2]); - delete[] ename; + E_Console(player, s, arg[0], arg[1], arg[2]); } break; @@ -2723,7 +2727,7 @@ void Net_SkipCommand (int type, BYTE **stream) break; case DEM_NETEVENT: - skip = strlen((char *)(*stream)) + 13; + skip = strlen((char *)(*stream)) + 14; break; case DEM_SUMMON2: @@ -2747,6 +2751,7 @@ void Net_SkipCommand (int type, BYTE **stream) case DEM_SPRAY: case DEM_MORPHEX: case DEM_KILLCLASSCHEAT: + case DEM_MDK: skip = strlen ((char *)(*stream)) + 1; break; diff --git a/src/d_protocol.h b/src/d_protocol.h index 27af1dae2..f95e3fc81 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -159,7 +159,8 @@ enum EDemoCommand DEM_SETSLOTPNUM, // 67 Byte: player number, the rest is the same as DEM_SETSLOT DEM_REMOVE, // 68 DEM_FINISHGAME, // 69 - DEM_NETEVENT // 70 String: Event name, Byte: Arg count; each arg is a 4-byte int + DEM_NETEVENT, // 70 String: Event name, Byte: Arg count; each arg is a 4-byte int + DEM_MDK // 71 String: Damage type }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index c78ab5dde..652385df2 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -55,6 +55,22 @@ // writes some bytes to the network data stream, and the network code // later calls us. +void cht_DoMDK(player_t *player, const char *mod) +{ + if (player->mo == NULL) + { + Printf("What do you want to kill outside of a game?\n"); + } + else if (!deathmatch) + { + // Don't allow this in deathmatch even with cheats enabled, because it's + // a very very cheap kill. + P_LineAttack(player->mo, player->mo->Angles.Yaw, PLAYERMISSILERANGE, + P_AimLineAttack(player->mo, player->mo->Angles.Yaw, PLAYERMISSILERANGE), TELEFRAG_DAMAGE, + mod, NAME_BulletPuff); + } +} + void cht_DoCheat (player_t *player, int cheat) { static const char * const BeholdPowers[9] = @@ -671,6 +687,7 @@ CCMD (mdk) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_MDK); + const char *name = argv.argc() > 1 ? argv[1] : ""; + Net_WriteByte (DEM_MDK); + Net_WriteString(name); } diff --git a/src/m_cheat.h b/src/m_cheat.h index baab5a451..729c3bff6 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -31,6 +31,7 @@ class player_t; class PClassActor; +void cht_DoMDK(player_t *player, const char *mod); void cht_DoCheat (player_t *player, int cheat); void cht_Give (player_t *player, const char *item, int amount=1); void cht_Take (player_t *player, const char *item, int amount=1); diff --git a/src/version.h b/src/version.h index a03c6a21e..d0910f8b4 100644 --- a/src/version.h +++ b/src/version.h @@ -57,7 +57,7 @@ const char *GetVersionString(); // Version identifier for network games. // Bump it every time you do a release unless you're certain you // didn't change anything that will affect sync. -#define NETGAMEVERSION 232 +#define NETGAMEVERSION 233 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to From 1ff401649845990fd154007b459839b907ea4157 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 20:42:12 +0100 Subject: [PATCH 13/48] - added ACS math functions floor, ceil and round. --- src/p_acs.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 4a2ca3fd9..baf15c110 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4368,6 +4368,9 @@ enum EACSFunctions ACSF_GetActorFloorTexture, ACSF_GetActorFloorTerrain, ACSF_StrArg, + ACSF_Floor, + ACSF_Ceil, + ACSF_Round, // OpenGL stuff @@ -6091,6 +6094,15 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_StrArg: return -FName(FBehavior::StaticLookupString(args[0])); + case ACSF_Floor: + return args[0] & ~0xffff; + + case ACSF_Ceil: + return (args[0] & ~0xffff) + 0x10000; + + case ACSF_Round: + return (args[0] + 32768) & ~0xffff; + default: break; } From d5d383ee93326c160a3a3f0d7454b5247f936375 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 21:31:59 +0100 Subject: [PATCH 14/48] - added Floor_Stop and Ceiling_Stop action specials. --- src/actionspecials.h | 2 ++ src/p_ceiling.cpp | 15 +++++++++++++++ src/p_floor.cpp | 15 +++++++++++++++ src/p_lnspec.cpp | 16 ++++++++++++++++ src/p_spec.h | 2 ++ 5 files changed, 50 insertions(+) diff --git a/src/actionspecials.h b/src/actionspecials.h index 233bb8958..173a07b2d 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -260,5 +260,7 @@ DEFINE_SPECIAL(Stairs_BuildUpDoomSync, 271, 4, 4, 4) DEFINE_SPECIAL(Stairs_BuildDownDoomSync, 272, 4, 4, 4) DEFINE_SPECIAL(Stairs_BuildUpDoomCrush, 273, 5, 5, 5) DEFINE_SPECIAL(Door_AnimatedClose, 274, 4, 4, 4) +DEFINE_SPECIAL(Floor_Stop, 275, 1, 1, 1) +DEFINE_SPECIAL(Ceiling_Stop, 276, 1, 1, 1) #undef DEFINE_SPECIAL diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 7bf1f9099..b978fd0d3 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -582,3 +582,18 @@ bool EV_CeilingCrushStop (int tag, bool remove) return rtn; } + +bool EV_StopCeiling(int tag) +{ + FSectorTagIterator it(tag); + while (int sec = it.Next()) + { + if (level.sectors[sec].ceilingdata) + { + SN_StopSequence(&level.sectors[sec], CHAN_CEILING); + level.sectors[sec].ceilingdata->Destroy(); + level.sectors[sec].ceilingdata = nullptr; + } + } + return true; +} diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 2fd205a9d..1bd0c53fc 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -561,6 +561,21 @@ bool EV_FloorCrushStop (int tag) return true; } +// same as above but stops any floor mover that was active on the given sector. +bool EV_StopFloor(int tag) +{ + FSectorTagIterator it(tag); + while (int sec = it.Next()) + { + if (level.sectors[sec].floordata) + { + SN_StopSequence(&level.sectors[sec], CHAN_FLOOR); + level.sectors[sec].floordata->Destroy(); + level.sectors[sec].floordata = nullptr; + } + } + return true; +} //========================================================================== // // BUILD A STAIRCASE! diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index ee70dcee5..ff72b3baa 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -563,6 +563,13 @@ FUNC(LS_Generic_Floor) } +FUNC(LS_Floor_Stop) +// Floor_Stop (tag) +{ + return EV_StopFloor(arg0); +} + + FUNC(LS_Stairs_BuildDown) // Stair_BuildDown (tag, speed, height, delay, reset) { @@ -860,6 +867,13 @@ FUNC(LS_Ceiling_LowerByTexture) return EV_DoCeiling (DCeiling::ceilLowerByTexture, ln, arg0, SPEED(arg1), 0, 0, CRUSH(arg3), 0, CHANGE(arg4)); } +FUNC(LS_Ceiling_Stop) +// Ceiling_Stop (tag) +{ + return EV_StopCeiling(arg0); +} + + FUNC(LS_Generic_Ceiling) // Generic_Ceiling (tag, speed, height, target, change/model/direct/crush) { @@ -3614,6 +3628,8 @@ static lnSpecFunc LineSpecials[] = /* 272 */ LS_Stairs_BuildDownDoomSync, /* 273 */ LS_Stairs_BuildUpDoomCrush, /* 274 */ LS_Door_AnimatedClose, + /* 275 */ LS_Floor_Stop, + /* 276 */ LS_Ceiling_Stop, }; diff --git a/src/p_spec.h b/src/p_spec.h index b00e5cacf..930ae5143 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -451,6 +451,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line, int tag, double speed, double speed2, double height, int crush, int silent, int change, DCeiling::ECrushMode hexencrush = DCeiling::ECrushMode::crushDoom); bool EV_CeilingCrushStop (int tag, bool remove); +bool EV_StopCeiling(int tag); void P_ActivateInStasisCeiling (int tag); @@ -564,6 +565,7 @@ bool EV_DoFloor(DFloor::EFloor floortype, line_t *line, int tag, double speed, double height, int crush, int change, bool hexencrush, bool hereticlower = false); bool EV_FloorCrushStop (int tag); +bool EV_StopFloor(int tag); bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed); class DElevator : public DMover From 3700dea3361361999d6b4102a0551faa42783c53 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 22:05:20 +0100 Subject: [PATCH 15/48] Revert "- the UDMF health key for actors was not correctly implemented. This addresses the problem by adding a second one and documenting 'Health' as implemented." This reverts commit e4e023e59a516aa8d74b7db02b27dbe6c45fa542. (This was nonsense.) --- specs/udmf_zdoom.txt | 4 ++-- src/dobjtype.cpp | 14 ++++++++++++-- src/dobjtype.h | 5 ++++- src/namedef.h | 1 - src/p_udmf.cpp | 16 ---------------- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 553c75360..f4af55f2d 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -263,8 +263,8 @@ Note: All fields default to false unless mentioned otherwise. gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1.0. - health = ; // Set per-actor health as an absolute value. Default = actor default. - healthfactor = ; // Set per-actor health as a factor to the original. Default = 1. + health = ; // Set per-actor health. Positive values are multiplied with the class's property, + // negative values are used as their absolute. Default = 1. renderstyle = ; // Set per-actor render style, overriding the class default. Possible values can be "normal", // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 75193b868..97d154a3b 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3160,7 +3160,6 @@ void PClass::InitializeDefaults() optr->ObjNext = nullptr; optr->SetClass(this); - // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != nullptr) { @@ -3174,6 +3173,13 @@ void PClass::InitializeDefaults() { memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } + + if (MetaSize != 0) + { + Meta = (BYTE*)ClassDataAllocator.Alloc(MetaSize); + memset(Meta, 0, MetaSize); + if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + } } if (bRuntimeClass) @@ -3183,10 +3189,14 @@ void PClass::InitializeDefaults() if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); for (const PField *field : Fields) { - if (!(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } + if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) + { + field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); + } } } } diff --git a/src/dobjtype.h b/src/dobjtype.h index 0151e6c11..24951c9d8 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -560,8 +560,9 @@ class PClass : public PNativeStruct protected: // We unravel _WITH_META here just as we did for PType. TArray SpecialInits; + TArray MetaInits; void Derive(PClass *newclass, FName name); - void InitializeSpecials(void *addr, void *defaults) const; + void InitializeSpecials(void *addr, void *defaults, TArray* PClass::*Inits); void SetSuper(); public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; @@ -582,6 +583,8 @@ public: const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default const size_t *ArrayPointers; // dynamic arrays containing object pointers. BYTE *Defaults; + BYTE *Meta; // Per-class static script data + unsigned MetaSize; bool bRuntimeClass; // class was defined at run-time, not compile-time bool bExported; // This type has been declared in a script bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility diff --git a/src/namedef.h b/src/namedef.h index 28de56818..bb42fc76d 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -46,7 +46,6 @@ xx(Shadow) xx(Subtract) xx(Subtractive) xx(FillColor) -xx(HealthFactor) // Healingradius types xx(Mana) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index b9300f654..27293b918 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -515,7 +515,6 @@ public: FString arg0str, arg1str; memset(th, 0, sizeof(*th)); - double healthfactor = 1; th->Gravity = 1; th->RenderStyle = STYLE_Count; th->Alpha = -1; @@ -739,52 +738,38 @@ public: break; case NAME_Alpha: - CHECK_N(Zd | Zdt) th->Alpha = CheckFloat(key); break; case NAME_FillColor: - CHECK_N(Zd | Zdt) th->fillcolor = CheckInt(key); break; case NAME_Health: - CHECK_N(Zd | Zdt) th->health = CheckInt(key); break; - case NAME_HealthFactor: - CHECK_N(Zd | Zdt) - healthfactor = CheckFloat(key); - break; - case NAME_Score: - CHECK_N(Zd | Zdt) th->score = CheckInt(key); break; case NAME_Pitch: - CHECK_N(Zd | Zdt) th->pitch = (short)CheckInt(key); break; case NAME_Roll: - CHECK_N(Zd | Zdt) th->roll = (short)CheckInt(key); break; case NAME_ScaleX: - CHECK_N(Zd | Zdt) th->Scale.X = CheckFloat(key); break; case NAME_ScaleY: - CHECK_N(Zd | Zdt) th->Scale.Y = CheckFloat(key); break; case NAME_Scale: - CHECK_N(Zd | Zdt) th->Scale.X = th->Scale.Y = CheckFloat(key); break; @@ -808,7 +793,6 @@ public: { th->args[1] = -FName(arg1str); } - th->health = int(th->health * healthfactor); // Thing specials are only valid in namespaces with Hexen-type specials // and in ZDoomTranslated - which will use the translator on them. if (namespc == NAME_ZDoomTranslated) From f343d36ea941829b68c239eb91d0f68c4e7a3b38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 23:28:19 +0100 Subject: [PATCH 16/48] - implemented the basics of a working metadata system. This will store class meta properties in a separate memory block so that it won't have to muck around with PClass - which made the implementation from the scripting branch relatively useless because extending the data wasn't particularly easy and also not well implemented. This can now be handled just like the defaults. --- src/dobjtype.cpp | 105 ++++++++++++++++++---- src/dobjtype.h | 14 +-- src/intermission/intermission.h | 6 +- src/menu/menu.cpp | 2 +- src/scripting/backend/codegen.cpp | 8 +- src/scripting/decorate/thingdef_parse.cpp | 9 +- src/scripting/vm/vmexec.h | 8 +- src/scripting/vm/vmops.h | 3 +- src/scripting/zscript/zcc_compile.cpp | 14 +-- 9 files changed, 128 insertions(+), 41 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 75193b868..dcb93599d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2910,6 +2910,11 @@ PClass::~PClass() M_Free(Defaults); Defaults = nullptr; } + if (Meta != nullptr) + { + M_Free(Meta); + Meta = nullptr; + } } //========================================================================== @@ -3047,7 +3052,7 @@ PClass *PClass::FindClass (FName zaname) // //========================================================================== -DObject *PClass::CreateNew() const +DObject *PClass::CreateNew() { BYTE *mem = (BYTE *)M_Malloc (Size); assert (mem != nullptr); @@ -3064,7 +3069,7 @@ DObject *PClass::CreateNew() const } ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); - InitializeSpecials(mem, Defaults); + InitializeSpecials(mem, Defaults, &PClass::SpecialInits); return (DObject *)mem; } @@ -3076,7 +3081,7 @@ DObject *PClass::CreateNew() const // //========================================================================== -void PClass::InitializeSpecials(void *addr, void *defaults) const +void PClass::InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits) { // Once we reach a native class, we can stop going up the family tree, // since native classes handle initialization natively. @@ -3085,8 +3090,8 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const return; } assert(ParentClass != nullptr); - ParentClass->InitializeSpecials(addr, defaults); - for (auto tao : SpecialInits) + ParentClass->InitializeSpecials(addr, defaults, Inits); + for (auto tao : (this->*Inits)) { tao.first->InitializeValue((char*)addr + tao.second, defaults == nullptr? nullptr : ((char*)defaults) + tao.second); } @@ -3101,7 +3106,7 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const // //========================================================================== -void PClass::DestroySpecials(void *addr) const +void PClass::DestroySpecials(void *addr) { // Once we reach a native class, we can stop going up the family tree, // since native classes handle deinitialization natively. @@ -3160,7 +3165,6 @@ void PClass::InitializeDefaults() optr->ObjNext = nullptr; optr->SetClass(this); - // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != nullptr) { @@ -3174,19 +3178,31 @@ void PClass::InitializeDefaults() { memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } + + if (MetaSize != 0) + { + Meta = (BYTE*)M_Malloc(MetaSize); + memset(Meta, 0, MetaSize); + if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + } } if (bRuntimeClass) { // Copy parent values from the parent defaults. assert(ParentClass != nullptr); - if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); + if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits); + if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits); for (const PField *field : Fields) { - if (!(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } + if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) + { + field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); + } } } } @@ -3264,6 +3280,39 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) return type; } +//========================================================================== +// +// PStruct :: AddField +// +// Appends a new metadata field to the end of a struct. Returns either the new field +// or nullptr if a symbol by that name already exists. +// +//========================================================================== + +PField *PClass::AddMetaField(FName name, PType *type, DWORD flags) +{ + PField *field = new PField(name, type, flags); + + // The new field is added to the end of this struct, alignment permitting. + field->Offset = (MetaSize + (type->Align - 1)) & ~(type->Align - 1); + + // Enlarge this struct to enclose the new field. + MetaSize = unsigned(field->Offset + type->Size); + + // This struct's alignment is the same as the largest alignment of any of + // its fields. + Align = MAX(Align, type->Align); + + if (Symbols.AddSymbol(field) == nullptr) + { // name is already in use + field->Destroy(); + return nullptr; + } + Fields.Push(field); + + return field; +} + //========================================================================== // // PClass :: AddField @@ -3272,18 +3321,36 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) PField *PClass::AddField(FName name, PType *type, DWORD flags) { - unsigned oldsize = Size; - PField *field = Super::AddField(name, type, flags); - - // Only initialize the defaults if they have already been created. - // For ZScript this is not the case, it will first define all fields before - // setting up any defaults for any class. - if (field != nullptr && !(flags & VARF_Native) && Defaults != nullptr) + if (!(flags & VARF_Meta)) { - Defaults = (BYTE *)M_Realloc(Defaults, Size); - memset(Defaults + oldsize, 0, Size - oldsize); + unsigned oldsize = Size; + PField *field = Super::AddField(name, type, flags); + + // Only initialize the defaults if they have already been created. + // For ZScript this is not the case, it will first define all fields before + // setting up any defaults for any class. + if (field != nullptr && !(flags & VARF_Native) && Defaults != nullptr) + { + Defaults = (BYTE *)M_Realloc(Defaults, Size); + memset(Defaults + oldsize, 0, Size - oldsize); + } + return field; + } + else + { + unsigned oldsize = MetaSize; + PField *field = AddMetaField(name, type, flags); + + // Only initialize the defaults if they have already been created. + // For ZScript this is not the case, it will first define all fields before + // setting up any defaults for any class. + if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) + { + Meta = (BYTE *)M_Realloc(Meta, MetaSize); + memset(Meta + oldsize, 0, MetaSize - oldsize); + } + return field; } - return field; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 0151e6c11..c88b00930 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -557,12 +557,13 @@ enum class PClass : public PNativeStruct { DECLARE_CLASS(PClass, PNativeStruct); -protected: // We unravel _WITH_META here just as we did for PType. - TArray SpecialInits; +protected: + TArray MetaInits; void Derive(PClass *newclass, FName name); - void InitializeSpecials(void *addr, void *defaults) const; + void InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits); void SetSuper(); + PField *AddMetaField(FName name, PType *type, DWORD flags); public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; void WriteAllFields(FSerializer &ar, const void *addr) const; @@ -577,11 +578,14 @@ public: static void StaticBootstrap(); // Per-class information ------------------------------------- + TArray SpecialInits; PClass *ParentClass; // the class this class derives from const size_t *Pointers; // object pointers defined by this class *only* const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default const size_t *ArrayPointers; // dynamic arrays containing object pointers. BYTE *Defaults; + BYTE *Meta; // Per-class static script data + unsigned MetaSize; bool bRuntimeClass; // class was defined at run-time, not compile-time bool bExported; // This type has been declared in a script bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility @@ -593,13 +597,13 @@ public: PClass(); ~PClass(); void InsertIntoHash(); - DObject *CreateNew() const; + DObject *CreateNew(); PClass *CreateDerivedClass(FName name, unsigned int size); PField *AddField(FName name, PType *type, DWORD flags=0) override; void InitializeActorInfo(); void BuildFlatPointers(); void BuildArrayPointers(); - void DestroySpecials(void *addr) const; + void DestroySpecials(void *addr); const PClass *NativeClass() const; // Returns true if this type is an ancestor of (or same as) the passed type. diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index cdc100d88..f0b423150 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -58,15 +58,15 @@ enum EScrollDir }; // actions that don't create objects -#define WIPER_ID ((const PClass*)intptr_t(-1)) -#define TITLE_ID ((const PClass*)intptr_t(-2)) +#define WIPER_ID ((PClass*)intptr_t(-1)) +#define TITLE_ID ((PClass*)intptr_t(-2)) //========================================================================== struct FIntermissionAction { int mSize; - const PClass *mClass; + PClass *mClass; FString mMusic; int mMusicOrder; int mCdTrack; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 8b0bf35e9..1c8e0b39b 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -472,7 +472,7 @@ void M_SetMenu(FName menu, int param) } else { - const PClass *menuclass = PClass::FindClass(menu); + PClass *menuclass = PClass::FindClass(menu); if (menuclass != nullptr) { if (menuclass->IsDescendantOf("GenericMenu")) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index cc93c2215..bd18103fc 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6371,7 +6371,7 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build) ExpEmit ob = obj->Emit(build); ob.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(OP_META, meta.RegNum, ob.RegNum); + build->Emit(OP_CLSS, meta.RegNum, ob.RegNum); build->Emit(OP_LOS, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults))); return meta; @@ -6805,7 +6805,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { obj.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(OP_META, meta.RegNum, obj.RegNum); + build->Emit(membervar->Flags & VARF_Native? OP_CLSS : OP_META, meta.RegNum, obj.RegNum); obj = meta; } @@ -8832,7 +8832,7 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build) ExpEmit op = Self->Emit(build); op.Free(build); ExpEmit to(build, REGT_POINTER); - build->Emit(OP_META, to.RegNum, op.RegNum); + build->Emit(OP_CLSS, to.RegNum, op.RegNum); return to; } @@ -8873,7 +8873,7 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build) if (Self->IsObject()) { ExpEmit to(build, REGT_POINTER); - build->Emit(OP_META, to.RegNum, op.RegNum); + build->Emit(OP_CLSS, to.RegNum, op.RegNum); op = to; op.Free(build); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e444d30a9..bd4d781a1 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -827,7 +827,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul if (i > 0) sc.MustGetStringName(","); if (f->Flags & VARF_Meta) { - addr = ((char*)bag.Info) + f->Offset; + if (f->Flags & VARF_Native) + { + addr = ((char*)bag.Info) + f->Offset; + } + else + { + addr = ((char*)bag.Info->Meta) + f->Offset; + } } else { diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 3082abf80..c37e29cbf 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -109,12 +109,18 @@ begin: reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts. NEXTOP; - OP(META): + OP(CLSS): ASSERTA(a); ASSERTO(B); reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... reg.atag[a] = ATAG_OBJECT; NEXTOP; + OP(META): + ASSERTA(a); ASSERTO(B); + reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(LB): ASSERTD(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index b058dc94b..3d503932a 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -23,7 +23,8 @@ xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer -xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta class address +xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta data address +xx(CLSS, clss, RPRP, NOP, 0, 0), // load a class's descriptor address // Load from memory. rA = *(rB + rkC) xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b28226efb..6f902648e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1070,11 +1070,6 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (field->Flags & ZCC_Meta) { varflags |= VARF_Meta | VARF_Static | VARF_ReadOnly; // metadata implies readonly - if (!(field->Flags & ZCC_Native)) - { - // Non-native meta data is not implemented yet and requires some groundwork in the class copy code. - Error(field, "Metadata member %s must be native", FName(field->Names->Name).GetChars()); - } } if (field->Type->ArraySize != nullptr) @@ -1692,7 +1687,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop if (f->Flags & VARF_Meta) { - addr = ((char*)bag.Info) + f->Offset; + if (f->Flags & VARF_Native) + { + addr = ((char*)bag.Info) + f->Offset; + } + else + { + addr = ((char*)bag.Info->Meta) + f->Offset; + } } else { From 78a66e001aa0c67e88f3fba81bdf2ce511542a3b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 00:45:16 +0100 Subject: [PATCH 17/48] - properly handle all meta properties for inventory items. --- src/dobject.h | 1 + src/dobjtype.cpp | 40 ++++++++++++++----- src/dobjtype.h | 6 +++ src/g_inventory/a_pickups.cpp | 5 +-- src/g_inventory/a_pickups.h | 1 - src/info.cpp | 1 - src/info.h | 1 - src/namedef.h | 2 + src/scripting/decorate/olddecorations.cpp | 4 +- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/thingdef_properties.cpp | 19 --------- src/scripting/zscript/zcc_compile.cpp | 5 +++ wadsrc/static/zscript/inventory/ammo.txt | 2 +- wadsrc/static/zscript/inventory/health.txt | 4 +- wadsrc/static/zscript/inventory/inv_misc.txt | 4 +- wadsrc/static/zscript/inventory/inventory.txt | 7 +++- wadsrc/static/zscript/inventory/weapons.txt | 2 +- 17 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 41b5e2824..7510a4cff 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -486,6 +486,7 @@ public: PalEntry &ColorVar(FName field); FName &NameVar(FName field); double &FloatVar(FName field); + FString &StringVar(FName field); template T*& PointerVar(FName field); // If you need to replace one object with another and want to diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dcb93599d..1d5cd1512 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2892,6 +2892,7 @@ PClass::PClass() bExported = false; bDecorateClass = false; ConstructNative = nullptr; + Meta = nullptr; mDescriptiveName = "Class"; PClass::AllClasses.Push(this); @@ -3085,11 +3086,10 @@ void PClass::InitializeSpecials(void *addr, void *defaults, TArrayInitializeSpecials(addr, defaults, Inits); for (auto tao : (this->*Inits)) { @@ -3179,11 +3179,27 @@ void PClass::InitializeDefaults() memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } + assert(MetaSize >= ParentClass->MetaSize); if (MetaSize != 0) { Meta = (BYTE*)M_Malloc(MetaSize); - memset(Meta, 0, MetaSize); - if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + + // Copy the defaults from the parent but leave the DObject part alone because it contains important data. + if (ParentClass->Meta != nullptr) + { + memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + if (MetaSize > ParentClass->MetaSize) + { + memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize); + } + } + else + { + memset(Meta, 0, MetaSize); + } + + if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + else memset(Meta, 0, MetaSize); } } @@ -3199,10 +3215,14 @@ void PClass::InitializeDefaults() { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } - if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) - { - field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); - } + } + } + if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits); + for (const PField *field : Fields) + { + if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) + { + field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); } } } @@ -3264,6 +3284,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) type->bRuntimeClass = true; Derive(type, name); type->Size = size; + type->MetaSize = MetaSize; if (size != TentativeClass) { type->InitializeDefaults(); @@ -3344,7 +3365,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) // Only initialize the defaults if they have already been created. // For ZScript this is not the case, it will first define all fields before // setting up any defaults for any class. - if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) + if (field != nullptr && !(flags & VARF_Native)) { Meta = (BYTE *)M_Realloc(Meta, MetaSize); memset(Meta + oldsize, 0, MetaSize - oldsize); @@ -3380,6 +3401,7 @@ PClass *PClass::FindClassTentative(FName name) PClass *type = static_cast(GetClass()->CreateNew()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); + assert(MetaSize == 0); Derive(type, name); type->Size = TentativeClass; TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket); diff --git a/src/dobjtype.h b/src/dobjtype.h index c88b00930..76e17b133 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -603,6 +603,7 @@ public: void InitializeActorInfo(); void BuildFlatPointers(); void BuildArrayPointers(); + void InitMeta(); void DestroySpecials(void *addr); const PClass *NativeClass() const; @@ -742,6 +743,11 @@ inline double &DObject::FloatVar(FName field) return *(double*)ScriptVar(field, TypeFloat64); } +inline FString &DObject::StringVar(FName field) +{ + return *(FString*)ScriptVar(field, TypeString); +} + template inline T *&DObject::PointerVar(FName field) { diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 53e7d84ed..df6679d41 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -50,8 +50,6 @@ DEFINE_FIELD(AInventory, DropTime) DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, PickupFlash) DEFINE_FIELD(AInventory, PickupSound) -DEFINE_FIELD(AInventory, GiveQuest) -DEFINE_FIELD(PClassActor, PickupMsg) //=========================================================================== // @@ -115,8 +113,7 @@ void AInventory::Serialize(FSerializer &arc) ("icon", Icon, def->Icon) ("pickupsound", PickupSound, def->PickupSound) ("spawnpointclass", SpawnPointClass, def->SpawnPointClass) - ("droptime", DropTime, def->DropTime) - ("givequest", GiveQuest, def->GiveQuest); + ("droptime", DropTime, def->DropTime); } //=========================================================================== diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 817fcf176..9258d320a 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -87,7 +87,6 @@ public: FTextureID Icon; // Icon to show on status bar or HUD int DropTime; // Countdown after dropping PClassActor *SpawnPointClass; // For respawning like Heretic's mace - int GiveQuest; // Optionally give one of the quest items. FTextureID AltHUDIcon; DWORD ItemFlags; diff --git a/src/info.cpp b/src/info.cpp index 7cac3569d..2bba8afb4 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -354,7 +354,6 @@ void PClassActor::DeriveData(PClass *newclass) } // Inventory stuff - newa->PickupMsg = PickupMsg; newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass; newa->RestrictedToPlayerClass = RestrictedToPlayerClass; diff --git a/src/info.h b/src/info.h index 6d6329f88..f0f0f6c3c 100644 --- a/src/info.h +++ b/src/info.h @@ -321,7 +321,6 @@ public: double MissileHeight; // These are only valid for inventory items. - FString PickupMsg; TArray RestrictedToPlayerClass; TArray ForbiddenToPlayerClass; diff --git a/src/namedef.h b/src/namedef.h index 28de56818..df2841daa 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -398,6 +398,8 @@ xx(VisibleStartPitch) xx(VisibleEndAngle) xx(VisibleEndPitch) xx(Format) +xx(PickupMsg) +xx(Respawnable) // Various actor names which are used internally xx(MapSpot) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 50e8f9c6a..5c5714ba3 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -541,11 +541,11 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) { sc.MustGetString (); - bag.Info->PickupMsg = sc.String; + inv->StringVar(NAME_PickupMsg) = sc.String; } else if (def == DEF_Pickup && sc.Compare ("Respawns")) { - inv->BoolVar("Respawnable") = true; + inv->BoolVar(NAME_Respawnable) = true; } else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath")) { diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index bd4d781a1..e70059fec 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -874,7 +874,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul else if (f->Type->IsKindOf(RUNTIME_CLASS(PString))) { sc.MustGetString(); - *(FString*)addr = sc.String; + *(FString*)addr = strbin1(sc.String); } else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index cf70b19ae..527782382 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1831,16 +1831,6 @@ DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory) defaults->PickupFlash = FindClassTentative(str, RUNTIME_CLASS(AActor)); } -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->PickupMsg = str; -} - //========================================================================== // //========================================================================== @@ -1875,15 +1865,6 @@ DEFINE_CLASS_PROPERTY(usesound, S, Inventory) defaults->UseSound = str; } -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY(givequest, I, Inventory) -{ - PROP_INT_PARM(i, 0); - defaults->GiveQuest = i; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6f902648e..1a9dfbe8d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1007,6 +1007,11 @@ void ZCCCompiler::CompileAllFields() type->Size = Classes[i]->Type()->ParentClass->Size; } } + if (Classes[i]->Type()->ParentClass) + type->MetaSize = Classes[i]->Type()->ParentClass->MetaSize; + else + type->MetaSize = 0; + if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false, !!HasNativeChildren.CheckKey(type))) { // Remove from the list if all fields got compiled. diff --git a/wadsrc/static/zscript/inventory/ammo.txt b/wadsrc/static/zscript/inventory/ammo.txt index e742e806d..092a93846 100644 --- a/wadsrc/static/zscript/inventory/ammo.txt +++ b/wadsrc/static/zscript/inventory/ammo.txt @@ -37,7 +37,7 @@ class Ammo : Inventory { int BackpackAmount; int BackpackMaxAmount; - /*meta*/ int DropAmount; + meta int DropAmount; property BackpackAmount: BackpackAmount; property BackpackMaxAmount: BackpackMaxAmount; diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index 230b3575b..e2fb8eacf 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -36,8 +36,8 @@ class Health : Inventory { transient int PrevHealth; - /*meta*/ int LowHealth; - /*meta*/ String LowHealthMessage; + meta int LowHealth; + meta String LowHealthMessage; property LowMessage: LowHealth, LowHealthMessage; diff --git a/wadsrc/static/zscript/inventory/inv_misc.txt b/wadsrc/static/zscript/inventory/inv_misc.txt index 441566786..ce4bf805b 100644 --- a/wadsrc/static/zscript/inventory/inv_misc.txt +++ b/wadsrc/static/zscript/inventory/inv_misc.txt @@ -87,8 +87,8 @@ class MapRevealer : Inventory class PuzzleItem : Inventory { - /*meta*/ int PuzzleItemNumber; - /*meta*/ String PuzzFailMessage; + meta int PuzzleItemNumber; + meta String PuzzFailMessage; property Number: PuzzleItemNumber; property FailMessage: PuzzFailMessage; diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 06caedad7..cac9b9b8f 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -23,8 +23,11 @@ class Inventory : Actor native native bool bPickupGood; native bool bCreateCopyMoved; native bool bInitEffectFailed; - native meta String PickupMsg; - native /*meta*/ int GiveQuest; + meta String PickupMsg; + meta int GiveQuest; + + Property PickupMessage: PickupMsg; + Property GiveQuest: GiveQuest; Default { diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index c76aaef54..de9464726 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -33,7 +33,7 @@ class Weapon : StateProvider native native float FOVScale; native int Crosshair; // 0 to use player's crosshair native bool GivenAsMorphWeapon; - native bool bAltFire; // Set when self weapon's alternate fire is used. + native bool bAltFire; // Set when this weapon's alternate fire is used. native readonly bool bDehAmmo; Default From 4a87a598fb0926ff36d4740879af859f78a91b56 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 00:59:09 +0100 Subject: [PATCH 18/48] - do floatification of the UDMF Health property as it should have been. --- specs/udmf_zdoom.txt | 2 +- src/dobjtype.cpp | 14 ++------------ src/dobjtype.h | 5 +---- src/doomdata.h | 2 +- src/p_mobj.cpp | 10 +++++----- src/p_setup.cpp | 4 ++-- src/p_udmf.cpp | 4 ++-- 7 files changed, 14 insertions(+), 27 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index f4af55f2d..eeb3c2a56 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -263,7 +263,7 @@ Note: All fields default to false unless mentioned otherwise. gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1.0. - health = ; // Set per-actor health. Positive values are multiplied with the class's property, + health = ; // Set per-actor health. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1. renderstyle = ; // Set per-actor render style, overriding the class default. Possible values can be "normal", diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 97d154a3b..75193b868 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3160,6 +3160,7 @@ void PClass::InitializeDefaults() optr->ObjNext = nullptr; optr->SetClass(this); + // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != nullptr) { @@ -3173,13 +3174,6 @@ void PClass::InitializeDefaults() { memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } - - if (MetaSize != 0) - { - Meta = (BYTE*)ClassDataAllocator.Alloc(MetaSize); - memset(Meta, 0, MetaSize); - if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); - } } if (bRuntimeClass) @@ -3189,14 +3183,10 @@ void PClass::InitializeDefaults() if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); for (const PField *field : Fields) { - if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta)) + if (!(field->Flags & VARF_Native)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } - if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) - { - field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); - } } } } diff --git a/src/dobjtype.h b/src/dobjtype.h index 24951c9d8..0151e6c11 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -560,9 +560,8 @@ class PClass : public PNativeStruct protected: // We unravel _WITH_META here just as we did for PType. TArray SpecialInits; - TArray MetaInits; void Derive(PClass *newclass, FName name); - void InitializeSpecials(void *addr, void *defaults, TArray* PClass::*Inits); + void InitializeSpecials(void *addr, void *defaults) const; void SetSuper(); public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; @@ -583,8 +582,6 @@ public: const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default const size_t *ArrayPointers; // dynamic arrays containing object pointers. BYTE *Defaults; - BYTE *Meta; // Per-class static script data - unsigned MetaSize; bool bRuntimeClass; // class was defined at run-time, not compile-time bool bExported; // This type has been declared in a script bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility diff --git a/src/doomdata.h b/src/doomdata.h index eca7dcd4a..39f0d184a 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -359,7 +359,7 @@ struct FMapThing double Alpha; DWORD fillcolor; DVector2 Scale; - int health; + double Health; int score; short pitch; short roll; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 88bb1d40a..f38ac12bb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5930,13 +5930,13 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) mobj->LevelSpawned (); } - if (mthing->health > 0) - mobj->health *= mthing->health; + if (mthing->Health > 0) + mobj->health = int(mobj->health * mthing->Health); else - mobj->health = -mthing->health; - if (mthing->health == 0) + mobj->health = -int(mthing->Health); + if (mthing->Health == 0) mobj->CallDie(NULL, NULL); - else if (mthing->health != 1) + else if (mthing->Health != 1) mobj->StartHealth = mobj->health; return mobj; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 308054a8b..76e8b6b34 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1741,7 +1741,7 @@ void P_LoadThings (MapData * map) mti[i].ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes mti[i].RenderStyle = STYLE_Count; mti[i].Alpha = -1; - mti[i].health = 1; + mti[i].Health = 1; mti[i].FloatbobPhase = -1; mti[i].pos.X = LittleShort(mt->x); @@ -1837,7 +1837,7 @@ void P_LoadThings2 (MapData * map) mti[i].Gravity = 1; mti[i].RenderStyle = STYLE_Count; mti[i].Alpha = -1; - mti[i].health = 1; + mti[i].Health = 1; mti[i].FloatbobPhase = -1; } delete[] mtp; diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 27293b918..4d5e00e48 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -518,7 +518,7 @@ public: th->Gravity = 1; th->RenderStyle = STYLE_Count; th->Alpha = -1; - th->health = 1; + th->Health = 1; th->FloatbobPhase = -1; sc.MustGetToken('{'); while (!sc.CheckToken('}')) @@ -746,7 +746,7 @@ public: break; case NAME_Health: - th->health = CheckInt(key); + th->Health = CheckFloat(key); break; case NAME_Score: From a93a7e1cac9745aa8ec731e4015a3d7b71fe1da5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 01:23:12 +0100 Subject: [PATCH 19/48] - handle player meta properties. Only two really make sense, the rest is never used from scripts and may just remain where it was. --- src/d_player.h | 2 -- src/p_user.cpp | 3 --- src/scripting/thingdef_properties.cpp | 18 ----------------- src/scripting/zscript/zcc_compile.cpp | 6 ++++-- wadsrc/static/zscript/shared/player.txt | 26 ++++++++++++++----------- 5 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 2d7d439c5..43e6e53ab 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -159,8 +159,6 @@ public: FNameNoInit Face; // Doom status bar face (when used) FNameNoInit Portrait; FNameNoInit Slot[10]; - FNameNoInit InvulMode; - FNameNoInit HealingRadiusType; double HexenArmor[5]; BYTE ColorRangeStart; // Skin color range BYTE ColorRangeEnd; diff --git a/src/p_user.cpp b/src/p_user.cpp index 5bb0e2127..30db0a271 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3325,13 +3325,10 @@ DEFINE_FIELD(APlayerPawn, FlechetteType) DEFINE_FIELD(APlayerPawn, DamageFade) DEFINE_FIELD(APlayerPawn, ViewBob) DEFINE_FIELD(APlayerPawn, FullHeight) - -DEFINE_FIELD(APlayerPawn, HealingRadiusType) DEFINE_FIELD(APlayerPawn, SoundClass) DEFINE_FIELD(APlayerPawn, Face) DEFINE_FIELD(APlayerPawn, Portrait) DEFINE_FIELD(APlayerPawn, Slot) -DEFINE_FIELD(APlayerPawn, InvulMode) DEFINE_FIELD(APlayerPawn, HexenArmor) DEFINE_FIELD(APlayerPawn, ColorRangeStart) DEFINE_FIELD(APlayerPawn, ColorRangeEnd) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 527782382..09f6dcd95 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2699,24 +2699,6 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn) bag.DropItemList = di; } -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn) -{ - PROP_STRING_PARM(str, 0); - defaults->InvulMode = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn) -{ - PROP_STRING_PARM(str, 0); - defaults->HealingRadiusType = str; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1a9dfbe8d..548424cd9 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1188,8 +1188,10 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray &Proper FString qualifiedname; // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. - if (prefix == NAME_None) qualifiedname.Format("@property@%s", FName(p->NodeName).GetChars()); - else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), FName(p->NodeName).GetChars()); + FName name = FName(p->NodeName); + if (prefix == NAME_None) qualifiedname.Format("@property@%s", name.GetChars()); + else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), name.GetChars()); + fields.ShrinkToFit(); if (!type->Symbols.AddSymbol(new PProperty(qualifiedname, fields))) { diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8886e6744..9b686a551 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -8,18 +8,14 @@ class PlayerPawn : Actor native native int PlayerFlags; native Inventory InvFirst; // first inventory item displayed on inventory bar native Inventory InvSel; // selected inventory item - native meta String DisplayName; // Display name (used in menus, etc.) + native Name SoundClass; // Sound class + native Name Face; // Doom status bar face (when used) + native Name Portrait; + native Name Slot[10]; + native double HexenArmor[5]; + native uint8 ColorRangeStart; // Skin color range + native uint8 ColorRangeEnd; - native /*meta*/ Name SoundClass; // Sound class - native /*meta*/ Name Face; // Doom status bar face (when used) - native /*meta*/ Name Portrait; - native /*meta*/ Name Slot[10]; - native /*meta*/ Name InvulMode; - native /*meta*/ Name HealingRadiusType; - native /*meta*/ double HexenArmor[5]; - native /*meta*/ uint8 ColorRangeStart; // Skin color range - native /*meta*/ uint8 ColorRangeEnd; - // [GRB] Player class properties native double JumpZ; native double GruntSpeed; @@ -37,6 +33,14 @@ class PlayerPawn : Actor native native color DamageFade; // [CW] Fades for when you are being damaged. native double ViewBob; // [SP] ViewBob Multiplier native double FullHeight; + + native meta String DisplayName; // Display name (used in menus, etc.) + meta Name HealingRadiusType; + meta Name InvulMode; + + Property prefix: Player; + Property HealRadiusType: HealingradiusType; + Property InvulnerabilityMode: InvulMode; Default { From b6a1fe7fc6ac50409cc127c026e39387a5955f94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 10:51:32 +0100 Subject: [PATCH 20/48] - scriptified the basic attack functions, its properties and the explosion properties to test the new metadata system. --- src/dobject.cpp | 14 +++- src/info.cpp | 13 ---- src/info.h | 9 --- src/namedef.h | 3 + src/p_actionfunctions.cpp | 87 +-------------------- src/p_mobj.cpp | 7 -- src/scripting/decorate/olddecorations.cpp | 6 +- src/scripting/thingdef_properties.cpp | 69 ----------------- src/scripting/zscript/zcc_parser.cpp | 1 + wadsrc/static/zscript/actor.txt | 92 ++++++++++++++++++++--- 10 files changed, 101 insertions(+), 200 deletions(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index 747c1f9bf..b8097f549 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -623,12 +623,20 @@ DEFINE_ACTION_FUNCTION(DObject, MSTime) void *DObject::ScriptVar(FName field, PType *type) { - auto sym = dyn_cast(GetClass()->Symbols.FindSymbol(field, true)); + auto cls = GetClass(); + auto sym = dyn_cast(cls->Symbols.FindSymbol(field, true)); if (sym && (sym->Type == type || type == nullptr)) { - return (((char*)this) + sym->Offset); + if (!(sym->Flags & VARF_Meta)) + { + return (((char*)this) + sym->Offset); + } + else + { + return (cls->Meta + sym->Offset); + } } // This is only for internal use so I_Error is fine. - I_Error("Variable %s not found in %s\n", field.GetChars(), GetClass()->TypeName.GetChars()); + I_Error("Variable %s not found in %s\n", field.GetChars(), cls->TypeName.GetChars()); return nullptr; } diff --git a/src/info.cpp b/src/info.cpp index 2bba8afb4..0db6c7fbc 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -262,11 +262,6 @@ PClassActor::PClassActor() CameraHeight = INT_MIN; DropItems = NULL; - - DontHurtShooter = false; - ExplosionRadius = -1; - MeleeDamage = 0; - // Record this in the master list. AllActorClasses.Push(this); } @@ -330,14 +325,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->DropItems = DropItems; - newa->DontHurtShooter = DontHurtShooter; - newa->ExplosionRadius = ExplosionRadius; - newa->ExplosionDamage = ExplosionDamage; - newa->MeleeDamage = MeleeDamage; - newa->MeleeSound = MeleeSound; - newa->MissileName = MissileName; - newa->MissileHeight = MissileHeight; - newa->VisibleToPlayerClass = VisibleToPlayerClass; if (DamageFactors != NULL) diff --git a/src/info.h b/src/info.h index f0f0f6c3c..9e684f462 100644 --- a/src/info.h +++ b/src/info.h @@ -311,15 +311,6 @@ public: FString SourceLumpName; FIntCVar *distancecheck; - // Old Decorate compatibility stuff - bool DontHurtShooter; - int ExplosionRadius; - int ExplosionDamage; - int MeleeDamage; - FSoundID MeleeSound; - FName MissileName; - double MissileHeight; - // These are only valid for inventory items. TArray RestrictedToPlayerClass; TArray ForbiddenToPlayerClass; diff --git a/src/namedef.h b/src/namedef.h index df2841daa..196c41fd0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -400,6 +400,9 @@ xx(VisibleEndPitch) xx(Format) xx(PickupMsg) xx(Respawnable) +xx(ExplosionDamage) +xx(ExplosionRadius) +xx(DontHurtShooter) // Various actor names which are used internally xx(MapSpot) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 54a577e5b..1f6e6df7f 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -86,7 +86,6 @@ AActor *SingleActorFromTID(int tid, AActor *defactor); static FRandom pr_camissile ("CustomActorfire"); -static FRandom pr_camelee ("CustomMelee"); static FRandom pr_cabullet ("CustomBullet"); static FRandom pr_cajump ("CustomJump"); static FRandom pr_cwbullet ("CustomWpBullet"); @@ -924,86 +923,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CopyFriendliness) return 0; } -//========================================================================== -// -// Customizable attack functions which use actor parameters. -// -//========================================================================== -static void DoAttack (AActor *self, bool domelee, bool domissile, - int MeleeDamage, FSoundID MeleeSound, PClassActor *MissileType,double MissileHeight) -{ - if (self->target == NULL) return; - - A_FaceTarget (self); - if (domelee && MeleeDamage>0 && self->CheckMeleeRange ()) - { - int damage = pr_camelee.HitDice(MeleeDamage); - if (MeleeSound) S_Sound (self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - else if (domissile && MissileType != NULL) - { - // This seemingly senseless code is needed for proper aiming. - double add = MissileHeight + self->GetBobOffset() - 32; - self->AddZ(add); - AActor *missile = P_SpawnMissileXYZ (self->PosPlusZ(32.), self, self->target, MissileType, false); - self->AddZ(-add); - - if (missile) - { - // automatic handling of seeker missiles - if (missile->flags2&MF2_SEEKERMISSILE) - { - missile->tracer=self->target; - } - P_CheckMissileSpawn(missile, self->radius); - } - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - int MeleeDamage = self->GetClass()->MeleeDamage; - FSoundID MeleeSound = self->GetClass()->MeleeSound; - DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); - DoAttack(self, false, true, 0, 0, MissileType, self->GetClass()->MissileHeight); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - int MeleeDamage = self->GetClass()->MeleeDamage; - FSoundID MeleeSound = self->GetClass()->MeleeSound; - PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); - DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, self->GetClass()->MissileHeight); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BasicAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (melee_damage); - PARAM_SOUND (melee_sound); - PARAM_CLASS (missile_type, AActor); - PARAM_FLOAT (missile_height); - - if (missile_type != NULL) - { - DoAttack(self, true, true, melee_damage, melee_sound, missile_type, missile_height); - } - return 0; -} - //========================================================================== // // Custom sound functions. @@ -1261,9 +1180,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode) if (damage < 0) // get parameters from metadata { - damage = self->GetClass()->ExplosionDamage; - distance = self->GetClass()->ExplosionRadius; - flags = !self->GetClass()->DontHurtShooter; + damage = self->IntVar(NAME_ExplosionDamage); + distance = self->IntVar(NAME_ExplosionRadius); + flags = !self->BoolVar(NAME_DontHurtShooter); alert = false; } if (distance <= 0) distance = damage; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 88bb1d40a..40fa7e0c9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -328,13 +328,6 @@ DEFINE_FIELD(PClassActor, HowlSound) DEFINE_FIELD(PClassActor, BloodType) DEFINE_FIELD(PClassActor, BloodType2) DEFINE_FIELD(PClassActor, BloodType3) -DEFINE_FIELD(PClassActor, DontHurtShooter) -DEFINE_FIELD(PClassActor, ExplosionRadius) -DEFINE_FIELD(PClassActor, ExplosionDamage) -DEFINE_FIELD(PClassActor, MeleeDamage) -DEFINE_FIELD(PClassActor, MeleeSound) -DEFINE_FIELD(PClassActor, MissileName) -DEFINE_FIELD(PClassActor, MissileHeight) //========================================================================== // diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 5c5714ba3..8d220ec70 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -445,18 +445,18 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius")) { sc.MustGetNumber (); - bag.Info->ExplosionRadius = sc.Number; + defaults->IntVar(NAME_ExplosionRadius) = sc.Number; extra.bExplosive = true; } else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage")) { sc.MustGetNumber (); - bag.Info->ExplosionDamage = sc.Number; + defaults->IntVar(NAME_ExplosionDamage) = sc.Number; extra.bExplosive = true; } else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter")) { - bag.Info->DontHurtShooter = true; + defaults->BoolVar(NAME_DontHurtShooter) = true; } else if (def == DEF_Projectile && sc.Compare ("Damage")) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 09f6dcd95..0e34e2da4 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1001,35 +1001,6 @@ DEFINE_PROPERTY(hitobituary, S, Actor) static_cast(info)->HitObituary = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(donthurtshooter, 0, Actor) -{ - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->DontHurtShooter = true; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(explosionradius, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->ExplosionRadius = id; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(explosiondamage, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->ExplosionDamage = id; -} - //========================================================================== // //========================================================================== @@ -1068,16 +1039,6 @@ DEFINE_PROPERTY(meleethreshold, F, Actor) defaults->meleethreshold = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(meleedamage, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MeleeDamage = id; -} - //========================================================================== // //========================================================================== @@ -1087,36 +1048,6 @@ DEFINE_PROPERTY(meleerange, F, Actor) defaults->meleerange = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(meleesound, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MeleeSound = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(missiletype, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MissileName = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(missileheight, F, Actor) -{ - PROP_DOUBLE_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MissileHeight = id; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 501a7b2ea..439b495b4 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -281,6 +281,7 @@ static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCPar tokentype = ZCC_FLOATCONST; break; + case TK_None: // 'NONE' is a token for SBARINFO but not here. case TK_Identifier: value.Int = FName(sc.String); tokentype = ZCC_IDENTIFIER; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 99c23c7bf..6a12e00f8 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -189,7 +189,7 @@ class Actor : Thinker native native State MissileState; native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; - + native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee native meta double DeathHeight; // Height on normal death @@ -204,15 +204,24 @@ class Actor : Thinker native native meta Name BloodType; // Blood replacement type native meta Name BloodType2; // Bloopsplatter replacement type native meta Name BloodType3; // AxeBlood replacement type - native meta bool DontHurtShooter; - native meta int ExplosionRadius; - native meta int ExplosionDamage; - native meta int MeleeDamage; - native meta Sound MeleeSound; - native meta Name MissileName; - native meta double MissileHeight; + meta bool DontHurtShooter; + meta int ExplosionRadius; + meta int ExplosionDamage; + meta int MeleeDamage; + meta Sound MeleeSound; + meta double MissileHeight; + meta Name MissileName; + Property prefix: none; + Property MeleeDamage: MeleeDamage; + Property MeleeSound: MeleeSound; + Property MissileHeight: MissileHeight; + Property MissileType: MissileName; + Property DontHurtShooter: DontHurtShooter; + Property ExplosionRadius: ExplosionRadius; + Property ExplosionDamage: ExplosionDamage; + // need some definition work first //FRenderStyle RenderStyle; //int ConversationRoot; // THe root of the current dialogue @@ -271,6 +280,7 @@ class Actor : Thinker native DefThreshold 100; BloodType "Blood", "BloodSplatter", "AxeBlood"; ExplosionDamage 128; + ExplosionRadius -1; // i.e. use ExplosionDamage value MissileHeight 32; SpriteAngle 0; SpriteRotation 0; @@ -724,6 +734,68 @@ class Actor : Thinker native // Meh, MBF redundant functions. Only for DeHackEd support. native bool A_LineEffect(int boomspecial = 0, int tag = 0); // End of MBF redundant functions. + + + //========================================================================== + // + // old customizable attack functions which use actor parameters. + // + //========================================================================== + + private void DoAttack (bool domelee, bool domissile, int MeleeDamage, Sound MeleeSound, Class MissileType,double MissileHeight) + { + if (target == NULL) return; + + A_FaceTarget (); + if (domelee && MeleeDamage>0 && CheckMeleeRange ()) + { + int damage = random[CustomMelee](1, 8) * MeleeDamage; + if (MeleeSound) A_PlaySound (MeleeSound, CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + else if (domissile && MissileType != NULL) + { + // This seemingly senseless code is needed for proper aiming. + double add = MissileHeight + GetBobOffset() - 32; + AddZ(add); + Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), target, MissileType, false); + AddZ(-add); + + if (missile) + { + // automatic handling of seeker missiles + if (missile.bSeekerMissile) + { + missile.tracer = target; + } + missile.CheckMissileSpawn(radius); + } + } + } + + deprecated void A_MeleeAttack() + { + DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0); + } + + deprecated void A_MissileAttack() + { + Class MissileType = MissileName; + DoAttack(false, true, 0, 0, MissileType, MissileHeight); + } + + deprecated void A_ComboAttack() + { + Class MissileType = MissileName; + DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); + } + + void A_BasicAttack(int melee_damage, sound melee_sound, class missile_type, double missile_height) + { + DoAttack(true, true, melee_damage, melee_sound, missile_type, missile_height); + } + native void A_MonsterRail(); native void A_Pain(); @@ -753,9 +825,6 @@ class Actor : Thinker native native void A_Wander(int flags = 0); native void A_Look2(); - deprecated native void A_MissileAttack(); - deprecated native void A_MeleeAttack(); - deprecated native void A_ComboAttack(); deprecated native void A_BulletAttack(); native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class pufftype = "BulletPuff"); native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false); @@ -793,7 +862,6 @@ class Actor : Thinker native native void A_RaiseMaster(int flags = 0); native void A_RaiseChildren(int flags = 0); native void A_RaiseSiblings(int flags = 0); - deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, double missileheight); action native bool, Actor A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, double xdist, double ydist); native bool A_Morph(class type, int duration = 0, int flags = 0, class enter_flash = null, class exit_flash = null); From 1311f08f4714138fb1bfa837a91672760f77d944 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:11:25 +0100 Subject: [PATCH 21/48] - scriptified Actor.GetBloodType as a virtual function to allow mods more flexibility here. - made CameraHeight a modifiable actor property - it was readonly before. - allow accessing the type constants from ZScript, this required quite a bit of explicit coding because the type system has no capabilities to search for basic types by name. --- src/actor.h | 30 +--------- src/dobjtype.cpp | 4 -- src/info.cpp | 5 -- src/info.h | 4 -- src/p_mobj.cpp | 21 +++++-- src/scripting/backend/codegen.cpp | 80 ++++++++++++++++++++++++--- src/scripting/thingdef_properties.cpp | 34 +----------- wadsrc/static/zscript/actor.txt | 43 +++++++++++--- 8 files changed, 129 insertions(+), 92 deletions(-) diff --git a/src/actor.h b/src/actor.h index 2ed004740..6e64b6033 100644 --- a/src/actor.h +++ b/src/actor.h @@ -817,32 +817,7 @@ public: void SetAngle(DAngle ang, bool interpolate); void SetRoll(DAngle roll, bool interpolate); - PClassActor *GetBloodType(int type = 0) const - { - PClassActor *bloodcls; - if (type == 0) - { - bloodcls = PClass::FindActor(GetClass()->BloodType); - } - else if (type == 1) - { - bloodcls = PClass::FindActor(GetClass()->BloodType2); - } - else if (type == 2) - { - bloodcls = PClass::FindActor(GetClass()->BloodType3); - } - else - { - return NULL; - } - - if (bloodcls != NULL) - { - bloodcls = bloodcls->GetReplacement(); - } - return bloodcls; - } + PClassActor *GetBloodType(int type = 0) const; double Distance2DSquared(AActor *other, bool absolute = false) { @@ -1048,7 +1023,8 @@ public: double renderradius; double projectilepassheight; // height for clipping projectile movement against this actor - + double CameraHeight; // Height of camera when used as such + SDWORD tics; // state tic counter FState *state; //VMFunction *Damage; // For missiles and monster railgun diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1d5cd1512..f86797dfd 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -722,10 +722,6 @@ PBool::PBool() { mDescriptiveName = "Bool"; MemberOnly = false; - // Override the default max set by PInt's constructor - PSymbolConstNumeric *maxsym = static_cast(Symbols.FindSymbol(NAME_Max, false)); - assert(maxsym != nullptr && maxsym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); - maxsym->Value = 1; } /* PFloat *****************************************************************/ diff --git a/src/info.cpp b/src/info.cpp index 0db6c7fbc..6f9b95f36 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -259,7 +259,6 @@ PClassActor::PClassActor() RDFactor = 1.; SelfDamageFactor = 1.; StealthAlpha = 0.; - CameraHeight = INT_MIN; DropItems = NULL; // Record this in the master list. @@ -316,11 +315,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->RDFactor = RDFactor; newa->SelfDamageFactor = SelfDamageFactor; newa->StealthAlpha = StealthAlpha; - newa->CameraHeight = CameraHeight; newa->HowlSound = HowlSound; - newa->BloodType = BloodType; - newa->BloodType2 = BloodType2; - newa->BloodType3 = BloodType3; newa->distancecheck = distancecheck; newa->DropItems = DropItems; diff --git a/src/info.h b/src/info.h index 9e684f462..fd8914546 100644 --- a/src/info.h +++ b/src/info.h @@ -300,12 +300,8 @@ public: double FastSpeed; // speed in fast mode double RDFactor; // Radius damage factor double SelfDamageFactor; - double CameraHeight; // Height of camera when used as such double StealthAlpha; // Minmum alpha for MF_STEALTH. FSoundID HowlSound; // Sound being played when electrocuted or poisoned - FName BloodType; // Blood replacement type - FName BloodType2; // Bloopsplatter replacement type - FName BloodType3; // AxeBlood replacement type FDropItem *DropItems; FString SourceLumpName; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 40fa7e0c9..d95bae5b2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -311,6 +311,7 @@ DEFINE_FIELD(AActor, ConversationRoot) DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) DEFINE_FIELD(AActor, fountaincolor) +DEFINE_FIELD(AActor, CameraHeight) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -323,11 +324,7 @@ DEFINE_FIELD(PClassActor, FastSpeed) DEFINE_FIELD(PClassActor, RDFactor) DEFINE_FIELD(PClassActor, SelfDamageFactor) DEFINE_FIELD(PClassActor, StealthAlpha) -DEFINE_FIELD(PClassActor, CameraHeight) DEFINE_FIELD(PClassActor, HowlSound) -DEFINE_FIELD(PClassActor, BloodType) -DEFINE_FIELD(PClassActor, BloodType2) -DEFINE_FIELD(PClassActor, BloodType3) //========================================================================== // @@ -488,6 +485,7 @@ void AActor::Serialize(FSerializer &arc) A("spriteangle", SpriteAngle) A("spriterotation", SpriteRotation) ("alternative", alternative) + A("cameraheight", CameraHeight) A("tag", Tag) A("visiblestartangle",VisibleStartAngle) A("visibleendangle",VisibleEndAngle) @@ -3816,6 +3814,19 @@ void AActor::SetRoll(DAngle r, bool interpolate) } } +PClassActor *AActor::GetBloodType(int type) const +{ + IFVIRTUAL(AActor, GetBloodType) + { + VMValue params[] = { (DObject*)this, type }; + PClassActor *res; + VMReturn ret((void**)&res); + GlobalVMStack.Call(func, params, countof(params), &ret, 1); + return res; + } + return nullptr; +} + DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) { @@ -7593,7 +7604,7 @@ int AActor::GetGibHealth() const double AActor::GetCameraHeight() const { - return GetClass()->CameraHeight == INT_MIN ? Height / 2 : GetClass()->CameraHeight; + return CameraHeight == INT_MIN ? Height / 2 : CameraHeight; } DEFINE_ACTION_FUNCTION(AActor, GetCameraHeight) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index bd18103fc..893a50eed 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6088,19 +6088,85 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) if (Object->ExprType == EFX_Identifier) { + auto id = static_cast(Object)->Identifier; // If the left side is a class name for a static member function call it needs to be resolved manually // because the resulting value type would cause problems in nearly every other place where identifiers are being used. - ccls = FindStructType(static_cast(Object)->Identifier, ctx); - if (ccls != nullptr) static_cast(Object)->noglobal = true; + ccls = FindStructType(id, ctx); + if (ccls != nullptr) + { + static_cast(Object)->noglobal = true; + } + else + { + PType *type; + // Another special case to deal with here is constants assigned to non-struct types. The code below cannot deal with them so it needs to be done here explicitly. + // Thanks to the messed up search logic of the type system, which doesn't allow any search by type name for the basic types at all, + // we have to do this manually, though and check for all types that may have values attached explicitly. + // (What's the point of attached fields to types if you cannot even search for the types...???) + switch (id) + { + default: + type = nullptr; + break; + + case NAME_Byte: + case NAME_uint8: + type = TypeUInt8; + break; + + case NAME_sByte: + case NAME_int8: + type = TypeSInt8; + break; + + case NAME_uShort: + case NAME_uint16: + type = TypeUInt16; + break; + + case NAME_Short: + case NAME_int16: + type = TypeSInt16; + break; + + case NAME_Int: + type = TypeSInt32; + break; + + case NAME_uInt: + type = TypeUInt32; + break; + + case NAME_Float: + type = TypeFloat32; + break; + + case NAME_Double: + type = TypeFloat64; + break; + } + if (type != nullptr) + { + auto sym = type->Symbols.FindSymbol(Identifier, true); + if (sym != nullptr) + { + // non-struct symbols must be constant numbers and can only be defined internally. + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); + auto sn = static_cast(sym); + + VMValue vmv; + if (sn->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) vmv = sn->Value; + else vmv = sn->Float; + auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + } + } } SAFE_RESOLVE(Object, ctx); - if (Identifier == FName("allmap")) - { - int a = 2; - } - // check for class or struct constants if the left side is a type name. if (Object->ValueType == TypeError) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 0e34e2da4..3838c3a89 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1121,37 +1121,6 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(bloodtype, Sss, Actor) -{ - PROP_STRING_PARM(str, 0) - PROP_STRING_PARM(str1, 1) - PROP_STRING_PARM(str2, 2) - - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - PClassActor *ainfo = static_cast(info); - - FName blood = str; - // normal blood - ainfo->BloodType = blood; - - if (PROP_PARM_COUNT > 1) - { - blood = str1; - } - // blood splatter - ainfo->BloodType2 = blood; - - if (PROP_PARM_COUNT > 2) - { - blood = str2; - } - // axe blood - ainfo->BloodType3 = blood; -} - //========================================================================== // //========================================================================== @@ -1387,8 +1356,7 @@ DEFINE_PROPERTY(stealthalpha, F, Actor) DEFINE_PROPERTY(cameraheight, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->CameraHeight = i; + defaults->CameraHeight = i; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 6a12e00f8..9796c3e8d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -189,6 +189,7 @@ class Actor : Thinker native native State MissileState; native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; + native double CameraHeight; // Height of camera when used as such native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee @@ -199,12 +200,11 @@ class Actor : Thinker native native meta int WoundHealth; // Health needed to enter wound state native meta double FastSpeed; // speed in fast mode native meta double RDFactor; // Radius damage factor - native meta double CameraHeight; // Height of camera when used as such native meta Sound HowlSound; // Sound being played when electrocuted or poisoned - native meta Name BloodType; // Blood replacement type - native meta Name BloodType2; // Bloopsplatter replacement type - native meta Name BloodType3; // AxeBlood replacement type - + + meta Name BloodType; // Blood replacement type + meta Name BloodType2; // Bloopsplatter replacement type + meta Name BloodType3; // AxeBlood replacement type meta bool DontHurtShooter; meta int ExplosionRadius; meta int ExplosionDamage; @@ -221,6 +221,7 @@ class Actor : Thinker native Property DontHurtShooter: DontHurtShooter; Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; + Property BloodType: BloodType, BloodType2, BloodType3; // need some definition work first //FRenderStyle RenderStyle; @@ -248,7 +249,7 @@ class Actor : Thinker native Health DEFAULT_HEALTH; Reactiontime 8; Radius 20; - RenderRadius 0; + RenderRadius 0; Height 16; Mass 100; RenderStyle 'Normal'; @@ -288,6 +289,7 @@ class Actor : Thinker native VisibleAngles 0, 0; VisiblePitch 0, 0; DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; + CameraHeight int.min; } // Functions @@ -320,7 +322,7 @@ class Actor : Thinker native virtual native void Touch(Actor toucher); virtual native void MarkPrecacheSounds(); - // Called by PIT_CheckThing to check if two actos actually can collide. + // Called by PIT_CheckThing to check if two actors actually can collide. virtual bool CanCollideWith(Actor other, bool passive) { return true; @@ -344,6 +346,33 @@ class Actor : Thinker native { return false; } + + virtual class GetBloodType(int type) + { + Class bloodcls; + if (type == 0) + { + bloodcls = BloodType; + } + else if (type == 1) + { + bloodcls = BloodType2; + } + else if (type == 2) + { + bloodcls = BloodType3; + } + else + { + return NULL; + } + + if (bloodcls != NULL) + { + bloodcls = GetReplacement(bloodcls); + } + return bloodcls; + } native static class GetReplacement(class cls); native static class GetReplacee(class cls); From 2a4a5e7a7064c615b5d9a68e4805e999e047fba4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:47:44 +0100 Subject: [PATCH 22/48] - refactored a few more native meta properties. --- src/actor.h | 4 +++ src/info.cpp | 8 ------ src/info.h | 4 --- src/namedef.h | 1 + src/p_interaction.cpp | 2 +- src/p_map.cpp | 4 +-- src/p_mobj.cpp | 36 +++++++++++++++++---------- src/scripting/thingdef_properties.cpp | 19 +++----------- wadsrc/static/zscript/actor.txt | 12 +++++++-- 9 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6e64b6033..e7d84f09d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1025,6 +1025,10 @@ public: double projectilepassheight; // height for clipping projectile movement against this actor double CameraHeight; // Height of camera when used as such + double RadiusDamageFactor; // Radius damage factor + double SelfDamageFactor; + double StealthAlpha; // Minmum alpha for MF_STEALTH. + SDWORD tics; // state tic counter FState *state; //VMFunction *Damage; // For missiles and monster railgun diff --git a/src/info.cpp b/src/info.cpp index 6f9b95f36..b8abba976 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -255,10 +255,6 @@ PClassActor::PClassActor() BurnHeight = -1; GibHealth = INT_MIN; WoundHealth = 6; - FastSpeed = -1.; - RDFactor = 1.; - SelfDamageFactor = 1.; - StealthAlpha = 0.; DropItems = NULL; // Record this in the master list. @@ -311,10 +307,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->BloodColor = BloodColor; newa->GibHealth = GibHealth; newa->WoundHealth = WoundHealth; - newa->FastSpeed = FastSpeed; - newa->RDFactor = RDFactor; - newa->SelfDamageFactor = SelfDamageFactor; - newa->StealthAlpha = StealthAlpha; newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index fd8914546..f2a6101e9 100644 --- a/src/info.h +++ b/src/info.h @@ -297,10 +297,6 @@ public: PalEntry BloodColor; // Colorized blood int GibHealth; // Negative health below which this monster dies an extreme death int WoundHealth; // Health needed to enter wound state - double FastSpeed; // speed in fast mode - double RDFactor; // Radius damage factor - double SelfDamageFactor; - double StealthAlpha; // Minmum alpha for MF_STEALTH. FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; diff --git a/src/namedef.h b/src/namedef.h index 196c41fd0..7c63eb785 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -392,6 +392,7 @@ xx(Radius) xx(ReactionTime) xx(MeleeRange) xx(Speed) +xx(FastSpeed) xx(Clamp) xx(VisibleStartAngle) xx(VisibleStartPitch) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 4c23c8123..2af2a3da1 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1022,7 +1022,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da } if (target == source && damage < TELEFRAG_DAMAGE) { - damage = int(damage * target->GetClass()->SelfDamageFactor); + damage = int(damage * target->SelfDamageFactor); } // [MC] Changed it to check rawdamage here for consistency, even though that doesn't actually do anything diff --git a/src/p_map.cpp b/src/p_map.cpp index 70b18df7f..7e110dcbf 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -5680,7 +5680,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom { points = points * splashfactor; } - points *= thing->GetClass()->RDFactor; + points *= thing->RadiusDamageFactor; double check = int(points) * bombdamage; // points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.) @@ -5759,7 +5759,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom dist = clamp(dist - fulldamagedistance, 0, dist); int damage = Scale(bombdamage, bombdistance - int(dist), bombdistance); - double factor = splashfactor * thing->GetClass()->RDFactor; + double factor = splashfactor * thing->RadiusDamageFactor; damage = int(damage * factor); if (damage > 0 || (bombspot->flags7 & MF7_FORCEZERORADIUSDMG)) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d95bae5b2..9ccdde24e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -312,6 +312,9 @@ DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) DEFINE_FIELD(AActor, fountaincolor) DEFINE_FIELD(AActor, CameraHeight) +DEFINE_FIELD(AActor, RadiusDamageFactor) +DEFINE_FIELD(AActor, SelfDamageFactor) +DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -320,10 +323,6 @@ DEFINE_FIELD(PClassActor, BurnHeight) DEFINE_FIELD(PClassActor, BloodColor) DEFINE_FIELD(PClassActor, GibHealth) DEFINE_FIELD(PClassActor, WoundHealth) -DEFINE_FIELD(PClassActor, FastSpeed) -DEFINE_FIELD(PClassActor, RDFactor) -DEFINE_FIELD(PClassActor, SelfDamageFactor) -DEFINE_FIELD(PClassActor, StealthAlpha) DEFINE_FIELD(PClassActor, HowlSound) //========================================================================== @@ -490,7 +489,11 @@ void AActor::Serialize(FSerializer &arc) A("visiblestartangle",VisibleStartAngle) A("visibleendangle",VisibleEndAngle) A("visiblestartpitch",VisibleStartPitch) - A("visibleendpitch",VisibleEndPitch); + A("visibleendpitch",VisibleEndPitch) + A("rdfactor", RadiusDamageFactor) + A("selfdamagefactor", SelfDamageFactor) + A("stealthalpha", StealthAlpha); + } #undef A @@ -4105,9 +4108,9 @@ void AActor::Tick () else if (visdir < 0) { Alpha -= 1.5/TICRATE; - if (Alpha < GetClass()->StealthAlpha) + if (Alpha < StealthAlpha) { - Alpha = GetClass()->StealthAlpha; + Alpha = StealthAlpha; visdir = 0; } } @@ -4828,8 +4831,11 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright()); actor->touching_sectorlist = nullptr; // NULL head of sector list // phares 3/13/98 actor->touching_rendersectors = nullptr; - if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) - actor->Speed = actor->GetClass()->FastSpeed; + if (G_SkillProperty(SKILLP_FastMonsters)) + { + double f = actor->FloatVar(NAME_FastSpeed); + if (f >= 0) actor->Speed = f; + } // set subsector and/or block links actor->LinkToWorld (nullptr, SpawningMapThing); @@ -6701,10 +6707,14 @@ static double GetDefaultSpeed(PClassActor *type) { if (type == NULL) return 0; - else if (G_SkillProperty(SKILLP_FastMonsters) && type->FastSpeed >= 0) - return type->FastSpeed; - else - return GetDefaultByType(type)->Speed; + + auto def = GetDefaultByType(type); + if (G_SkillProperty(SKILLP_FastMonsters)) + { + double f = def->FloatVar(NAME_FastSpeed); + if (f >= 0) return f; + } + return def->Speed; } DEFINE_ACTION_FUNCTION(AActor, GetDefaultSpeed) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 3838c3a89..a6657ce97 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1310,24 +1310,13 @@ DEFINE_PROPERTY(poisondamagetype, S, Actor) defaults->PoisonDamageType = poisondamagetype; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(fastspeed, F, Actor) -{ - PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->FastSpeed = i; -} - //========================================================================== // //========================================================================== DEFINE_PROPERTY(radiusdamagefactor, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->RDFactor = i; + defaults->RadiusDamageFactor = i; } //========================================================================== @@ -1336,8 +1325,7 @@ DEFINE_PROPERTY(radiusdamagefactor, F, Actor) DEFINE_PROPERTY(selfdamagefactor, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->SelfDamageFactor = i; + defaults->SelfDamageFactor = i; } //========================================================================== @@ -1346,8 +1334,7 @@ DEFINE_PROPERTY(selfdamagefactor, F, Actor) DEFINE_PROPERTY(stealthalpha, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->StealthAlpha = i; + defaults->StealthAlpha = i; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9796c3e8d..2fc0d6d3b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -190,6 +190,9 @@ class Actor : Thinker native native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; native double CameraHeight; // Height of camera when used as such + native double RadiusDamageFactor; // Radius damage factor + native double SelfDamageFactor; + native double StealthAlpha; native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee @@ -198,8 +201,6 @@ class Actor : Thinker native native meta color BloodColor; // Colorized blood native meta int GibHealth; // Negative health below which this monster dies an extreme death native meta int WoundHealth; // Health needed to enter wound state - native meta double FastSpeed; // speed in fast mode - native meta double RDFactor; // Radius damage factor native meta Sound HowlSound; // Sound being played when electrocuted or poisoned meta Name BloodType; // Blood replacement type @@ -212,6 +213,7 @@ class Actor : Thinker native meta Sound MeleeSound; meta double MissileHeight; meta Name MissileName; + meta double FastSpeed; // speed in fast mode Property prefix: none; Property MeleeDamage: MeleeDamage; @@ -222,6 +224,7 @@ class Actor : Thinker native Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; Property BloodType: BloodType, BloodType2, BloodType3; + Property FastSpeed: FastSpeed; // need some definition work first //FRenderStyle RenderStyle; @@ -290,6 +293,11 @@ class Actor : Thinker native VisiblePitch 0, 0; DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; CameraHeight int.min; + FastSpeed -1; + RadiusDamageFactor 1; + SelfDamageFactor 1; + StealthAlpha 0; + } // Functions From d5250d6b9f87af047214926e4c8f7ac14cb65032 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:56:35 +0100 Subject: [PATCH 23/48] - made WoundHealth modifiable to allow more control over the wound state. --- src/actor.h | 1 + src/info.cpp | 2 -- src/info.h | 1 - src/p_interaction.cpp | 2 +- src/p_mobj.cpp | 3 ++- src/scripting/thingdef_properties.cpp | 3 +-- wadsrc/static/zscript/actor.txt | 2 ++ 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/actor.h b/src/actor.h index e7d84f09d..739f08f4a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1028,6 +1028,7 @@ public: double RadiusDamageFactor; // Radius damage factor double SelfDamageFactor; double StealthAlpha; // Minmum alpha for MF_STEALTH. + int WoundHealth; // Health needed to enter wound state SDWORD tics; // state tic counter FState *state; diff --git a/src/info.cpp b/src/info.cpp index b8abba976..d81d4d874 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -254,7 +254,6 @@ PClassActor::PClassActor() DeathHeight = -1; BurnHeight = -1; GibHealth = INT_MIN; - WoundHealth = 6; DropItems = NULL; // Record this in the master list. @@ -306,7 +305,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->BurnHeight = BurnHeight; newa->BloodColor = BloodColor; newa->GibHealth = GibHealth; - newa->WoundHealth = WoundHealth; newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index f2a6101e9..28a684281 100644 --- a/src/info.h +++ b/src/info.h @@ -296,7 +296,6 @@ public: double BurnHeight; // Height on burning death PalEntry BloodColor; // Colorized blood int GibHealth; // Negative health below which this monster dies an extreme death - int WoundHealth; // Health needed to enter wound state FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 2af2a3da1..da60af8ad 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1536,7 +1536,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da woundstate = target->FindState(NAME_Wound, mod); if (woundstate != NULL) { - int woundhealth = target->GetClass()->WoundHealth; + int woundhealth = target->WoundHealth; if (target->health <= woundhealth) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9ccdde24e..22cbe1e3f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -315,6 +315,7 @@ DEFINE_FIELD(AActor, CameraHeight) DEFINE_FIELD(AActor, RadiusDamageFactor) DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) +DEFINE_FIELD(AActor, WoundHealth) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -322,7 +323,6 @@ DEFINE_FIELD(PClassActor, DeathHeight) DEFINE_FIELD(PClassActor, BurnHeight) DEFINE_FIELD(PClassActor, BloodColor) DEFINE_FIELD(PClassActor, GibHealth) -DEFINE_FIELD(PClassActor, WoundHealth) DEFINE_FIELD(PClassActor, HowlSound) //========================================================================== @@ -490,6 +490,7 @@ void AActor::Serialize(FSerializer &arc) A("visibleendangle",VisibleEndAngle) A("visiblestartpitch",VisibleStartPitch) A("visibleendpitch",VisibleEndPitch) + A("woundhealth", WoundHealth) A("rdfactor", RadiusDamageFactor) A("selfdamagefactor", SelfDamageFactor) A("stealthalpha", StealthAlpha); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index a6657ce97..a70fa0c9e 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -608,8 +608,7 @@ DEFINE_PROPERTY(gibhealth, I, Actor) DEFINE_PROPERTY(woundhealth, I, Actor) { PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->WoundHealth = id; + defaults->WoundHealth = id; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2fc0d6d3b..4fa2323b0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -297,6 +297,8 @@ class Actor : Thinker native RadiusDamageFactor 1; SelfDamageFactor 1; StealthAlpha 0; + WoundHealth 6; + } From 851984efe0649bda9583ecc834d948c1c241a9f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 13:40:46 +0100 Subject: [PATCH 24/48] - made GetDeathHeight a virtual scripted function. - made GetGibHealth a virtual scripted function. - removed a few more native meta properties. --- src/dobject.h | 2 + src/dobjtype.h | 5 ++ src/gi.cpp | 1 + src/info.cpp | 8 ---- src/info.h | 4 -- src/namedef.h | 1 + src/p_acs.cpp | 4 +- src/p_actionfunctions.cpp | 16 ------- src/p_interaction.cpp | 20 ++------ src/p_mobj.cpp | 32 ++++++------- src/scripting/decorate/olddecorations.cpp | 4 +- src/scripting/thingdef_properties.cpp | 40 ---------------- wadsrc/static/zscript/actor.txt | 57 +++++++++++++++++++---- wadsrc/static/zscript/base.txt | 1 + 14 files changed, 80 insertions(+), 115 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 7510a4cff..d99fbee2b 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -41,6 +41,7 @@ class PClass; class PType; class FSerializer; +class FSoundID; class DObject; /* @@ -483,6 +484,7 @@ public: // Add other types as needed. bool &BoolVar(FName field); int &IntVar(FName field); + FSoundID &SoundVar(FName field); PalEntry &ColorVar(FName field); FName &NameVar(FName field); double &FloatVar(FName field); diff --git a/src/dobjtype.h b/src/dobjtype.h index 76e17b133..f589b4e48 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -728,6 +728,11 @@ inline int &DObject::IntVar(FName field) return *(int*)ScriptVar(field, TypeSInt32); } +inline FSoundID &DObject::SoundVar(FName field) +{ + return *(FSoundID*)ScriptVar(field, TypeSound); +} + inline PalEntry &DObject::ColorVar(FName field) { return *(PalEntry*)ScriptVar(field, TypeColor); diff --git a/src/gi.cpp b/src/gi.cpp index 672ca3263..ad5c5a0ee 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -56,6 +56,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mBackButton) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenMapNameFont) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenEnteringFont) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenFinishedFont) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gibfactor) const char *GameNames[17] = diff --git a/src/info.cpp b/src/info.cpp index d81d4d874..76ba0fbcb 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -251,10 +251,6 @@ PClassActor::PClassActor() DamageFactors = NULL; PainChances = NULL; - DeathHeight = -1; - BurnHeight = -1; - GibHealth = INT_MIN; - DropItems = NULL; // Record this in the master list. AllActorClasses.Push(this); @@ -301,11 +297,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->DefaultStateUsage = DefaultStateUsage; newa->Obituary = Obituary; newa->HitObituary = HitObituary; - newa->DeathHeight = DeathHeight; - newa->BurnHeight = BurnHeight; newa->BloodColor = BloodColor; - newa->GibHealth = GibHealth; - newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; newa->DropItems = DropItems; diff --git a/src/info.h b/src/info.h index 28a684281..cd21deac4 100644 --- a/src/info.h +++ b/src/info.h @@ -292,11 +292,7 @@ public: FString Obituary; // Player was killed by this actor FString HitObituary; // Player was killed by this actor in melee - double DeathHeight; // Height on normal death - double BurnHeight; // Height on burning death PalEntry BloodColor; // Colorized blood - int GibHealth; // Negative health below which this monster dies an extreme death - FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; FString SourceLumpName; diff --git a/src/namedef.h b/src/namedef.h index 7c63eb785..50bde739f 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -393,6 +393,7 @@ xx(ReactionTime) xx(MeleeRange) xx(Speed) xx(FastSpeed) +xx(HowlSound) xx(Clamp) xx(VisibleStartAngle) xx(VisibleStartPitch) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index baf15c110..6053ce85a 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4232,7 +4232,7 @@ enum SOUND_Howl, }; -static FSoundID GetActorSound(const AActor *actor, int soundtype) +static FSoundID GetActorSound(AActor *actor, int soundtype) { switch (soundtype) { @@ -4245,7 +4245,7 @@ static FSoundID GetActorSound(const AActor *actor, int soundtype) case SOUND_Bounce: return actor->BounceSound; case SOUND_WallBounce: return actor->WallBounceSound; case SOUND_CrushPain: return actor->CrushPainSound; - case SOUND_Howl: return actor->GetClass()->HowlSound; + case SOUND_Howl: return actor->SoundVar(NAME_HowlSound); default: return 0; } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 1f6e6df7f..b75949f01 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -438,22 +438,6 @@ DEFINE_ACTION_FUNCTION(AActor, GetSpawnHealth) return 0; } -//========================================================================== -// -// GetGibHealth -// -//========================================================================== -DEFINE_ACTION_FUNCTION(AActor, GetGibHealth) -{ - if (numret > 0) - { - PARAM_SELF_PROLOGUE(AActor); - ret->SetInt(self->GetGibHealth()); - return 1; - } - return 0; -} - //========================================================================== // // GetSpriteAngle diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index da60af8ad..9d8d63de0 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -411,23 +411,11 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) } flags6 |= MF6_KILLED; - // [RH] Allow the death height to be overridden using metadata. - double metaheight = -1; - if (DamageType == NAME_Fire) + IFVIRTUAL(AActor, GetDeathHeight) { - metaheight = GetClass()->BurnHeight; - } - if (metaheight < 0) - { - metaheight = GetClass()->DeathHeight; - } - if (metaheight < 0) - { - Height *= 0.25; - } - else - { - Height = MAX (metaheight, 0); + VMValue params[] = { (DObject*)this }; + VMReturn ret(&Height); + GlobalVMStack.Call(func, params, 1, &ret, 1); } // [RH] If the thing has a special, execute and remove it diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 22cbe1e3f..bc432434c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -319,11 +319,7 @@ DEFINE_FIELD(AActor, WoundHealth) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) -DEFINE_FIELD(PClassActor, DeathHeight) -DEFINE_FIELD(PClassActor, BurnHeight) -DEFINE_FIELD(PClassActor, BloodColor) -DEFINE_FIELD(PClassActor, GibHealth) -DEFINE_FIELD(PClassActor, HowlSound) +//DEFINE_FIELD(PClassActor, BloodColor) //========================================================================== // @@ -3516,7 +3512,7 @@ int AActor::GetMissileDamage (int mask, int add) void AActor::Howl () { - FSoundID howl = GetClass()->HowlSound; + FSoundID howl = IntVar(NAME_HowlSound); if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl)) { S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM); @@ -7481,9 +7477,10 @@ void AActor::Crash() { FState *crashstate = NULL; + int gibh = GetGibHealth(); if (DamageType != NAME_None) { - if (health < GetGibHealth()) + if (health < gibh) { // Extreme death FName labels[] = { NAME_Crash, NAME_Extreme, DamageType }; crashstate = FindState (3, labels, true); @@ -7495,7 +7492,7 @@ void AActor::Crash() } if (crashstate == NULL) { - if (health < GetGibHealth()) + if (health < gibh) { // Extreme death crashstate = FindState(NAME_Crash, NAME_Extreme); } @@ -7601,16 +7598,15 @@ void AActor::Revive() int AActor::GetGibHealth() const { - int gibhealth = GetClass()->GibHealth; - - if (gibhealth != INT_MIN) + IFVIRTUAL(AActor, GetGibHealth) { - return -abs(gibhealth); - } - else - { - return -int(SpawnHealth() * gameinfo.gibfactor); + VMValue params[] = { (DObject*)this }; + int h; + VMReturn ret(&h); + GlobalVMStack.Call(func, params, 1, &ret, 1); + return h; } + return -SpawnHealth(); } double AActor::GetCameraHeight() const @@ -8294,9 +8290,9 @@ void PrintMiscActorInfo(AActor *query) query->args[0], query->args[1], query->args[2], query->args[3], query->args[4], query->special1, query->special2); Printf("\nTID: %d", query->tid); - Printf("\nCoord= x: %f, y: %f, z:%f, floor:%f, ceiling:%f.", + Printf("\nCoord= x: %f, y: %f, z:%f, floor:%f, ceiling:%f, height= %f", query->X(), query->Y(), query->Z(), - query->floorz, query->ceilingz); + query->floorz, query->ceilingz, query->Height); Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n", query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length()); Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y); diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 8d220ec70..7370ddb54 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -223,7 +223,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns) { extra.DeathHeight = ((AActor*)(type->Defaults))->Height; } - type->DeathHeight = extra.DeathHeight; + ((AActor*)(type->Defaults))->FloatVar("DeathHeight") = extra.DeathHeight; } bag.statedef.SetStateLabel("Death", &type->OwnedStates[extra.DeathStart]); } @@ -262,7 +262,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns) } if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->Height; - type->BurnHeight = extra.BurnHeight; + ((AActor*)(type->Defaults))->FloatVar("BurnHeight") = extra.BurnHeight; bag.statedef.SetStateLabel("Burn", &type->OwnedStates[extra.FireDeathStart]); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index a70fa0c9e..e588b452c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -592,16 +592,6 @@ DEFINE_PROPERTY(health, I, Actor) defaults->health=id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(gibhealth, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->GibHealth = id; -} - //========================================================================== // //========================================================================== @@ -887,16 +877,6 @@ DEFINE_PROPERTY(activesound, S, Actor) defaults->ActiveSound = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(howlsound, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->HowlSound = str; -} - //========================================================================== // //========================================================================== @@ -1000,26 +980,6 @@ DEFINE_PROPERTY(hitobituary, S, Actor) static_cast(info)->HitObituary = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(deathheight, F, Actor) -{ - PROP_DOUBLE_PARM(h, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->DeathHeight = MAX(0., h); -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(burnheight, F, Actor) -{ - PROP_DOUBLE_PARM(h, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->BurnHeight = MAX(0., h); -} - //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4fa2323b0..fcb250563 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -193,16 +193,16 @@ class Actor : Thinker native native double RadiusDamageFactor; // Radius damage factor native double SelfDamageFactor; native double StealthAlpha; + native int WoundHealth; // Health needed to enter wound state + //native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit. native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee - native meta double DeathHeight; // Height on normal death - native meta double BurnHeight; // Height on burning death - native meta color BloodColor; // Colorized blood - native meta int GibHealth; // Negative health below which this monster dies an extreme death - native meta int WoundHealth; // Health needed to enter wound state - native meta Sound HowlSound; // Sound being played when electrocuted or poisoned + meta double DeathHeight; // Height on normal death + meta double BurnHeight; // Height on burning death + meta int GibHealth; // Negative health below which this monster dies an extreme death + meta Sound HowlSound; // Sound being played when electrocuted or poisoned meta Name BloodType; // Blood replacement type meta Name BloodType2; // Bloopsplatter replacement type meta Name BloodType3; // AxeBlood replacement type @@ -225,6 +225,10 @@ class Actor : Thinker native Property ExplosionDamage: ExplosionDamage; Property BloodType: BloodType, BloodType2, BloodType3; Property FastSpeed: FastSpeed; + Property HowlSound: HowlSound; + Property GibHealth: GibHealth; + Property DeathHeight: DeathHeight; + Property BurnHeight: BurnHeight; // need some definition work first //FRenderStyle RenderStyle; @@ -298,8 +302,9 @@ class Actor : Thinker native SelfDamageFactor 1; StealthAlpha 0; WoundHealth 6; - - + GibHealth int.min; + DeathHeight -1; + BurnHeight -1; } // Functions @@ -383,6 +388,41 @@ class Actor : Thinker native } return bloodcls; } + + virtual int GetGibHealth() + { + if (GibHealth != int.min) + { + return -abs(GibHealth); + } + else + { + return -int(GetSpawnHealth() * gameinfo.gibfactor); + } + } + + virtual double GetDeathHeight() + { + // [RH] Allow the death height to be overridden using metadata. + double metaheight = -1; + if (DamageType == 'Fire') + { + metaheight = BurnHeight; + } + if (metaheight < 0) + { + metaheight = DeathHeight; + } + if (metaheight < 0) + { + return Height * 0.25; + } + else + { + return MAX(metaheight, 0); + } + } + native static class GetReplacement(class cls); native static class GetReplacee(class cls); @@ -559,7 +599,6 @@ class Actor : Thinker native native double GetAngle(int flags, int ptr = AAPTR_TARGET); native double GetZAt(double px = 0, double py = 0, double angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); - native int GetGibHealth(); native double GetCrouchFactor(int ptr = AAPTR_PLAYER1); native double GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index d8fed2f28..f5eda9022 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -310,6 +310,7 @@ struct GameInfoStruct native native GIFont mStatscreenMapNameFont; native GIFont mStatscreenEnteringFont; native GIFont mStatscreenFinishedFont; + native double gibfactor; } class Object native From fc125f7eafcac65805f3b62f9ae13eca774f0c47 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:30:14 +0100 Subject: [PATCH 25/48] - reworked the obituary system to use scripted virtual overrides. Let's hope this solves the problems with the original code, now that any actor needing special treatment can override it. --- src/info.cpp | 2 - src/info.h | 2 - src/p_interaction.cpp | 90 +++++---------------- src/p_mobj.cpp | 2 - src/scripting/thingdef_properties.cpp | 20 ----- wadsrc/static/zscript/actor.txt | 20 ++++- wadsrc/static/zscript/inventory/weapons.txt | 6 ++ wadsrc/static/zscript/shared/player.txt | 30 +++++++ 8 files changed, 73 insertions(+), 99 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 76ba0fbcb..d51cad115 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -295,8 +295,6 @@ void PClassActor::DeriveData(PClass *newclass) PClassActor *newa = static_cast(newclass); newa->DefaultStateUsage = DefaultStateUsage; - newa->Obituary = Obituary; - newa->HitObituary = HitObituary; newa->BloodColor = BloodColor; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index cd21deac4..d5e3eff48 100644 --- a/src/info.h +++ b/src/info.h @@ -290,8 +290,6 @@ public: TArray VisibleToPlayerClass; - FString Obituary; // Player was killed by this actor - FString HitObituary; // Player was killed by this actor in melee PalEntry BloodColor; // Colorized blood FDropItem *DropItems; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 9d8d63de0..b4cb5d16f 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -62,7 +62,6 @@ #include "g_levellocals.h" #include "events.h" -static FRandom pr_obituary ("Obituary"); static FRandom pr_botrespawn ("BotRespawn"); static FRandom pr_killmobj ("ActorDie"); FRandom pr_damagemobj ("ActorTakeDamage"); @@ -186,14 +185,11 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf const char *message; const char *messagename; char gendermessage[1024]; - int gender; // No obituaries for non-players, voodoo dolls or when not wanted if (self->player == NULL || self->player->mo != self || !show_obituaries) return; - gender = self->player->userinfo.GetGender(); - // Treat voodoo dolls as unknown deaths if (inflictor && inflictor->player && inflictor->player->mo != inflictor) MeansOfDeath = NAME_None; @@ -217,93 +213,47 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf } FString obit = DamageTypeDefinition::GetObituary(mod); - if (obit.IsNotEmpty()) messagename = obit; + if (attacker == nullptr) messagename = obit; else { switch (mod) { - case NAME_Suicide: messagename = "OB_SUICIDE"; break; - case NAME_Falling: messagename = "OB_FALLING"; break; - case NAME_Crush: messagename = "OB_CRUSH"; break; - case NAME_Exit: messagename = "OB_EXIT"; break; - case NAME_Drowning: messagename = "OB_WATER"; break; - case NAME_Slime: messagename = "OB_SLIME"; break; - case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break; + case NAME_Suicide: message = "$OB_SUICIDE"; break; + case NAME_Falling: message = "$OB_FALLING"; break; + case NAME_Crush: message = "$OB_CRUSH"; break; + case NAME_Exit: message = "$OB_EXIT"; break; + case NAME_Drowning: message = "$OB_WATER"; break; + case NAME_Slime: message = "$OB_SLIME"; break; + case NAME_Fire: messagename = "$OB_LAVA"; break; } } // Check for being killed by a voodoo doll. if (inflictor && inflictor->player && inflictor->player->mo != inflictor) { - messagename = "OB_VOODOO"; + messagename = "$OB_VOODOO"; } - if (messagename != NULL) - message = GStrings(messagename); - if (attacker != NULL && message == NULL) { if (attacker == self) { - message = GStrings("OB_KILLEDSELF"); + message = "$OB_KILLEDSELF"; } - else if (attacker->player == NULL) + else { - if (mod == NAME_Telefrag) + IFVIRTUALPTR(attacker, AActor, GetObituary) { - message = GStrings("OB_MONTELEFRAG"); - } - else if (mod == NAME_Melee && attacker->GetClass()->HitObituary.IsNotEmpty()) - { - message = attacker->GetClass()->HitObituary; - } - else if (attacker->GetClass()->Obituary.IsNotEmpty()) - { - message = attacker->GetClass()->Obituary; + VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) }; + FString ret; + VMReturn rett(&ret); + GlobalVMStack.Call(func, params, countof(params), &rett, 1); + if (ret.IsNotEmpty()) message = ret; } } } - - if (message == NULL && attacker != NULL && attacker->player != NULL) - { - if (self->player != attacker->player && self->IsTeammate(attacker)) - { - self = attacker; - gender = self->player->userinfo.GetGender(); - mysnprintf (gendermessage, countof(gendermessage), "OB_FRIENDLY%c", '1' + (pr_obituary() & 3)); - message = GStrings(gendermessage); - } - else - { - if (mod == NAME_Telefrag) message = GStrings("OB_MPTELEFRAG"); - if (message == NULL) - { - if (inflictor != NULL && inflictor->GetClass()->Obituary.IsNotEmpty()) - { - message = inflictor->GetClass()->Obituary; - } - if (message == NULL && (dmgflags & DMG_PLAYERATTACK) && attacker->player->ReadyWeapon != NULL) - { - message = attacker->player->ReadyWeapon->GetClass()->Obituary; - } - if (message == NULL) - { - switch (mod) - { - case NAME_BFGSplash: messagename = "OB_MPBFG_SPLASH"; break; - case NAME_Railgun: messagename = "OB_RAILGUN"; break; - } - if (messagename != NULL) - message = GStrings(messagename); - } - if (message == NULL) - { - message = attacker->GetClass()->Obituary; - } - } - } - } - else attacker = self; // for the message creation + if (message == nullptr) message = messagename; // fallback to defaults if possible. + if (attacker->player == nullptr) attacker = self; // for the message creation if (message != NULL && message[0] == '$') { @@ -319,7 +269,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (message == NULL || strlen(message) <= 0) return; - SexMessage (message, gendermessage, gender, + SexMessage (message, gendermessage, self->player->userinfo.GetGender(), self->player->userinfo.GetName(), attacker->player->userinfo.GetName()); Printf (PRINT_MEDIUM, "%s\n", gendermessage); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bc432434c..4446393d7 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -317,8 +317,6 @@ DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(AActor, WoundHealth) -DEFINE_FIELD(PClassActor, Obituary) -DEFINE_FIELD(PClassActor, HitObituary) //DEFINE_FIELD(PClassActor, BloodColor) //========================================================================== diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e588b452c..e41523b8c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -960,26 +960,6 @@ DEFINE_PROPERTY(alpha, F, Actor) defaults->Alpha = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(obituary, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->Obituary = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(hitobituary, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->HitObituary = str; -} - //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index fcb250563..97e2bf6bb 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -196,9 +196,8 @@ class Actor : Thinker native native int WoundHealth; // Health needed to enter wound state //native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit. - native meta String Obituary; // Player was killed by this actor - native meta String HitObituary; // Player was killed by this actor in melee - + meta String Obituary; // Player was killed by this actor + meta String HitObituary; // Player was killed by this actor in melee meta double DeathHeight; // Height on normal death meta double BurnHeight; // Height on burning death meta int GibHealth; // Negative health below which this monster dies an extreme death @@ -216,6 +215,8 @@ class Actor : Thinker native meta double FastSpeed; // speed in fast mode Property prefix: none; + Property Obituary: Obituary; + Property HitObituary: HitObituary; Property MeleeDamage: MeleeDamage; Property MeleeSound: MeleeSound; Property MissileHeight: MissileHeight; @@ -423,6 +424,19 @@ class Actor : Thinker native } } + virtual String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + if (mod == 'Telefrag') + { + return "$OB_MONTELEFRAG"; + } + else if (mod == 'Melee' && HitObituary.Length() > 0) + { + return HitObituary; + } + return Obituary; + } + native static class GetReplacement(class cls); native static class GetReplacee(class cls); diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index de9464726..860d387e2 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -89,6 +89,12 @@ class Weapon : StateProvider native return s; } + override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + // Weapons may never return HitObituary by default. Override this if it is needed. + return Obituary; + } + action void A_GunFlash(statelabel flashlabel = null, int flags = 0) { let player = player; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 9b686a551..14347a41c 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -119,6 +119,36 @@ class PlayerPawn : Actor native } } + override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + if (victim.player != player && victim.IsTeammate(self)) + { + victim = self; + return String.Format("$OB_FRIENDLY%c", random[Obituary](49, 53)); + } + else + { + if (mod == 'Telefrag') return "$OB_MPTELEFRAG"; + + String message; + if (inflictor != NULL) + { + message = inflictor.GetObituary(victim, inflictor, mod, playerattack); + } + if (message.Length() == 0 && playerattack && player.ReadyWeapon != NULL) + { + message = player.ReadyWeapon.GetObituary(victim, inflictor, mod, playerattack); + } + if (message.Length() == 0) + { + if (mod == 'BFGSplash') return "$OB_MPBFG_SPLASH"; + if (mod == 'Railgun') return "$OB_RAILGUN"; + message = Obituary; + } + return message; + } + } + // This is for SBARINFO. int, int GetEffectTicsForItem(class item) { From bc0ffc4185d4c5c42e10b488b925cf2aec2be230 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:33:46 +0100 Subject: [PATCH 26/48] - removed access to the PlayerPawn's DisplayName variable. This one has implicit semantics, so wherever a displayable name is needed GetPrintableDisplayName should be called instead to allow later refactoring of the internal handling. --- src/p_user.cpp | 2 -- wadsrc/static/zscript/shared/player.txt | 1 - 2 files changed, 3 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index 30db0a271..0f8954e56 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3333,8 +3333,6 @@ DEFINE_FIELD(APlayerPawn, HexenArmor) DEFINE_FIELD(APlayerPawn, ColorRangeStart) DEFINE_FIELD(APlayerPawn, ColorRangeEnd) -DEFINE_FIELD(PClassActor, DisplayName) - DEFINE_FIELD_X(PlayerInfo, player_t, mo) DEFINE_FIELD_X(PlayerInfo, player_t, playerstate) DEFINE_FIELD_X(PlayerInfo, player_t, original_oldbuttons) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 14347a41c..2e7bda8f6 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -34,7 +34,6 @@ class PlayerPawn : Actor native native double ViewBob; // [SP] ViewBob Multiplier native double FullHeight; - native meta String DisplayName; // Display name (used in menus, etc.) meta Name HealingRadiusType; meta Name InvulMode; From 168627f549a353794d74aa83452b9139c5366f71 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:38:50 +0100 Subject: [PATCH 27/48] - native meta variables are not needed anymore. They were only a temporary aid to properly handle this, but now all have been redone. --- src/scripting/backend/codegen.cpp | 2 +- src/scripting/decorate/thingdef_parse.cpp | 9 +----- src/scripting/zscript/zcc_compile.cpp | 39 +++++++++++------------ 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 893a50eed..8e41f44ab 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6871,7 +6871,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { obj.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(membervar->Flags & VARF_Native? OP_CLSS : OP_META, meta.RegNum, obj.RegNum); + build->Emit(OP_META, meta.RegNum, obj.RegNum); obj = meta; } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e70059fec..72cac7cde 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -827,14 +827,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul if (i > 0) sc.MustGetStringName(","); if (f->Flags & VARF_Meta) { - if (f->Flags & VARF_Native) - { - addr = ((char*)bag.Info) + f->Offset; - } - else - { - addr = ((char*)bag.Info->Meta) + f->Offset; - } + addr = ((char*)bag.Info->Meta) + f->Offset; } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 548424cd9..5574fcc18 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1095,22 +1095,28 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (varflags & VARF_Native) { - auto querytype = (varflags & VARF_Meta) ? type->GetClass() : type; - fd = FindField(querytype, FName(name->Name).GetChars()); - if (fd == nullptr) + if (varflags & VARF_Meta) { - Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); + Error(field, "Native meta variable %s not allowed", FName(name->Name).GetChars()); } - else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0) - { - Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); - } - // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. else { - // for bit fields the type must point to the source variable. - if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; - type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); + fd = FindField(type, FName(name->Name).GetChars()); + if (fd == nullptr) + { + Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); + } + else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0) + { + Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); + } + // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. + else + { + // for bit fields the type must point to the source variable. + if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; + type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); + } } } else if (hasnativechildren) @@ -1694,14 +1700,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop if (f->Flags & VARF_Meta) { - if (f->Flags & VARF_Native) - { - addr = ((char*)bag.Info) + f->Offset; - } - else - { - addr = ((char*)bag.Info->Meta) + f->Offset; - } + addr = ((char*)bag.Info->Meta) + f->Offset; } else { From 5f6da0d2223569ea9f5c346f791ac7e913236d0b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:44:18 +0100 Subject: [PATCH 28/48] fixed double allocation of metadata. --- src/dobjtype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f86797dfd..cd128b656 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3361,7 +3361,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) // Only initialize the defaults if they have already been created. // For ZScript this is not the case, it will first define all fields before // setting up any defaults for any class. - if (field != nullptr && !(flags & VARF_Native)) + if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) { Meta = (BYTE *)M_Realloc(Meta, MetaSize); memset(Meta + oldsize, 0, MetaSize - oldsize); From bb1709228cb0e9b66150094d9d836e50468772b4 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 28 Feb 2017 18:23:40 +0800 Subject: [PATCH 29/48] Changed FOV from a CCMD to a CVar, allowing players' FOV settings to persist. Also exported SetFOV to PlayerInfo for ZScript. --- src/c_cmds.cpp | 28 ----------------- src/d_player.h | 3 ++ src/p_mobj.cpp | 3 +- src/p_user.cpp | 41 +++++++++++++++++++++++++ wadsrc/static/zscript/shared/player.txt | 1 + 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 7e0a66c4b..4bdca624a 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -732,34 +732,6 @@ CCMD (dir) chdir (curdir); } -CCMD (fov) -{ - player_t *player = who ? who->player : &players[consoleplayer]; - - if (argv.argc() != 2) - { - Printf ("fov is %g\n", player->DesiredFOV); - return; - } - else if (dmflags & DF_NO_FOV) - { - if (consoleplayer == Net_Arbitrator) - { - Net_WriteByte (DEM_FOV); - } - else - { - Printf ("A setting controller has disabled FOV changes.\n"); - return; - } - } - else - { - Net_WriteByte (DEM_MYFOV); - } - Net_WriteByte (clamp (atoi (argv[1]), 5, 179)); -} - //========================================================================== // // CCMD warp diff --git a/src/d_player.h b/src/d_player.h index 2d7d439c5..35daa57a2 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -529,6 +529,9 @@ public: DPSprite *GetPSprite(PSPLayers layer); bool GetPainFlash(FName type, PalEntry *color) const; + + // [Nash] set player FOV + void SetFOV(float fov); }; // Bookkeeping on players - state. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f38ac12bb..d5c133265 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5305,6 +5305,7 @@ DEFINE_ACTION_FUNCTION(AActor, AdjustFloorClip) // EXTERN_CVAR (Bool, chasedemo) EXTERN_CVAR(Bool, sv_singleplayerrespawn) +EXTERN_CVAR(Float, fov) extern bool demonew; @@ -5442,7 +5443,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) mobj->sprite = Skins[p->userinfo.GetSkin()].sprite; } - p->DesiredFOV = p->FOV = 90.f; + p->DesiredFOV = p->FOV = fov; p->camera = p->mo; p->playerstate = PST_LIVE; p->refire = 0; diff --git a/src/p_user.cpp b/src/p_user.cpp index 5bb0e2127..62d44c74e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -88,6 +88,13 @@ CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCO ColorSetList ColorSets; PainFlashList PainFlashes; +// [Nash] FOV cvar setting +CUSTOM_CVAR(Float, fov, 90.f, CVAR_ARCHIVE | CVAR_USERINFO | CVAR_NOINITCALL) +{ + player_t *p = &players[consoleplayer]; + p->SetFOV(fov); +} + struct PredictPos { int gametic; @@ -550,6 +557,40 @@ int player_t::GetSpawnClass() return static_cast(GetDefaultByType(type))->SpawnMask; } +// [Nash] Set FOV +void player_t::SetFOV(float fov) +{ + player_t *p = &players[consoleplayer]; + if (p != nullptr && p->mo != nullptr) + { + if (dmflags & DF_NO_FOV) + { + if (consoleplayer == Net_Arbitrator) + { + Net_WriteByte(DEM_MYFOV); + } + else + { + Printf("A setting controller has disabled FOV changes.\n"); + return; + } + } + else + { + Net_WriteByte(DEM_MYFOV); + } + Net_WriteByte((BYTE)clamp(fov, 5.f, 179.f)); + } +} + +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetFOV) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_FLOAT(fov); + self->SetFOV((float)fov); + return 0; +} + //=========================================================================== // // EnumColorsets diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8886e6744..d2bd2d012 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -320,6 +320,7 @@ usercmd_t original_cmd; native int GetGender(); native int GetTeam(); native float GetAutoaim(); + native void SetFOV(float fov); } struct PlayerClass native From dc6c91042bb1c34330774a4677fcb33cd785b124 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 18:47:18 +0100 Subject: [PATCH 30/48] - fixed misordered ACS functions. --- src/p_acs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 6053ce85a..5ea7dfa07 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4369,8 +4369,8 @@ enum EACSFunctions ACSF_GetActorFloorTerrain, ACSF_StrArg, ACSF_Floor, - ACSF_Ceil, ACSF_Round, + ACSF_Ceil, // OpenGL stuff From 12915b5f6e27e36e2eb69356114f287347df2134 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 21:45:47 +0100 Subject: [PATCH 31/48] - use an inventory flag to decide what items are slipped by DF_NO_HEALTH and DF_NO_ARMOR. With all the changes over the last 10 years this had become too spotty. - use an enum type for ItemFlags, just like it was done for actor flags. Since the flag word is almost full it may soon be necessary to add a second one and then this kind of security check may become necessary. --- src/g_inventory/a_pickups.h | 10 ++++-- src/p_enemy.cpp | 4 +-- src/p_mobj.cpp | 36 +++++++++----------- src/scripting/thingdef_data.cpp | 2 ++ wadsrc/static/zscript/doom/doomartifacts.txt | 3 ++ wadsrc/static/zscript/inventory/armor.txt | 1 + wadsrc/static/zscript/inventory/health.txt | 2 ++ 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 9258d320a..9b2fc1cc1 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -17,7 +17,7 @@ struct visstyle_t; // A pickup is anything the player can pickup (i.e. weapons, ammo, powerups, etc) -enum +enum ItemFlag { IF_ACTIVATABLE = 1<<0, // can be activated IF_ACTIVATED = 1<<1, // is currently activated @@ -46,8 +46,14 @@ enum IF_TRANSFER = 1<<24, // All inventory items that the inventory item contains is also transfered to the pickuper IF_NOTELEPORTFREEZE = 1<<25, // does not 'freeze' the player right after teleporting. IF_NOSCREENBLINK = 1<<26, // Does not blink the screen overlay when expiring. + IF_ISHEALTH = 1<<27, // for the DM flag so that it can recognize items that are not obviously health givers. + IF_ISARMOR = 1<<28, // for the DM flag so that it can recognize items that are not obviously armor givers. }; +typedef TFlags InvFlags; +//typedef TFlags ItemFlags2; +DEFINE_TFLAGS_OPERATORS(InvFlags) +//DEFINE_TFLAGS_OPERATORS(ItemFlags2) class AInventory : public AActor { @@ -89,7 +95,7 @@ public: PClassActor *SpawnPointClass; // For respawning like Heretic's mace FTextureID AltHUDIcon; - DWORD ItemFlags; + InvFlags ItemFlags; PClassActor *PickupFlash; // actor to spawn as pickup flash FSoundIDNoInit PickupSound; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5841e6b99..dde4fce29 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3217,13 +3217,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound) //--------------------------------------------------------------------------- void ModifyDropAmount(AInventory *inv, int dropamount) { - int flagmask = IF_IGNORESKILL; + auto flagmask = IF_IGNORESKILL; double dropammofactor = G_SkillProperty(SKILLP_DropAmmoFactor); // Default drop amount is half of regular amount * regular ammo multiplication if (dropammofactor == -1) { dropammofactor = 0.5; - flagmask = 0; + flagmask = ItemFlag(0); } if (dropamount > 0) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index fc40982f5..104a42471 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5821,27 +5821,23 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) // [RH] Other things that shouldn't be spawned depending on dmflags if (deathmatch || alwaysapplydmflags) { - // Fixme: This needs to be done differently, it's quite broken. - if (dmflags & DF_NO_HEALTH) + if (i->IsDescendantOf(RUNTIME_CLASS(AInventory))) { - if (i->IsDescendantOf (PClass::FindActor(NAME_Health))) - return NULL; - if (i->TypeName == NAME_Berserk) - return NULL; - if (i->TypeName == NAME_Megasphere) - return NULL; - } - if (dmflags & DF_NO_ITEMS) - { -// if (i->IsDescendantOf (RUNTIME_CLASS(AArtifact))) -// return; - } - if (dmflags & DF_NO_ARMOR) - { - if (i->IsDescendantOf (PClass::FindActor(NAME_Armor))) - return NULL; - if (i->TypeName == NAME_Megasphere) - return NULL; + auto it = static_cast(GetDefaultByType(i)); + + if (dmflags & DF_NO_HEALTH) + { + if (it->ItemFlags & IF_ISHEALTH) return nullptr; + } + if (dmflags & DF_NO_ITEMS) + { + // if (i->IsDescendantOf (RUNTIME_CLASS(AArtifact))) + // return; + } + if (dmflags & DF_NO_ARMOR) + { + if (it->ItemFlags & IF_ISARMOR) return nullptr; + } } } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 265dc079b..4b65e6413 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -430,6 +430,8 @@ static FFlagDef InventoryFlagDefs[] = DEFINE_FLAG(IF, TRANSFER, AInventory, ItemFlags), DEFINE_FLAG(IF, NOTELEPORTFREEZE, AInventory, ItemFlags), DEFINE_FLAG(IF, NOSCREENBLINK, AInventory, ItemFlags), + DEFINE_FLAG(IF, ISARMOR, AInventory, ItemFlags), + DEFINE_FLAG(IF, ISHEALTH, AInventory, ItemFlags), DEFINE_DUMMY_FLAG(FORCERESPAWNINSURVIVAL, false), diff --git a/wadsrc/static/zscript/doom/doomartifacts.txt b/wadsrc/static/zscript/doom/doomartifacts.txt index ad5e304c6..a6996cb88 100644 --- a/wadsrc/static/zscript/doom/doomartifacts.txt +++ b/wadsrc/static/zscript/doom/doomartifacts.txt @@ -72,6 +72,8 @@ class Megasphere : CustomInventory { +COUNTITEM +INVENTORY.ALWAYSPICKUP + +INVENTORY.ISHEALTH + +INVENTORY.ISARMOR Inventory.PickupMessage "$GOTMSPHERE"; Inventory.PickupSound "misc/p_pkup"; } @@ -183,6 +185,7 @@ class Berserk : CustomInventory { +COUNTITEM +INVENTORY.ALWAYSPICKUP + +INVENTORY.ISHEALTH Inventory.PickupMessage "$GOTBERSERK"; Inventory.PickupSound "misc/p_pkup"; } diff --git a/wadsrc/static/zscript/inventory/armor.txt b/wadsrc/static/zscript/inventory/armor.txt index ae9ab562e..600c4e526 100644 --- a/wadsrc/static/zscript/inventory/armor.txt +++ b/wadsrc/static/zscript/inventory/armor.txt @@ -38,6 +38,7 @@ class Armor : Inventory Default { Inventory.PickupSound "misc/armor_pkup"; + +INVENTORY.ISARMOR } } diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index e2fb8eacf..e64bbfd4a 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -43,6 +43,7 @@ class Health : Inventory Default { + +INVENTORY.ISHEALTH Inventory.Amount 1; Inventory.MaxAmount 0; Inventory.PickupSound "misc/health_pkup"; @@ -99,6 +100,7 @@ class HealthPickup : Inventory { Inventory.DefMaxAmount; +INVENTORY.INVBAR + +INVENTORY.ISHEALTH } //=========================================================================== From cb295e0441cccae57b011fd764b3e0d5c49774db Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 00:04:17 +0100 Subject: [PATCH 32/48] - added parameter to PLayerPawn::GetMaxHealth to return the real maximum health, including stamina upgrades. --- src/b_think.cpp | 2 +- src/d_player.h | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 4 ++-- src/p_mobj.cpp | 2 +- src/p_user.cpp | 11 +++++++---- wadsrc/static/zscript/shared/player.txt | 2 +- wadsrc/static/zscript/shared/player_cheat.txt | 2 +- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/b_think.cpp b/src/b_think.cpp index da3fb6124..f286dd30f 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -358,7 +358,7 @@ void DBot::WhatToGet (AActor *item) } else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && player->mo->health >= deh.MaxSoulsphere) return; - else if (item->IsKindOf (PClass::FindActor(NAME_Health)) && player->mo->health >= player->mo->GetMaxHealth() + player->mo->stamina) + else if (item->IsKindOf (PClass::FindActor(NAME_Health)) && player->mo->health >= player->mo->GetMaxHealth(true)) return; if ((dest == NULL || diff --git a/src/d_player.h b/src/d_player.h index 39698d6d8..2787df231 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -93,7 +93,7 @@ public: virtual bool UpdateWaterLevel (bool splash) override; bool ResetAirSupply (bool playgasp = true); - int GetMaxHealth() const; + int GetMaxHealth(bool withupgrades = false) const; void TweakSpeeds (double &forwardmove, double &sidemove); void MorphPlayerThink (); void ActivateMorphWeapon (); diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index ae6ba5b00..ad2da961d 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -2744,7 +2744,7 @@ class CommandDrawBar : public SBarInfoCommand max = 0; } else //default to the class's health - max = statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->mo->stamina; + max = statusBar->CPlayer->mo->GetMaxHealth(true); break; case ARMOR: value = statusBar->armor != NULL ? statusBar->armor->Amount : 0; @@ -3251,7 +3251,7 @@ class CommandDrawGem : public SBarInfoCommand void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { goalValue = armor ? (statusBar->armor ? statusBar->armor->Amount : 0) : statusBar->CPlayer->mo->health; - int max = armor ? 100 : statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->mo->stamina; + int max = armor ? 100 : statusBar->CPlayer->mo->GetMaxHealth(true); if(max != 0 && goalValue > 0) { goalValue = (goalValue*100)/max; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 104a42471..b4affd539 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1330,7 +1330,7 @@ bool P_GiveBody(AActor *actor, int num, int max) // calls while supporting health pickups. if (max <= 0) { - max = static_cast(actor)->GetMaxHealth() + player->mo->stamina; + max = static_cast(actor)->GetMaxHealth(true); // [MH] First step in predictable generic morph effects if (player->morphTics) { diff --git a/src/p_user.cpp b/src/p_user.cpp index 7509e9bca..ab4390ba2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1350,15 +1350,18 @@ const char *APlayerPawn::GetSoundClass() const // //=========================================================================== -int APlayerPawn::GetMaxHealth() const +int APlayerPawn::GetMaxHealth(bool withupgrades) const { - return MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); + int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); + if (withupgrades) ret += stamina; + return ret; } DEFINE_ACTION_FUNCTION(APlayerPawn, GetMaxHealth) { PARAM_SELF_PROLOGUE(APlayerPawn); - ACTION_RETURN_INT(self->GetMaxHealth()); + PARAM_BOOL_DEF(withupgrades); + ACTION_RETURN_INT(self->GetMaxHealth(withupgrades)); } //=========================================================================== @@ -2869,7 +2872,7 @@ void P_PlayerThink (player_t *player) // Apply degeneration. if (dmflags2 & DF2_YES_DEGENERATION) { - int maxhealth = player->mo->GetMaxHealth() + player->mo->stamina; + int maxhealth = player->mo->GetMaxHealth(true); if ((level.time % TICRATE) == 0 && player->health > maxhealth) { if (player->health - 5 < maxhealth) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 0b60e3d51..97e065c2a 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -166,7 +166,7 @@ class PlayerPawn : Actor native return -1, -1; } - native int GetMaxHealth(); + native int GetMaxHealth(bool withupgrades = false); native bool ResetAirSupply (bool playgasp = false); native void CheckWeaponSwitch(class item); native static String GetPrintableDisplayName(Class cls); diff --git a/wadsrc/static/zscript/shared/player_cheat.txt b/wadsrc/static/zscript/shared/player_cheat.txt index 2aaa01ba8..15bad043c 100644 --- a/wadsrc/static/zscript/shared/player_cheat.txt +++ b/wadsrc/static/zscript/shared/player_cheat.txt @@ -76,7 +76,7 @@ extend class PlayerPawn } else { - player.health = health = GetMaxHealth(); + player.health = health = GetMaxHealth(true); } } From 05836916708c458d58c2ac2ce96b24a1bcd891d1 Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Sun, 19 Feb 2017 06:08:50 -0800 Subject: [PATCH 33/48] Add bash-style console shortcuts --- src/c_console.cpp | 153 +++++++++++++++++++++++++++++++++++++- src/posix/sdl/i_input.cpp | 8 +- src/zstring.cpp | 1 - 3 files changed, 157 insertions(+), 5 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 0b1e58287..17e46e182 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -206,6 +206,9 @@ struct FCommandBuffer unsigned CursorPos; unsigned StartPos; // First character to display + FString YankBuffer; // Deleted text buffer + bool AppendToYankBuffer; // Append consecutive deletes to buffer + FCommandBuffer() { CursorPos = StartPos = 0; @@ -278,6 +281,30 @@ struct FCommandBuffer StartPos = MAX(0, n); } + unsigned WordBoundaryRight() + { + unsigned index = CursorPos; + while (index < Text.Len() && Text[index] == ' ') { + index++; + } + while (index < Text.Len() && Text[index] != ' ') { + index++; + } + return index; + } + + unsigned WordBoundaryLeft() + { + int index = CursorPos - 1; + while (index > -1 && Text[index] == ' ') { + index--; + } + while (index > -1 && Text[index] != ' ') { + index--; + } + return (unsigned)index + 1; + } + void CursorStart() { CursorPos = 0; @@ -309,6 +336,18 @@ struct FCommandBuffer } } + void CursorWordLeft() + { + CursorPos = WordBoundaryLeft(); + MakeStartPosGood(); + } + + void CursorWordRight() + { + CursorPos = WordBoundaryRight(); + MakeStartPosGood(); + } + void DeleteLeft() { if (CursorPos > 0) @@ -328,6 +367,50 @@ struct FCommandBuffer } } + void DeleteWordLeft() + { + if (CursorPos > 0) + { + unsigned index = WordBoundaryLeft(); + if (AppendToYankBuffer) { + YankBuffer = FString(&Text[index], CursorPos - index) + YankBuffer; + } else { + YankBuffer = FString(&Text[index], CursorPos - index); + } + Text.Remove(index, CursorPos - index); + CursorPos = index; + MakeStartPosGood(); + } + } + + void DeleteLineLeft() + { + if (CursorPos > 0) + { + if (AppendToYankBuffer) { + YankBuffer = FString(&Text[0], CursorPos) + YankBuffer; + } else { + YankBuffer = FString(&Text[0], CursorPos); + } + Text.Remove(0, CursorPos); + CursorStart(); + } + } + + void DeleteLineRight() + { + if (CursorPos < Text.Len()) + { + if (AppendToYankBuffer) { + YankBuffer += FString(&Text[CursorPos], Text.Len() - CursorPos); + } else { + YankBuffer = FString(&Text[CursorPos], Text.Len() - CursorPos); + } + Text.Truncate(CursorPos); + CursorEnd(); + } + } + void AddChar(int character) { ///FIXME: Not Unicode-aware @@ -1345,6 +1428,7 @@ DEFINE_ACTION_FUNCTION(_Console, Printf) static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) { int data1 = ev->data1; + bool keepappending = false; switch (ev->subtype) { @@ -1352,8 +1436,22 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) return false; case EV_GUI_Char: + if (ev->data2) + { + // Bash-style shortcuts + if (data1 == 'b') + { + buffer.CursorWordLeft(); + break; + } + else if (data1 == 'f') + { + buffer.CursorWordRight(); + break; + } + } // Add keypress to command line - buffer.AddChar(ev->data1); + buffer.AddChar(data1); HistPos = NULL; TabbedLast = false; TabbedList = false; @@ -1654,6 +1752,56 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) break; } break; + + // Bash-style shortcuts + case 'A': + if (ev->data3 & GKM_CTRL) + { + buffer.CursorStart(); + } + break; + case 'E': + if (ev->data3 & GKM_CTRL) + { + buffer.CursorEnd(); + } + break; + case 'W': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteWordLeft(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'U': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteLineLeft(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'K': + if (ev->data3 & GKM_CTRL) + { + buffer.DeleteLineRight(); + keepappending = true; + TabbedLast = false; + TabbedList = false; + } + break; + case 'Y': + if (ev->data3 & GKM_CTRL) + { + buffer.AddString(buffer.YankBuffer); + TabbedLast = false; + TabbedList = false; + HistPos = NULL; + } + break; } break; @@ -1664,6 +1812,9 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) break; #endif } + + buffer.AppendToYankBuffer = keepappending; + // Ensure that the cursor is always visible while typing CursorTicker = C_BLINKRATE; cursoron = 1; diff --git a/src/posix/sdl/i_input.cpp b/src/posix/sdl/i_input.cpp index 759da062c..57ea03d92 100644 --- a/src/posix/sdl/i_input.cpp +++ b/src/posix/sdl/i_input.cpp @@ -395,9 +395,10 @@ void MessagePump (const SDL_Event &sev) { event.type = EV_GUI_Event; event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp; - event.data3 = ((sev.key.keysym.mod & KMOD_SHIFT) ? GKM_SHIFT : 0) | - ((sev.key.keysym.mod & KMOD_CTRL) ? GKM_CTRL : 0) | - ((sev.key.keysym.mod & KMOD_ALT) ? GKM_ALT : 0); + SDL_Keymod kmod = SDL_GetModState(); + event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); if (event.subtype == EV_GUI_KeyDown) { @@ -458,6 +459,7 @@ void MessagePump (const SDL_Event &sev) event.type = EV_GUI_Event; event.subtype = EV_GUI_Char; event.data1 = sev.text.text[0]; + event.data2 = !!(SDL_GetModState() & KMOD_ALT); D_PostEvent (&event); } break; diff --git a/src/zstring.cpp b/src/zstring.cpp index 83a2a20d8..a74edd01b 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -393,7 +393,6 @@ void FString::Remove(size_t index, size_t remlen) } else { - remlen = Len() - remlen < remlen ? Len() - remlen : remlen; if (Data()->RefCount == 1) { // Can do this in place memmove(Chars + index, Chars + index + remlen, Len() - index - remlen); From b5d4a5946524cb7b23893c2a2eff9bb11be3ddca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:09:50 +0100 Subject: [PATCH 34/48] - fixed: Meta properties must not be serialized. --- src/dobjtype.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index cd128b656..c8a89e955 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2307,7 +2307,7 @@ void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArrayFlags & VARF_Transient)) + if (!(field->Flags & (VARF_Transient|VARF_Meta))) { field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset); } @@ -2340,6 +2340,11 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n", label, TypeName.GetChars()); } + else if ((static_cast(sym)->Flags & (VARF_Transient | VARF_Meta))) + { + DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n", + label, TypeName.GetChars()); + } else { readsomething |= static_cast(sym)->Type->ReadValue(ar, nullptr, @@ -2638,7 +2643,7 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void * // Don't write this part if it has no non-transient variables for (unsigned i = 0; i < type->Fields.Size(); ++i) { - if (!(type->Fields[i]->Flags & VARF_Transient)) + if (!(type->Fields[i]->Flags & (VARF_Transient|VARF_Meta))) { // Tag this section with the class it came from in case // a more-derived class has variables that shadow a less- From 0de79042d4b388cf4e23478d661eb6f28e385719 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:20:46 +0100 Subject: [PATCH 35/48] - fixed: 'Bloodtype' cannot use the generic property definition because it needs special handling for optional arguments. This reinstates the native handler. --- src/scripting/thingdef_properties.cpp | 27 +++++++++++++++++++++++++++ wadsrc/static/zscript/actor.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e41523b8c..af79e1d04 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1059,6 +1059,33 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) static_cast(info)->BloodColor = pe; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(bloodtype, Sss, Actor) +{ + PROP_STRING_PARM(str, 0) + PROP_STRING_PARM(str1, 1) + PROP_STRING_PARM(str2, 2) + + FName blood = str; + // normal blood + defaults->NameVar("BloodType") = blood; + + if (PROP_PARM_COUNT > 1) + { + blood = str1; + } + // blood splatter + defaults->NameVar("BloodType2") = blood; + + if (PROP_PARM_COUNT > 2) + { + blood = str2; + } + // axe blood + defaults->NameVar("BloodType3") = blood; +} //========================================================================== // diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 97e2bf6bb..4c62863df 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -224,7 +224,7 @@ class Actor : Thinker native Property DontHurtShooter: DontHurtShooter; Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; - Property BloodType: BloodType, BloodType2, BloodType3; + //Property BloodType: BloodType, BloodType2, BloodType3; Property FastSpeed: FastSpeed; Property HowlSound: HowlSound; Property GibHealth: GibHealth; From 9b2f31e69292c79c989955a70f2bcc243fd2d143 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 20:54:37 +0100 Subject: [PATCH 36/48] - had to add a hack because some people had to exploit implementation-dependent behavior of the PulseLight type. --- src/dobjtype.cpp | 1 - src/gl/dynlights/a_dynlight.cpp | 3 ++- src/gl/dynlights/gl_dynlight.cpp | 28 ++++++++++++++++++---------- src/gl/dynlights/gl_dynlight.h | 1 + 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index c8a89e955..a2a5a6883 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3402,7 +3402,6 @@ PClass *PClass::FindClassTentative(FName name) PClass *type = static_cast(GetClass()->CreateNew()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); - assert(MetaSize == 0); Derive(type, name); type->Size = TentativeClass; TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket); diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 1255401ae..bd2575216 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -204,7 +204,8 @@ void ADynamicLight::Activate(AActor *activator) float pulseTime = specialf1 / TICRATE; m_lastUpdate = level.maptime; - m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime); + if (!swapped) m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime); + else m_cycler.SetParams(float(args[LIGHT_INTENSITY]), float(args[LIGHT_SECONDARY_INTENSITY]), pulseTime); m_cycler.ShouldCycle(true); m_cycler.SetCycleType(CYCLE_Sin); m_currentRadius = m_cycler.GetVal(); diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index 5ce79fd09..4b0eac499 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -135,6 +135,16 @@ public: void SetDontLightSelf(bool add) { m_dontlightself = add; } void SetAttenuate(bool on) { m_attenuate = on; } void SetHalo(bool halo) { m_halo = halo; } + + void OrderIntensities() + { + if (m_Args[LIGHT_INTENSITY] > m_Args[LIGHT_SECONDARY_INTENSITY]) + { + std::swap(m_Args[LIGHT_INTENSITY], m_Args[LIGHT_SECONDARY_INTENSITY]); + m_swapped = true; + } + } + protected: FName m_Name; int m_Args[5]; @@ -143,6 +153,7 @@ protected: ELightType m_type; int8_t m_attenuate; bool m_subtractive, m_additive, m_halo, m_dontlightself; + bool m_swapped = false; }; TArray LightDefaults; @@ -178,8 +189,8 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const light->SetOffset(m_Pos); light->halo = m_halo; for (int a = 0; a < 3; a++) light->args[a] = clamp((int)(m_Args[a]), 0, 255); - light->args[LIGHT_INTENSITY] = int(m_Args[LIGHT_INTENSITY]); - light->args[LIGHT_SECONDARY_INTENSITY] = int(m_Args[LIGHT_SECONDARY_INTENSITY]); + light->args[LIGHT_INTENSITY] = m_Args[LIGHT_INTENSITY]; + light->args[LIGHT_SECONDARY_INTENSITY] = m_Args[LIGHT_SECONDARY_INTENSITY]; light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF); if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE; if (m_additive) light->flags4 |= MF4_ADDITIVE; @@ -190,11 +201,13 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const float pulseTime = float(m_Param / TICRATE); light->m_lastUpdate = level.maptime; - light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight); + if (m_swapped) light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight); + else light->m_cycler.SetParams(float(light->args[LIGHT_INTENSITY]), float(light->args[LIGHT_SECONDARY_INTENSITY]), pulseTime, oldtype == PulseLight); light->m_cycler.ShouldCycle(true); light->m_cycler.SetCycleType(CYCLE_Sin); light->m_currentRadius = light->m_cycler.GetVal(); if (light->m_currentRadius <= 0) light->m_currentRadius = 1; + light->swapped = m_swapped; } switch (m_attenuate) @@ -474,13 +487,7 @@ void gl_ParsePulseLight(FScanner &sc) sc.ScriptError("Unknown tag: %s\n", sc.String); } } - if (defaults->GetArg(LIGHT_INTENSITY) > defaults->GetArg(LIGHT_SECONDARY_INTENSITY)) - { - auto i = defaults->GetArg(LIGHT_INTENSITY); - auto j = defaults->GetArg(LIGHT_SECONDARY_INTENSITY); - defaults->SetArg(LIGHT_INTENSITY, j); - defaults->SetArg(LIGHT_SECONDARY_INTENSITY, i); - } + defaults->OrderIntensities(); gl_AddLightDefaults(defaults); } @@ -564,6 +571,7 @@ void gl_ParseFlickerLight(FScanner &sc) sc.ScriptError("Unknown tag: %s\n", sc.String); } } + defaults->OrderIntensities(); gl_AddLightDefaults(defaults); } else diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index ee581e74a..4733d853f 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -141,6 +141,7 @@ public: bool halo; BYTE color2[3]; bool visibletoplayer; + bool swapped; int bufferindex; From 3c21ca9cb18e240b2503cb255e02f452f71774e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 22:06:39 +0100 Subject: [PATCH 37/48] - added a compatibility option to move vertices and applied it to E1M6 of Masters of Chaos. This map has a door/lift combination that could trap the player without any chance to get out because both elements are so close together that it was almost impossible to trigger the lift. Moved two vertices by one map unit to make enough room. --- src/compatibility.cpp | 25 ++++++++++++++++++++++++- wadsrc/static/compatibility.txt | 6 ++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 0b27a1efa..37531d40f 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -86,6 +86,7 @@ enum CP_SETTHINGZ, CP_SETTAG, CP_SETTHINGFLAGS, + CP_SETVERTEX, }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -345,7 +346,19 @@ void ParseCompatibility() sc.MustGetNumber(); CompatParams.Push(sc.Number); } - else + else if (sc.Compare("setvertex")) + { + if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); + CompatParams.Push(CP_SETVERTEX); + sc.MustGetNumber(); + CompatParams.Push(sc.Number); + sc.MustGetFloat(); + CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels + sc.MustGetFloat(); + CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels + flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES; + } + else { sc.UnGet(); break; @@ -600,6 +613,16 @@ void SetCompatibilityParams() i += 3; break; } + case CP_SETVERTEX: + { + if ((unsigned)CompatParams[i + 1] < level.vertexes.Size()) + { + level.vertexes[CompatParams[i + 1]].p.X = CompatParams[i + 2] / 256.; + level.vertexes[CompatParams[i + 1]].p.Y = CompatParams[i + 3] / 256.; + } + i += 4; + break; + } } } } diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 020d8477d..9f7564b95 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -497,6 +497,12 @@ ABC4EB5A1535ECCD0061AD14F3547908 // Plutonia Experiment, map26 setsectorspecial 156 0 } +B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6 +{ + setvertex 1650 -3072 2671 + setvertex 1642 -2944 2671 +} + 712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect { setsectortag 545 32000 From 384accbc860b46a5293784572421c649b067204c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 2 Mar 2017 10:12:11 +0200 Subject: [PATCH 38/48] Fixed name and placement of 'All except doors' localized string --- wadsrc/static/language.eng | 1 - wadsrc/static/language.enu | 1 + wadsrc/static/menudef.txt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/language.eng b/wadsrc/static/language.eng index 66757cee7..bf0a0a91d 100644 --- a/wadsrc/static/language.eng +++ b/wadsrc/static/language.eng @@ -106,7 +106,6 @@ CMPTMNU_RENDERINGBEHAVIOR = "Rendering Behaviour"; CMPTMNU_SOUNDBEHAVIOR = "Sound Behaviour"; CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only"; -OPTVAL_NODOORS = "All except doors"; C_GRAY = "\ccgrey"; C_DARKGRAY = "\cudark grey"; diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 64cf4034b..55477ee2e 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2286,6 +2286,7 @@ OPTVAL_FRONT = "Front"; OPTVAL_ANIMATED = "Animated"; OPTVAL_ROTATED = "Rotated"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only"; +OPTVAL_NODOORS = "All except doors"; OPTVAL_DOUBLE = "Double"; OPTVAL_TRIPLE = "Triple"; OPTVAL_QUADRUPLE = "Quadruple"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b66b381ba..2dd3e5e55 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1014,7 +1014,7 @@ OptionValue MapBackTypes OptionValue MapTriggers { 0, "$OPTVAL_OFF" - 1, "$OPTVAL_NO_DOORS" + 1, "$OPTVAL_NODOORS" 2, "$OPTVAL_ON" } From 59bd4d608c767e8a9234268009736d285de5f9c5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 09:59:25 +0100 Subject: [PATCH 39/48] - fixed: Be a bit more paranoid about what to consider a mod with an empty top-level directory. This should only be accepted if the subdirectory contains at least one identifiable game definition lump to avoid catching some patch mods with only a few files. --- src/resourcefiles/file_zip.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index bd2990dec..7b83084ab 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -218,8 +218,11 @@ bool FZipFile::Open(bool quiet) char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; - // Check if all files have the same prefix so that this can be stripped out. FString name0; + bool foundspeciallump = false; + + // Check if all files have the same prefix so that this can be stripped out. + // This will only be done if there is either a MAPINFO, ZMAPINFO or GAMEINFO lump in the subdirectory, denoting a ZDoom mod. if (NumLumps > 1) for (DWORD i = 0; i < NumLumps; i++) { FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; @@ -251,6 +254,7 @@ bool FZipFile::Open(bool quiet) !name.Compare("voxels/") || !name.Compare("colormaps/") || !name.Compare("acs/") || + !name.Compare("maps/") || !name.Compare("voices/") || !name.Compare("patches/") || !name.Compare("graphics/") || @@ -266,6 +270,23 @@ bool FZipFile::Open(bool quiet) name0 = ""; break; } + else if (!foundspeciallump) + { + // at least one of the more common definition lumps must be present. + if (name.IndexOf(name0 + "mapinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "zmapinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "gameinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "sndinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "sbarinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "menudef") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "gldefs") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "animdefs") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "decorate.") == 0) foundspeciallump = true; // DECORATE is a common subdirectory name, so the check needs to be a bit different. + else if (name.Compare(name0 + "decorate") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "zscript.") == 0) foundspeciallump = true; // same here. + else if (name.Compare(name0 + "zscript") == 0) foundspeciallump = true; + else if (name.Compare(name0 + "maps/") == 0) foundspeciallump = true; + } } } From 00dc59ebdce8405578e950324028ddef505ccb11 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 10:26:23 +0100 Subject: [PATCH 40/48] - separated the blood translation index from the BloodColor variable to allow more than 255 blood translations and as a prerequisite for allowing to change the blood color. --- src/actor.h | 7 ++--- src/info.cpp | 1 - src/info.h | 2 -- src/p_actionfunctions.cpp | 3 +- src/p_map.cpp | 9 +++--- src/p_mobj.cpp | 42 ++++++++++++--------------- src/scripting/thingdef_properties.cpp | 7 ++--- wadsrc/static/zscript/actor.txt | 3 +- 8 files changed, 30 insertions(+), 44 deletions(-) diff --git a/src/actor.h b/src/actor.h index 739f08f4a..5cac23011 100644 --- a/src/actor.h +++ b/src/actor.h @@ -807,11 +807,6 @@ public: return (flags & MF_COUNTKILL) && !(flags & MF_FRIENDLY); } - PalEntry GetBloodColor() const - { - return GetClass()->BloodColor; - } - // These also set CF_INTERPVIEW for players. void SetPitch(DAngle p, bool interpolate, bool forceclamp = false); void SetAngle(DAngle ang, bool interpolate); @@ -1144,6 +1139,8 @@ public: BYTE FloatBobPhase; BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc) DWORD Translation; + PalEntry BloodColor; + DWORD BloodTranslation; // [RH] Stuff that used to be part of an Actor Info FSoundIDNoInit SeeSound; diff --git a/src/info.cpp b/src/info.cpp index d51cad115..fdda8633e 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -295,7 +295,6 @@ void PClassActor::DeriveData(PClass *newclass) PClassActor *newa = static_cast(newclass); newa->DefaultStateUsage = DefaultStateUsage; - newa->BloodColor = BloodColor; newa->distancecheck = distancecheck; newa->DropItems = DropItems; diff --git a/src/info.h b/src/info.h index d5e3eff48..6caa27325 100644 --- a/src/info.h +++ b/src/info.h @@ -290,8 +290,6 @@ public: TArray VisibleToPlayerClass; - PalEntry BloodColor; // Colorized blood - FDropItem *DropItems; FString SourceLumpName; FIntCVar *distancecheck; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index b75949f01..c32372b4e 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2580,8 +2580,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) else if (flags & SIXF_USEBLOODCOLOR) { // [XA] Use the spawning actor's BloodColor to translate the newly-spawned object. - PalEntry bloodcolor = self->GetBloodColor(); - mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + mo->Translation = self->BloodTranslation; } } if (flags & SIXF_TRANSFERPOINTERS) diff --git a/src/p_map.cpp b/src/p_map.cpp index 7e110dcbf..4d47b89c1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4803,7 +4803,7 @@ void P_TraceBleed(int damage, const DVector3 &pos, AActor *actor, DAngle angle, { if (bleedtrace.HitType == TRACE_HitWall) { - PalEntry bloodcolor = actor->GetBloodColor(); + PalEntry bloodcolor = actor->BloodColor; if (bloodcolor != 0) { bloodcolor.r >>= 1; // the full color is too bright for blood decals @@ -5994,7 +5994,6 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos) { if (!(thing->flags&MF_NOBLOOD)) { - PalEntry bloodcolor = thing->GetBloodColor(); PClassActor *bloodcls = thing->GetBloodType(); P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing); @@ -6006,9 +6005,9 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos) mo->Vel.X = pr_crunch.Random2() / 16.; mo->Vel.Y = pr_crunch.Random2() / 16.; - if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE)) + if (thing->BloodTranslation != 0 && !(mo->flags2 & MF2_DONTTRANSLATE)) { - mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + mo->Translation = thing->BloodTranslation; } if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; @@ -6017,7 +6016,7 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos) DAngle an = (M_Random() - 128) * (360./256); if (cl_bloodtype >= 1) { - P_DrawSplash2(32, thing->PosPlusZ(thing->Height/2), an, 2, bloodcolor); + P_DrawSplash2(32, thing->PosPlusZ(thing->Height/2), an, 2, thing->BloodColor); } } if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b4affd539..db8964ef4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -316,8 +316,8 @@ DEFINE_FIELD(AActor, RadiusDamageFactor) DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(AActor, WoundHealth) - -//DEFINE_FIELD(PClassActor, BloodColor) +DEFINE_FIELD(AActor, BloodColor) +DEFINE_FIELD(AActor, BloodTranslation) //========================================================================== // @@ -409,6 +409,8 @@ void AActor::Serialize(FSerializer &arc) A("inventoryid", InventoryID) A("floatbobphase", FloatBobPhase) A("translation", Translation) + A("bloodcolor", BloodColor) + A("bloodtranslation", BloodTranslation) A("seesound", SeeSound) A("attacksound", AttackSound) A("paimsound", PainSound) @@ -1665,8 +1667,7 @@ bool AActor::Grind(bool items) if (isgeneric) // Not a custom crush state, so colorize it appropriately. { S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE); - PalEntry bloodcolor = GetBloodColor(); - if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + Translation = BloodTranslation; } return false; } @@ -1707,10 +1708,7 @@ bool AActor::Grind(bool items) gib->Alpha = Alpha; gib->Height = 0; gib->radius = 0; - - PalEntry bloodcolor = GetBloodColor(); - if (bloodcolor != 0) - gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + gib->Translation = BloodTranslation; } S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE); } @@ -6051,7 +6049,6 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPuff) void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) { AActor *th; - PalEntry bloodcolor = originator->GetBloodColor(); PClassActor *bloodcls = originator->GetBloodType(); DVector3 pos = pos1; pos.Z += pr_spawnblood.Random2() / 64.; @@ -6076,9 +6073,9 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina th->tics = 1; } // colorize the blood - if (bloodcolor != 0 && !(th->flags2 & MF2_DONTTRANSLATE)) + if (!(th->flags2 & MF2_DONTTRANSLATE)) { - th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + th->Translation = originator->BloodTranslation; } // Moved out of the blood actor so that replacing blood is easier @@ -6135,7 +6132,7 @@ void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *origina } if (bloodtype >= 1) - P_DrawSplash2 (40, pos, dir, 2, bloodcolor); + P_DrawSplash2 (40, pos, dir, 2, originator->BloodColor); } DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) @@ -6159,7 +6156,6 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnBlood) void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle) { - PalEntry bloodcolor = originator->GetBloodColor(); PClassActor *bloodcls = originator->GetBloodType(1); int bloodtype = cl_bloodtype; @@ -6178,16 +6174,16 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle) mo->Vel.Z = 3; // colorize the blood! - if (bloodcolor!=0 && !(mo->flags2 & MF2_DONTTRANSLATE)) + if (!(mo->flags2 & MF2_DONTTRANSLATE)) { - mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + mo->Translation = originator->BloodTranslation; } if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { - P_DrawSplash2 (40, pos, hitangle-180., 2, bloodcolor); + P_DrawSplash2 (40, pos, hitangle-180., 2, originator->BloodColor); } } @@ -6199,7 +6195,6 @@ void P_BloodSplatter (const DVector3 &pos, AActor *originator, DAngle hitangle) void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle) { - PalEntry bloodcolor = originator->GetBloodColor(); PClassActor *bloodcls = originator->GetBloodType(2); int bloodtype = cl_bloodtype; @@ -6220,16 +6215,16 @@ void P_BloodSplatter2 (const DVector3 &pos, AActor *originator, DAngle hitangle) mo->target = originator; // colorize the blood! - if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE)) + if (!(mo->flags2 & MF2_DONTTRANSLATE)) { - mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + mo->Translation = originator->BloodTranslation; } if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { - P_DrawSplash2(40, pos + add, hitangle - 180., 2, bloodcolor); + P_DrawSplash2(40, pos + add, hitangle - 180., 2, originator->BloodColor); } } @@ -6255,7 +6250,6 @@ DEFINE_ACTION_FUNCTION(AActor, BloodSplatter) void P_RipperBlood (AActor *mo, AActor *bleeder) { - PalEntry bloodcolor = bleeder->GetBloodColor(); PClassActor *bloodcls = bleeder->GetBloodType(); double xo = pr_ripperblood.Random2() / 16.; @@ -6281,16 +6275,16 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) th->tics += pr_ripperblood () & 3; // colorize the blood! - if (bloodcolor!=0 && !(th->flags2 & MF2_DONTTRANSLATE)) + if (!(th->flags2 & MF2_DONTTRANSLATE)) { - th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); + th->Translation = bleeder->BloodTranslation; } if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { - P_DrawSplash2(28, pos, bleeder->AngleTo(mo) + 180., 0, bloodcolor); + P_DrawSplash2(28, pos, bleeder->AngleTo(mo) + 180., 0, bleeder->BloodColor); } } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index af79e1d04..6212f0ff1 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1053,10 +1053,9 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) { PROP_COLOR_PARM(color, 0); - PalEntry pe = color; - pe.a = CreateBloodTranslation(pe); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->BloodColor = pe; + defaults->BloodColor = color; + defaults->BloodColor.a = 255; // a should not be 0. + defaults->BloodTranslation = TRANSLATION(TRANSLATION_Blood, CreateBloodTranslation(color)); } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4c62863df..148fd4bd5 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -194,7 +194,8 @@ class Actor : Thinker native native double SelfDamageFactor; native double StealthAlpha; native int WoundHealth; // Health needed to enter wound state - //native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit. + native readonly color BloodColor; + native readonly int BloodTranslation; meta String Obituary; // Player was killed by this actor meta String HitObituary; // Player was killed by this actor in melee From b194ba205ac8752593b4101bc3c7cbd0e9f72a99 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 11:39:52 +0100 Subject: [PATCH 41/48] - backported Zandronum's MaxHealth base class for the MaxHealthBonus item. --- src/d_player.h | 2 ++ src/p_acs.cpp | 4 +-- src/p_mobj.cpp | 4 +-- src/p_user.cpp | 4 ++- wadsrc/static/zscript/inventory/health.txt | 30 +++++++++++++++++++++- wadsrc/static/zscript/shared/player.txt | 1 + 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 2787df231..379265cab 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -125,6 +125,8 @@ public: int crouchsprite; int MaxHealth; + int BonusHealth; + int MugShotMaxHealth; int RunHealth; int PlayerFlags; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 5ea7dfa07..4e1b7a026 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1330,7 +1330,7 @@ static int CheckInventory (AActor *activator, const char *type, bool max) if (max) { if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn))) - return static_cast(activator)->MaxHealth; + return static_cast(activator)->GetMaxHealth(); else return activator->SpawnHealth(); } @@ -3939,7 +3939,7 @@ int DLevelScript::GetActorProperty (int tid, int property) case APROP_Dormant: return !!(actor->flags2 & MF2_DORMANT); case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) { - return static_cast(actor)->MaxHealth; + return static_cast(actor)->GetMaxHealth(); } else { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index db8964ef4..99f48a702 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1340,7 +1340,7 @@ bool P_GiveBody(AActor *actor, int num, int max) { if (!(player->MorphStyle & MORPH_ADDSTAMINA)) { - max -= player->mo->stamina; + max -= player->mo->stamina + player->mo->BonusHealth; } } else // old health behaviour @@ -1348,7 +1348,7 @@ bool P_GiveBody(AActor *actor, int num, int max) max = MAXMORPHHEALTH; if (player->MorphStyle & MORPH_ADDSTAMINA) { - max += player->mo->stamina; + max += player->mo->stamina + player->mo->BonusHealth; } } } diff --git a/src/p_user.cpp b/src/p_user.cpp index ab4390ba2..9b65b559f 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -781,6 +781,7 @@ void APlayerPawn::Serialize(FSerializer &arc) arc("jumpz", JumpZ, def->JumpZ) ("maxhealth", MaxHealth, def->MaxHealth) + ("bonushealth", BonusHealth, def->BonusHealth) ("runhealth", RunHealth, def->RunHealth) ("spawnmask", SpawnMask, def->SpawnMask) ("forwardmove1", ForwardMove1, def->ForwardMove1) @@ -1353,7 +1354,7 @@ const char *APlayerPawn::GetSoundClass() const int APlayerPawn::GetMaxHealth(bool withupgrades) const { int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); - if (withupgrades) ret += stamina; + if (withupgrades) ret += stamina + BonusHealth; return ret; } @@ -3345,6 +3346,7 @@ bool P_IsPlayerTotallyFrozen(const player_t *player) DEFINE_FIELD(APlayerPawn, crouchsprite) DEFINE_FIELD(APlayerPawn, MaxHealth) +DEFINE_FIELD(APlayerPawn, BonusHealth) DEFINE_FIELD(APlayerPawn, MugShotMaxHealth) DEFINE_FIELD(APlayerPawn, RunHealth) DEFINE_FIELD(APlayerPawn, PlayerFlags) diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index e64bbfd4a..986dc7069 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -86,8 +86,36 @@ class Health : Inventory } return false; } +} - +class MaxHealth : Health +{ + //=========================================================================== + // + // TryPickup + // + //=========================================================================== + + override bool TryPickup (in out Actor other) + { + bool success = false; + int savedAmount = MaxAmount; + let player = PlayerPawn(other); + MaxAmount = Health; + if (player) + { + if (player.BonusHealth < savedAmount) + { + player.BonusHealth = min(player.BonusHealth + Amount, savedAmount); + success = true; + } + MaxAmount += player.BonusHealth; + } + success |= Super.TryPickup(other); + MaxAmount = saved; + if (success) GoAwayAndDie(); + return success; + } } class HealthPickup : Inventory diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 97e065c2a..a80210714 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -3,6 +3,7 @@ class PlayerPawn : Actor native native int crouchsprite; native int MaxHealth; + native int BonusHealth; native int MugShotMaxHealth; native int RunHealth; native int PlayerFlags; From cfda1a49d427918ad94d873ac477a3fa5734694a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 11:58:30 +0100 Subject: [PATCH 42/48] - forgot to save the last fix for the previous commit. - let the script compiler also output the size of the allocated data for the script functions in addition to the actual code size. --- src/scripting/backend/vmbuilder.cpp | 6 +++++- wadsrc/static/zscript/inventory/health.txt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/scripting/backend/vmbuilder.cpp b/src/scripting/backend/vmbuilder.cpp index 74f845248..3be1000c5 100644 --- a/src/scripting/backend/vmbuilder.cpp +++ b/src/scripting/backend/vmbuilder.cpp @@ -846,6 +846,7 @@ void FFunctionBuildList::Build() { int errorcount = 0; int codesize = 0; + int datasize = 0; FILE *dump = nullptr; if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w"); @@ -927,6 +928,8 @@ void FFunctionBuildList::Build() { DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len()); codesize += sfunc->CodeSize; + datasize += sfunc->LineInfoCount * sizeof(FStatementInfo) + sfunc->ExtraSpace + sfunc->NumKonstD * sizeof(int) + + sfunc->NumKonstA * sizeof(void*) + sfunc->NumKonstF * sizeof(double) + sfunc->NumKonstS * sizeof(FString); } sfunc->Unsafe = ctx.Unsafe; } @@ -944,10 +947,11 @@ void FFunctionBuildList::Build() } if (dump != nullptr) { - fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4); + fprintf(dump, "\n*************************************************************************\n%i code bytes\n%i data bytes", codesize * 4, datasize); fclose(dump); } FScriptPosition::StrictErrors = false; mItems.Clear(); + mItems.ShrinkToFit(); FxAlloc.FreeAllBlocks(); } \ No newline at end of file diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index 986dc7069..e69d85814 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -112,7 +112,7 @@ class MaxHealth : Health MaxAmount += player.BonusHealth; } success |= Super.TryPickup(other); - MaxAmount = saved; + MaxAmount = savedAmount; if (success) GoAwayAndDie(); return success; } From 3532e5057548497c1aa964f6e410217e5a6f6aa4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 12:14:00 +0100 Subject: [PATCH 43/48] - check for RF_MASKROTATION before calling IsInsideVisibleAngles, because it is a bit faster this way. --- src/gl/scene/gl_sprite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 5e8bdb560..3a6abb319 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -665,7 +665,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) bool isPicnumOverride = thing->picnum.isValid(); // Don't waste time projecting sprites that are definitely not visible. - if ((thing->sprite == 0 && !isPicnumOverride) || !thing->IsVisibleToPlayer() || !thing->IsInsideVisibleAngles()) + if ((thing->sprite == 0 && !isPicnumOverride) || !thing->IsVisibleToPlayer() || ((thing->renderflags & RF_MASKROTATION) && !thing->IsInsideVisibleAngles())) { return; } From 4dc0599a6c63a1c40fc854d2abe1f825aed0135b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 12:37:25 +0100 Subject: [PATCH 44/48] - did a bit of reordering AActor's variables to group the ones together which are accessed by the renderer. Tested with some actor-heavy maps this does provide a small, approx 3-4% speedup in the OpenGL sprite processing function. --- src/actor.h | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/actor.h b/src/actor.h index 5cac23011..4d1c7556b 100644 --- a/src/actor.h +++ b/src/actor.h @@ -978,30 +978,43 @@ public: // NOTE: The first member variable *must* be snext. AActor *snext, **sprev; // links in sector (if needed) DVector3 __Pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions. - DVector3 OldRenderPos; DAngle SpriteAngle; DAngle SpriteRotation; - DAngle VisibleStartAngle; - DAngle VisibleStartPitch; - DAngle VisibleEndAngle; - DAngle VisibleEndPitch; DRotator Angles; - DVector3 Vel; - double Speed; - double FloatSpeed; + DVector2 Scale; // Scaling values; 1 is normal size int sprite; // used to find patch_t and flip value uint8_t frame; // sprite frame to draw uint8_t effects; // [RH] see p_effect.h uint8_t fountaincolor; // Split out of 'effect' to have easier access. - DVector2 Scale; // Scaling values; 1 is normal size FRenderStyle RenderStyle; // Style to draw this actor with ActorRenderFlags renderflags; // Different rendering flags FTextureID picnum; // Draw this instead of sprite if valid double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. DWORD fillcolor; // Color to draw when STYLE_Shaded + ActorFlags flags; + ActorFlags2 flags2; // Heretic flags + ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable + ActorFlags4 flags4; // [RH] Even more flags! + ActorFlags5 flags5; // OMG! We need another one. + ActorFlags6 flags6; // Shit! Where did all the flags go? + ActorFlags7 flags7; // WHO WANTS TO BET ON 8!? + double Floorclip; // value to use for floor clipping + DWORD Translation; + + + DAngle VisibleStartAngle; + DAngle VisibleStartPitch; + DAngle VisibleEndAngle; + DAngle VisibleEndPitch; + + DVector3 OldRenderPos; + DVector3 Vel; + double Speed; + double FloatSpeed; + // interaction info FBlockNode *BlockNode; // links in blocks (if needed) struct sector_t *Sector; @@ -1031,13 +1044,6 @@ public: int DamageVal; VMFunction *DamageFunc; int projectileKickback; - ActorFlags flags; - ActorFlags2 flags2; // Heretic flags - ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable - ActorFlags4 flags4; // [RH] Even more flags! - ActorFlags5 flags5; // OMG! We need another one. - ActorFlags6 flags6; // Shit! Where did all the flags go? - ActorFlags7 flags7; // WHO WANTS TO BET ON 8!? // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it. DWORD VisibleToTeam; @@ -1075,7 +1081,6 @@ public: TObjPtr alternative; // (Un)Morphed actors stored here. Those with the MF_UNMORPHED flag are the originals. TObjPtr tracer; // Thing being chased/attacked for tracers TObjPtr master; // Thing which spawned this one (prevents mutual attacks) - double Floorclip; // value to use for floor clipping int tid; // thing identifier int special; // special @@ -1138,7 +1143,6 @@ public: BYTE smokecounter; BYTE FloatBobPhase; BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc) - DWORD Translation; PalEntry BloodColor; DWORD BloodTranslation; From ff88ecd3f00f4e8822cc1f10c4afd8eeadec841b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 12:55:04 +0100 Subject: [PATCH 45/48] - a bit more reordering for another minor performance gain. --- src/actor.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/actor.h b/src/actor.h index 4d1c7556b..9fc1d10f1 100644 --- a/src/actor.h +++ b/src/actor.h @@ -983,17 +983,18 @@ public: DAngle SpriteRotation; DRotator Angles; DVector2 Scale; // Scaling values; 1 is normal size + double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. int sprite; // used to find patch_t and flip value uint8_t frame; // sprite frame to draw uint8_t effects; // [RH] see p_effect.h uint8_t fountaincolor; // Split out of 'effect' to have easier access. FRenderStyle RenderStyle; // Style to draw this actor with - ActorRenderFlags renderflags; // Different rendering flags FTextureID picnum; // Draw this instead of sprite if valid - double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. DWORD fillcolor; // Color to draw when STYLE_Shaded + DWORD Translation; + ActorRenderFlags renderflags; // Different rendering flags ActorFlags flags; ActorFlags2 flags2; // Heretic flags ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable @@ -1002,8 +1003,7 @@ public: ActorFlags6 flags6; // Shit! Where did all the flags go? ActorFlags7 flags7; // WHO WANTS TO BET ON 8!? double Floorclip; // value to use for floor clipping - DWORD Translation; - + double radius, Height; // for movement checking DAngle VisibleStartAngle; DAngle VisibleStartPitch; @@ -1027,7 +1027,6 @@ public: int floorterrain; struct sector_t *ceilingsector; FTextureID ceilingpic; // contacted sec ceilingpic - double radius, Height; // for movement checking double renderradius; double projectilepassheight; // height for clipping projectile movement against this actor From 26f7902c3f5f9f6c007a2ce6731e31a877e31291 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 2 Mar 2017 06:27:18 -0500 Subject: [PATCH 46/48] - fixed: If player is killed by world, attacker was not checked for nullptr, causing a crash. --- src/p_interaction.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b4cb5d16f..9629ccfe8 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -253,6 +253,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf } } if (message == nullptr) message = messagename; // fallback to defaults if possible. + if (attacker == nullptr) attacker = self; // world if (attacker->player == nullptr) attacker = self; // for the message creation if (message != NULL && message[0] == '$') From 62dd810a4edec42e1e9860531da11dcd0e75f6cc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 13:09:25 +0100 Subject: [PATCH 47/48] - fixed: A_ProgrammerMelee damaged the caller, not the target. --- wadsrc/static/zscript/strife/programmer.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt index 3fa34b659..90cdd5399 100644 --- a/wadsrc/static/zscript/strife/programmer.txt +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -95,7 +95,7 @@ class Programmer : Actor A_PlaySound("programmer/clank", CHAN_WEAPON); int damage = ((random[Programmer]() % 10) + 1) * 6; - int newdam = DamageMobj (self, self, damage, 'Melee'); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); target.TraceBleed (newdam > 0 ? newdam : damage, self); } From e64f1e645da0d3e9e1e9083a038dbc08f06f87ee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 2 Mar 2017 13:14:16 +0100 Subject: [PATCH 48/48] - exported constants for SetGlobalFogParameter to ZScript. --- wadsrc/static/zscript/constants.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index c15433cd6..1982c4472 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1005,6 +1005,13 @@ enum ERaise RF_NOCHECKPOSITION = 2 } +enum eFogParm +{ + FOGP_DENSITY = 0, + FOGP_OUTSIDEDENSITY = 1, + FOGP_SKYFOG = 2, +} + enum ETeleport { TELF_DESTFOG = 1,