# Conflicts:
#	src/version.h
This commit is contained in:
Rachael Alexanderson 2017-02-28 04:46:23 -05:00
commit 5aec906031
25 changed files with 163 additions and 71 deletions

View file

@ -263,8 +263,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property, gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.0. // negative values are used as their absolute. Default = 1.0.
health = <int>; // Set per-actor health as an absolute value. Default = actor default. health = <float>; // Set per-actor health. Positive values are multiplied with the class's property,
healthfactor = <float>; // Set per-actor health as a factor to the original. Default = 1. // negative values are used as their absolute. Default = 1.
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal", renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",

View file

@ -260,5 +260,7 @@ DEFINE_SPECIAL(Stairs_BuildUpDoomSync, 271, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildDownDoomSync, 272, 4, 4, 4) DEFINE_SPECIAL(Stairs_BuildDownDoomSync, 272, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildUpDoomCrush, 273, 5, 5, 5) DEFINE_SPECIAL(Stairs_BuildUpDoomCrush, 273, 5, 5, 5)
DEFINE_SPECIAL(Door_AnimatedClose, 274, 4, 4, 4) 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 #undef DEFINE_SPECIAL

View file

@ -2380,6 +2380,11 @@ void Net_DoCommand (int type, BYTE **stream, int player)
SprayDecal(players[player].mo, s); SprayDecal(players[player].mo, s);
break; break;
case DEM_MDK:
s = ReadString(stream);
cht_DoMDK(&players[player], s);
break;
case DEM_PAUSE: case DEM_PAUSE:
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -2666,13 +2671,12 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_NETEVENT: case DEM_NETEVENT:
{ {
const char *ename = ReadString(stream); s = ReadString(stream);
int argn = ReadByte(stream); int argn = ReadByte(stream);
int arg[3] = { 0, 0, 0 }; int arg[3] = { 0, 0, 0 };
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
arg[i] = ReadLong(stream); arg[i] = ReadLong(stream);
E_Console(player, ename, arg[0], arg[1], arg[2]); E_Console(player, s, arg[0], arg[1], arg[2]);
delete[] ename;
} }
break; break;
@ -2723,7 +2727,7 @@ void Net_SkipCommand (int type, BYTE **stream)
break; break;
case DEM_NETEVENT: case DEM_NETEVENT:
skip = strlen((char *)(*stream)) + 13; skip = strlen((char *)(*stream)) + 14;
break; break;
case DEM_SUMMON2: case DEM_SUMMON2:
@ -2747,6 +2751,7 @@ void Net_SkipCommand (int type, BYTE **stream)
case DEM_SPRAY: case DEM_SPRAY:
case DEM_MORPHEX: case DEM_MORPHEX:
case DEM_KILLCLASSCHEAT: case DEM_KILLCLASSCHEAT:
case DEM_MDK:
skip = strlen ((char *)(*stream)) + 1; skip = strlen ((char *)(*stream)) + 1;
break; break;

View file

@ -159,7 +159,8 @@ enum EDemoCommand
DEM_SETSLOTPNUM, // 67 Byte: player number, the rest is the same as DEM_SETSLOT DEM_SETSLOTPNUM, // 67 Byte: player number, the rest is the same as DEM_SETSLOT
DEM_REMOVE, // 68 DEM_REMOVE, // 68
DEM_FINISHGAME, // 69 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 // The following are implemented by cht_DoCheat in m_cheat.cpp

View file

@ -359,7 +359,7 @@ struct FMapThing
double Alpha; double Alpha;
DWORD fillcolor; DWORD fillcolor;
DVector2 Scale; DVector2 Scale;
int health; double Health;
int score; int score;
short pitch; short pitch;
short roll; short roll;

View file

@ -1625,6 +1625,7 @@ void G_UnSnapshotLevel (bool hubLoad)
} }
} }
} }
arc.Close();
} }
// No reason to keep the snapshot around once the level's been entered. // No reason to keep the snapshot around once the level's been entered.
level.info->Snapshot.Clean(); level.info->Snapshot.Clean();

View file

