diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 553c75360..eeb3c2a56 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/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/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/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/g_level.cpp b/src/g_level.cpp index f346f8f48..1dabfd2cc 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1625,6 +1625,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/info.cpp b/src/info.cpp index 84d8e26be..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; @@ -868,7 +870,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(); 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/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/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_acs.cpp b/src/p_acs.cpp index ad66627f5..baf15c110 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4367,6 +4367,10 @@ enum EACSFunctions ACSF_SetTranslation, ACSF_GetActorFloorTexture, ACSF_GetActorFloorTerrain, + ACSF_StrArg, + ACSF_Floor, + ACSF_Ceil, + ACSF_Round, // OpenGL stuff @@ -6087,7 +6091,17 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } + 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; 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_mobj.cpp b/src/p_mobj.cpp index f85f2c9eb..f38ac12bb 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; } } @@ -5929,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; @@ -6008,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/src/p_pspr.cpp b/src/p_pspr.cpp index da1ad605c..1f036d1ff 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -540,6 +540,7 @@ void P_FireWeapon (player_t *player, FState *state) return; } + player->WeaponState &= ~WF_WEAPONBOBBING; player->mo->PlayAttacking (); weapon->bAltFire = false; if (state == nullptr) @@ -576,6 +577,7 @@ void P_FireWeaponAlt (player_t *player, FState *state) return; } + player->WeaponState &= ~WF_WEAPONBOBBING; player->mo->PlayAttacking (); weapon->bAltFire = true; 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_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 diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index b9300f654..4d5e00e48 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -515,11 +515,10 @@ public: FString arg0str, arg1str; memset(th, 0, sizeof(*th)); - double healthfactor = 1; th->Gravity = 1; th->RenderStyle = STYLE_Count; th->Alpha = -1; - th->health = 1; + th->Health = 1; th->FloatbobPhase = -1; sc.MustGetToken('{'); while (!sc.CheckToken('}')) @@ -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); + th->Health = 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) 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; +} + //========================================================================== // //========================================================================== 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); diff --git a/src/version.h b/src/version.h index 3b40c2cd6..22b8c30b7 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 235 +#define NETGAMEVERSION 233 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 63900301e..ef2032241 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -651,6 +651,7 @@ OptionValue PuffTypes { 0.0, "$OPTVAL_SPRITES" 1.0, "$OPTVAL_PARTICLES" + 2.0, "$OPTVAL_SPRITESPARTICLES" } OptionValue Wipes