@ -258,6 +258,7 @@ PClassActor::PClassActor()
FastSpeed = -1.; FastSpeed = -1.;
RDFactor = 1.; RDFactor = 1.;
SelfDamageFactor = 1.; SelfDamageFactor = 1.;
StealthAlpha = 0.;
CameraHeight = INT_MIN; CameraHeight = INT_MIN;
DropItems = NULL; DropItems = NULL;
@ -319,6 +320,7 @@ void PClassActor::DeriveData(PClass *newclass)
newa->FastSpeed = FastSpeed; newa->FastSpeed = FastSpeed;
newa->RDFactor = RDFactor; newa->RDFactor = RDFactor;
newa->SelfDamageFactor = SelfDamageFactor; newa->SelfDamageFactor = SelfDamageFactor;
newa->StealthAlpha = StealthAlpha;
newa->CameraHeight = CameraHeight; newa->CameraHeight = CameraHeight;
newa->HowlSound = HowlSound; newa->HowlSound = HowlSound;
newa->BloodType = BloodType; newa->BloodType = BloodType;
@ -868,7 +870,7 @@ void FMapInfoParser::ParseDamageDefinition()
dtd.DefaultFactor = sc.Float; dtd.DefaultFactor = sc.Float;
if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true; if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true;
} }
if (sc.Compare("OBITUARY")) else if (sc.Compare("OBITUARY"))
{ {
sc.MustGetStringName("="); sc.MustGetStringName("=");
sc.MustGetString(); sc.MustGetString();

View file

@ -301,6 +301,7 @@ public:
double RDFactor; // Radius damage factor double RDFactor; // Radius damage factor
double SelfDamageFactor; double SelfDamageFactor;
double CameraHeight; // Height of camera when used as such 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 FSoundID HowlSound; // Sound being played when electrocuted or poisoned
FName BloodType; // Blood replacement type FName BloodType; // Blood replacement type
FName BloodType2; // Bloopsplatter replacement type FName BloodType2; // Bloopsplatter replacement type

View file

@ -55,6 +55,22 @@
// writes some bytes to the network data stream, and the network code // writes some bytes to the network data stream, and the network code
// later calls us. // 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) void cht_DoCheat (player_t *player, int cheat)
{ {
static const char * const BeholdPowers[9] = static const char * const BeholdPowers[9] =
@ -671,6 +687,7 @@ CCMD (mdk)
if (CheckCheatmode ()) if (CheckCheatmode ())
return; return;
Net_WriteByte (DEM_GENERICCHEAT); const char *name = argv.argc() > 1 ? argv[1] : "";
Net_WriteByte (CHT_MDK); Net_WriteByte (DEM_MDK);
Net_WriteString(name);
} }

View file

@ -31,6 +31,7 @@
class player_t; class player_t;
class PClassActor; class PClassActor;
void cht_DoMDK(player_t *player, const char *mod);
void cht_DoCheat (player_t *player, int cheat); void cht_DoCheat (player_t *player, int cheat);
void cht_Give (player_t *player, const char *item, int amount=1); void cht_Give (player_t *player, const char *item, int amount=1);
void cht_Take (player_t *player, const char *item, int amount=1); void cht_Take (player_t *player, const char *item, int amount=1);

View file

@ -46,7 +46,6 @@ xx(Shadow)
xx(Subtract) xx(Subtract)
xx(Subtractive) xx(Subtractive)
xx(FillColor) xx(FillColor)
xx(HealthFactor)
// Healingradius types // Healingradius types
xx(Mana) xx(Mana)

View file

@ -4367,6 +4367,10 @@ enum EACSFunctions
ACSF_SetTranslation, ACSF_SetTranslation,
ACSF_GetActorFloorTexture, ACSF_GetActorFloorTexture,
ACSF_GetActorFloorTerrain, ACSF_GetActorFloorTerrain,
ACSF_StrArg,
ACSF_Floor,
ACSF_Ceil,
ACSF_Round,
// OpenGL stuff // OpenGL stuff
@ -6087,7 +6091,17 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
break; 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: default:
break; break;

View file

@ -582,3 +582,18 @@ bool EV_CeilingCrushStop (int tag, bool remove)
return rtn; 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;
}

View file

@ -561,6 +561,21 @@ bool EV_FloorCrushStop (int tag)
return true; 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! // BUILD A STAIRCASE!

View file

@ -563,6 +563,13 @@ FUNC(LS_Generic_Floor)
} }
FUNC(LS_Floor_Stop)
// Floor_Stop (tag)
{
return EV_StopFloor(arg0);
}
FUNC(LS_Stairs_BuildDown) FUNC(LS_Stairs_BuildDown)
// Stair_BuildDown (tag, speed, height, delay, reset) // 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)); 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) FUNC(LS_Generic_Ceiling)
// Generic_Ceiling (tag, speed, height, target, change/model/direct/crush) // Generic_Ceiling (tag, speed, height, target, change/model/direct/crush)
{ {
@ -3614,6 +3628,8 @@ static lnSpecFunc LineSpecials[] =
/* 272 */ LS_Stairs_BuildDownDoomSync, /* 272 */ LS_Stairs_BuildDownDoomSync,
/* 273 */ LS_Stairs_BuildUpDoomCrush, /* 273 */ LS_Stairs_BuildUpDoomCrush,
/* 274 */ LS_Door_AnimatedClose, /* 274 */ LS_Door_AnimatedClose,
/* 275 */ LS_Floor_Stop,
/* 276 */ LS_Ceiling_Stop,
}; };

View file

@ -322,6 +322,7 @@ DEFINE_FIELD(PClassActor, WoundHealth)
DEFINE_FIELD(PClassActor, FastSpeed) DEFINE_FIELD(PClassActor, FastSpeed)
DEFINE_FIELD(PClassActor, RDFactor) DEFINE_FIELD(PClassActor, RDFactor)
DEFINE_FIELD(PClassActor, SelfDamageFactor) DEFINE_FIELD(PClassActor, SelfDamageFactor)
DEFINE_FIELD(PClassActor, StealthAlpha)
DEFINE_FIELD(PClassActor, CameraHeight) DEFINE_FIELD(PClassActor, CameraHeight)
DEFINE_FIELD(PClassActor, HowlSound) DEFINE_FIELD(PClassActor, HowlSound)
DEFINE_FIELD(PClassActor, BloodType) DEFINE_FIELD(PClassActor, BloodType)
@ -4100,9 +4101,9 @@ void AActor::Tick ()
else if (visdir < 0) else if (visdir < 0)
{ {
Alpha -= 1.5/TICRATE; Alpha -= 1.5/TICRATE;
if (Alpha < 0) if (Alpha < GetClass()->StealthAlpha)
{ {
Alpha = 0; Alpha = GetClass()->StealthAlpha;
visdir = 0; visdir = 0;
} }
} }
@ -5929,13 +5930,13 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
mobj->LevelSpawned (); mobj->LevelSpawned ();
} }
if (mthing->health > 0) if (mthing->Health > 0)
mobj->health *= mthing->health; mobj->health = int(mobj->health * mthing->Health);
else else
mobj->health = -mthing->health; mobj->health = -int(mthing->Health);
if (mthing->health == 0) if (mthing->Health == 0)
mobj->CallDie(NULL, NULL); mobj->CallDie(NULL, NULL);
else if (mthing->health != 1) else if (mthing->Health != 1)
mobj->StartHealth = mobj->health; mobj->StartHealth = mobj->health;
return mobj; 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)) if (cl_pufftype && updown != 3 && (puff->flags4 & MF4_ALLOWPARTICLES))
{ {
P_DrawSplash2 (32, pos, particledir, updown, 1); 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) if ((flags & PF_HITTHING) && puff->SeeSound)

View file

@ -540,6 +540,7 @@ void P_FireWeapon (player_t *player, FState *state)
return; return;
} }
player->WeaponState &= ~WF_WEAPONBOBBING;
player->mo->PlayAttacking (); player->mo->PlayAttacking ();
weapon->bAltFire = false; weapon->bAltFire = false;
if (state == nullptr) if (state == nullptr)
@ -576,6 +577,7 @@ void P_FireWeaponAlt (player_t *player, FState *state)
return; return;
} }
player->WeaponState &= ~WF_WEAPONBOBBING;
player->mo->PlayAttacking (); player->mo->PlayAttacking ();
weapon->bAltFire = true; weapon->bAltFire = true;

View file

@ -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].ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes
mti[i].RenderStyle = STYLE_Count; mti[i].RenderStyle = STYLE_Count;
mti[i].Alpha = -1; mti[i].Alpha = -1;
mti[i].health = 1; mti[i].Health = 1;
mti[i].FloatbobPhase = -1; mti[i].FloatbobPhase = -1;
mti[i].pos.X = LittleShort(mt->x); mti[i].pos.X = LittleShort(mt->x);
@ -1837,7 +1837,7 @@ void P_LoadThings2 (MapData * map)
mti[i].Gravity = 1; mti[i].Gravity = 1;
mti[i].RenderStyle = STYLE_Count; mti[i].RenderStyle = STYLE_Count;
mti[i].Alpha = -1; mti[i].Alpha = -1;
mti[i].health = 1; mti[i].Health = 1;
mti[i].FloatbobPhase = -1; mti[i].FloatbobPhase = -1;
} }
delete[] mtp; delete[] mtp;

View file

@ -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_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_CeilingCrushStop (int tag, bool remove);
bool EV_StopCeiling(int tag);
void P_ActivateInStasisCeiling (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); double speed, double height, int crush, int change, bool hexencrush, bool hereticlower = false);
bool EV_FloorCrushStop (int tag); bool EV_FloorCrushStop (int tag);
bool EV_StopFloor(int tag);
bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed); bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed);
class DElevator : public DMover class DElevator : public DMover

View file

@ -515,11 +515,10 @@ public:
FString arg0str, arg1str; FString arg0str, arg1str;
memset(th, 0, sizeof(*th)); memset(th, 0, sizeof(*th));
double healthfactor = 1;
th->Gravity = 1; th->Gravity = 1;
th->RenderStyle = STYLE_Count; th->RenderStyle = STYLE_Count;
th->Alpha = -1; th->Alpha = -1;
th->health = 1; th->Health = 1;
th->FloatbobPhase = -1; th->FloatbobPhase = -1;
sc.MustGetToken('{'); sc.MustGetToken('{');
while (!sc.CheckToken('}')) while (!sc.CheckToken('}'))
@ -739,52 +738,38 @@ public:
break; break;
case NAME_Alpha: case NAME_Alpha:
CHECK_N(Zd | Zdt)
th->Alpha = CheckFloat(key); th->Alpha = CheckFloat(key);
break; break;
case NAME_FillColor: case NAME_FillColor:
CHECK_N(Zd | Zdt)
th->fillcolor = CheckInt(key); th->fillcolor = CheckInt(key);
break; break;
case NAME_Health: case NAME_Health:
CHECK_N(Zd | Zdt) th->Health = CheckFloat(key);
th->health = CheckInt(key);
break;
case NAME_HealthFactor:
CHECK_N(Zd | Zdt)
healthfactor = CheckFloat(key);
break; break;
case NAME_Score: case NAME_Score:
CHECK_N(Zd | Zdt)
th->score = CheckInt(key); th->score = CheckInt(key);
break; break;
case NAME_Pitch: case NAME_Pitch:
CHECK_N(Zd | Zdt)
th->pitch = (short)CheckInt(key); th->pitch = (short)CheckInt(key);
break; break;
case NAME_Roll: case NAME_Roll:
CHECK_N(Zd | Zdt)
th->roll = (short)CheckInt(key); th->roll = (short)CheckInt(key);
break; break;
case NAME_ScaleX: case NAME_ScaleX:
CHECK_N(Zd | Zdt)
th->Scale.X = CheckFloat(key); th->Scale.X = CheckFloat(key);
break; break;
case NAME_ScaleY: case NAME_ScaleY:
CHECK_N(Zd | Zdt)
th->Scale.Y = CheckFloat(key); th->Scale.Y = CheckFloat(key);
break; break;
case NAME_Scale: case NAME_Scale:
CHECK_N(Zd | Zdt)
th->Scale.X = th->Scale.Y = CheckFloat(key); th->Scale.X = th->Scale.Y = CheckFloat(key);
break; break;
@ -808,7 +793,6 @@ public:
{ {
th->args[1] = -FName(arg1str); th->args[1] = -FName(arg1str);
} }
th->health = int(th->health * healthfactor);
// Thing specials are only valid in namespaces with Hexen-type specials // Thing specials are only valid in namespaces with Hexen-type specials
// and in ZDoomTranslated - which will use the translator on them. // and in ZDoomTranslated - which will use the translator on them.
if (namespc == NAME_ZDoomTranslated) if (namespc == NAME_ZDoomTranslated)

View file

@ -1440,6 +1440,16 @@ DEFINE_PROPERTY(selfdamagefactor, F, Actor)
static_cast<PClassActor *>(info)->SelfDamageFactor = i; static_cast<PClassActor *>(info)->SelfDamageFactor = i;
} }
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(stealthalpha, F, Actor)
{
PROP_DOUBLE_PARM(i, 0);
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->StealthAlpha = i;
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================

View file

@ -486,6 +486,8 @@ bool FSerializer::OpenReader(FCompressedBuffer *input)
void FSerializer::Close() void FSerializer::Close()
{ {
if (w == nullptr && r == nullptr) return; // double close? This should skip the I_Error at the bottom.
if (w != nullptr) if (w != nullptr)
{ {
delete w; delete w;
@ -590,7 +592,7 @@ bool FSerializer::BeginObject(const char *name)
} }
else else
{ {
Printf(TEXTCOLOR_RED "Object expected for '%s'", name); Printf(TEXTCOLOR_RED "Object expected for '%s'\n", name);
mErrors++; mErrors++;
return false; return false;
} }
@ -656,7 +658,7 @@ bool FSerializer::BeginArray(const char *name)
} }
else else
{ {
Printf(TEXTCOLOR_RED "Array expected for '%s'", name); Printf(TEXTCOLOR_RED "Array expected for '%s'\n", name);
mErrors++; mErrors++;
return false; return false;
} }
@ -748,7 +750,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe
else else
{ {
assert(false && "Integer expected"); 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++; mErrors++;
} }
} }
@ -756,7 +758,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe
else else
{ {
assert(false && "array expected"); assert(false && "array expected");
Printf(TEXTCOLOR_RED "array expected for '%s'", key); Printf(TEXTCOLOR_RED "array expected for '%s'\n", key);
mErrors++; mErrors++;
} }
} }
@ -800,7 +802,7 @@ FSerializer &FSerializer::ScriptNum(const char *key, int &num)
else else
{ {
assert(false && "Integer expected"); assert(false && "Integer expected");
Printf(TEXTCOLOR_RED "Integer expected for '%s'", key); Printf(TEXTCOLOR_RED "Integer expected for '%s'\n", key);
mErrors++; mErrors++;
} }
} }
@ -1005,7 +1007,7 @@ void FSerializer::ReadObjects(bool hubtravel)
PClass *cls = PClass::FindClass(clsname); PClass *cls = PClass::FindClass(clsname);
if (cls == nullptr) 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; 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] = 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. 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) catch (CRecoverableError &err)
{ {
// In case something in here throws an error, let's continue and deal with it later. // 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++; mErrors++;
} }
} }
@ -1055,7 +1057,7 @@ void FSerializer::ReadObjects(bool hubtravel)
assert(!founderrors); assert(!founderrors);
if (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++; mErrors++;
} }
} }
@ -1064,7 +1066,7 @@ void FSerializer::ReadObjects(bool hubtravel)
// nuke all objects we created here. // nuke all objects we created here.
for (auto obj : r->mDObjects) for (auto obj : r->mDObjects)
{ {
obj->Destroy(); if (!(obj->ObjectFlags & OF_EuthanizeMe)) obj->Destroy();
} }
r->mDObjects.Clear(); r->mDObjects.Clear();
@ -1182,7 +1184,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, bool &value, bool *def
} }
else else
{ {
Printf(TEXTCOLOR_RED "boolean type expected for '%s'", key); Printf(TEXTCOLOR_RED "boolean type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1218,7 +1220,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, int64_t &value, int64_
} }
else else
{ {
Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1254,7 +1256,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, uint64_t &value, uint6
} }
else else
{ {
Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1291,7 +1293,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, int32_t &value, int32_
} }
else else
{ {
Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1327,7 +1329,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, uint32_t &value, uint3
} }
else else
{ {
Printf(TEXTCOLOR_RED "integer type expected for '%s'", key); Printf(TEXTCOLOR_RED "integer type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1405,7 +1407,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, double &value, double
} }
else else
{ {
Printf(TEXTCOLOR_RED "float type expected for '%s'", key); Printf(TEXTCOLOR_RED "float type expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
} }
} }
@ -1548,7 +1550,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
} }
else 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(); value.SetNull();
arc.mErrors++; arc.mErrors++;
} }
@ -1564,7 +1566,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
else else
{ {
assert(false && "not a texture"); 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(); value.SetNull();
arc.mErrors++; arc.mErrors++;
} }
@ -1649,7 +1651,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje
else else
{ {
assert(false && "invalid object reference"); 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; value = nullptr;
arc.mErrors++; arc.mErrors++;
if (retcode) *retcode = false; if (retcode) *retcode = false;
@ -1698,7 +1700,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d
} }
else else
{ {
Printf(TEXTCOLOR_RED "String expected for '%s'", key); Printf(TEXTCOLOR_RED "String expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
value = NAME_None; value = NAME_None;
} }
@ -1746,7 +1748,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDynamicCol
} }
} }
assert(false && "not a colormap"); 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; cm = &NormalLight;
} }
} }
@ -1787,7 +1789,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI
} }
else else
{ {
Printf(TEXTCOLOR_RED "string type expected for '%s'", key); Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key);
sid = 0; sid = 0;
arc.mErrors++; arc.mErrors++;
} }
@ -1836,7 +1838,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor
} }
else else
{ {
Printf(TEXTCOLOR_RED "string type expected for '%s'", key); Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key);
clst = nullptr; clst = nullptr;
arc.mErrors++; arc.mErrors++;
} }
@ -1884,7 +1886,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl
} }
else else
{ {
Printf(TEXTCOLOR_RED "string type expected for '%s'", key); Printf(TEXTCOLOR_RED "string type expected for '%s'\n", key);
clst = nullptr; clst = nullptr;
arc.mErrors++; 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. // this can actually happen by changing the DECORATE so treat it as a warning, not an error.
state = nullptr; 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 else
{ {
assert(false && "not a state"); 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++; arc.mErrors++;
} }
} }
else if (!retcode) else if (!retcode)
{ {
assert(false && "not an array"); 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++; arc.mErrors++;
} }
} }
@ -2028,7 +2030,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FStrifeDial
} }
else else
{ {
Printf(TEXTCOLOR_RED "integer expected for '%s'", key); Printf(TEXTCOLOR_RED "integer expected for '%s'\n", key);
arc.mErrors++; arc.mErrors++;
node = nullptr; node = nullptr;
} }
@ -2077,7 +2079,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FString *&p
} }
else else
{ {
Printf(TEXTCOLOR_RED "string expected for '%s'", key); Printf(TEXTCOLOR_RED "string expected for '%s'\n", key);
pstr = nullptr; pstr = nullptr;
arc.mErrors++; arc.mErrors++;
} }
@ -2119,7 +2121,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &pstr, FString
} }
else else
{ {
Printf(TEXTCOLOR_RED "string expected for '%s'", key); Printf(TEXTCOLOR_RED "string expected for '%s'\n", key);
pstr = ""; pstr = "";
arc.mErrors++; arc.mErrors++;
} }
@ -2168,7 +2170,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr
} }
else else
{ {
Printf(TEXTCOLOR_RED "string expected for '%s'", key); Printf(TEXTCOLOR_RED "string expected for '%s'\n", key);
pstr = nullptr; pstr = nullptr;
arc.mErrors++; arc.mErrors++;
} }

View file

@ -64,6 +64,7 @@ public:
~FSerializer() ~FSerializer()
{ {
mErrors = 0; // The destructor may not throw an exception so silence the error checker.
Close(); Close();
} }
bool OpenWriter(bool pretty = true); bool OpenWriter(bool pretty = true);

View file

@ -57,7 +57,7 @@ const char *GetVersionString();
// Version identifier for network games. // Version identifier for network games.
// Bump it every time you do a release unless you're certain you // Bump it every time you do a release unless you're certain you
// didn't change anything that will affect sync. // didn't change anything that will affect sync.
#define NETGAMEVERSION 235 #define NETGAMEVERSION 233
// Version stored in the ini's [LastRun] section. // Version stored in the ini's [LastRun] section.
// Bump it if you made some configuration change that you want to // Bump it if you made some configuration change that you want to

View file

@ -651,6 +651,7 @@ OptionValue PuffTypes
{ {
0.0, "$OPTVAL_SPRITES" 0.0, "$OPTVAL_SPRITES"
1.0, "$OPTVAL_PARTICLES" 1.0, "$OPTVAL_PARTICLES"
2.0, "$OPTVAL_SPRITESPARTICLES"
} }
OptionValue Wipes OptionValue Wipes