diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 36e3d576b..c8f1ee4c6 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1488,6 +1488,44 @@ FBaseCVar *FindCVarSub (const char *var_name, int namelen) return var; } +FBaseCVar *GetCVar(AActor *activator, const char *cvarname) +{ + FBaseCVar *cvar = FindCVar(cvarname, nullptr); + // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return nullptr. + if (cvar == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + else + { + // For userinfo cvars, redirect to GetUserCVar + if (cvar->GetFlags() & CVAR_USERINFO) + { + if (activator == nullptr || activator->player == nullptr) + { + return nullptr; + } + return GetUserCVar(int(activator->player - players), cvarname); + } + return cvar; + } +} + +FBaseCVar *GetUserCVar(int playernum, const char *cvarname) +{ + if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) + { + return nullptr; + } + FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); + FBaseCVar *cvar; + if (cvar_p == nullptr || (cvar = *cvar_p) == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + return cvar; +} + //=========================================================================== // // C_CreateCVar diff --git a/src/c_cvars.h b/src/c_cvars.h index 59a3208d1..be7676e89 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -186,6 +186,10 @@ void C_BackupCVars (void); FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); FBaseCVar *FindCVarSub (const char *var_name, int namelen); +// Used for ACS and DECORATE. +FBaseCVar *GetCVar(AActor *activator, const char *cvarname); +FBaseCVar *GetUserCVar(int playernum, const char *cvarname); + // Create a new cvar with the specified name and type FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, DWORD flags); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index a7a378375..e4acc75a6 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3123,22 +3123,29 @@ bool ADehackedPickup::TryPickup (AActor *&toucher) const char *ADehackedPickup::PickupMessage () { - return RealPickup->PickupMessage (); + if (RealPickup != nullptr) + return RealPickup->PickupMessage (); + else return ""; } bool ADehackedPickup::ShouldStay () { - return RealPickup->ShouldStay (); + if (RealPickup != nullptr) + return RealPickup->ShouldStay (); + else return true; } bool ADehackedPickup::ShouldRespawn () { - return RealPickup->ShouldRespawn (); + if (RealPickup != nullptr) + return RealPickup->ShouldRespawn (); + else return false; } void ADehackedPickup::PlayPickupSound (AActor *toucher) { - RealPickup->PlayPickupSound (toucher); + if (RealPickup != nullptr) + RealPickup->PlayPickupSound (toucher); } void ADehackedPickup::DoPickupSpecial (AActor *toucher) @@ -3146,19 +3153,19 @@ void ADehackedPickup::DoPickupSpecial (AActor *toucher) Super::DoPickupSpecial (toucher); // If the real pickup hasn't joined the toucher's inventory, make sure it // doesn't stick around. - if (RealPickup->Owner != toucher) + if (RealPickup != nullptr && RealPickup->Owner != toucher) { RealPickup->Destroy (); } - RealPickup = NULL; + RealPickup = nullptr; } void ADehackedPickup::Destroy () { - if (RealPickup != NULL) + if (RealPickup != nullptr) { RealPickup->Destroy (); - RealPickup = NULL; + RealPickup = nullptr; } Super::Destroy (); } diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index febcad0b5..6b963f6d4 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -60,6 +60,7 @@ // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- +EXTERN_CVAR(Bool, strictdecorate); // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -3067,7 +3068,8 @@ void PClass::InsertIntoHash () if (found != NULL) { // This type has already been inserted // ... but there is no need whatsoever to make it a fatal error! - Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); + if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); + else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars()); TypeTable.ReplaceType(this, found, bucket); } else diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index a978f3097..124cb1403 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -287,8 +287,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard) self->SetState (self->FindState(NAME_Death)); self->flags &= ~MF_MISSILE; mo->master = self->target; - // Heretic did not offset it by TELEFOGHEIGHT, so I won't either. - Spawn (self->Pos(), ALLOW_REPLACE); + P_SpawnTeleportFog(self, self->Pos(), false, true); } } return 0; diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index c8a330536..95c2ae6d0 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -17,6 +17,7 @@ #include "farchive.h" #include "d_player.h" #include "a_morph.h" +#include "p_spec.h" // Include all the other Heretic stuff here to reduce compile time #include "a_chicken.cpp" diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index dd5267c60..f2031a7a3 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon) rebel->SetState (rebel->SeeState); rebel->Angles.Yaw = self->Angles.Yaw; - Spawn (rebel->Vec3Angle(20., self->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); + P_SpawnTeleportFog(rebel, rebel->Vec3Angle(20., self->Angles.Yaw, 0), false, true); if (--self->health < 0) { self->SetState(self->FindState(NAME_Death)); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2de959be6..29c9fe8fe 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3968,6 +3968,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) case APROP_Friction: actor->Friction = ACSToDouble(value); + break; case APROP_MaxStepHeight: actor->MaxStepHeight = ACSToDouble(value); @@ -4656,7 +4657,11 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) { UCVarValue val; - if (is_string) + if (cvar == nullptr) + { + return 0; + } + else if (is_string) { val = cvar->GetGenericRep(CVAR_String); return GlobalACSStrings.AddString(val.String); @@ -4673,44 +4678,6 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) } } -static int GetUserCVar(int playernum, const char *cvarname, bool is_string) -{ - if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) - { - return 0; - } - FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); - FBaseCVar *cvar; - if (cvar_p == NULL || (cvar = *cvar_p) == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - return DoGetCVar(cvar, is_string); -} - -static int GetCVar(AActor *activator, const char *cvarname, bool is_string) -{ - FBaseCVar *cvar = FindCVar(cvarname, NULL); - // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return 0. - if (cvar == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - else - { - // For userinfo cvars, redirect to GetUserCVar - if (cvar->GetFlags() & CVAR_USERINFO) - { - if (activator == NULL || activator->player == NULL) - { - return 0; - } - return GetUserCVar(int(activator->player - players), cvarname, is_string); - } - return DoGetCVar(cvar, is_string); - } -} - static int SetUserCVar(int playernum, const char *cvarname, int value, bool is_string) { if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) @@ -5395,7 +5362,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetCVarString: if (argCount == 1) { - return GetCVar(activator, FBehavior::StaticLookupString(args[0]), true); + return DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(args[0])), true); } break; @@ -5416,14 +5383,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetUserCVar: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), false); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), false); } break; case ACSF_GetUserCVarString: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), true); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), true); } break; @@ -6047,7 +6014,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) PalEntry color = args[0]; bool fullbright = argCount > 1 ? !!args[1] : false; int lifetime = argCount > 2 ? args[2] : 35; - int size = argCount > 3 ? args[3] : 1; + double size = argCount > 3 ? args[3] : 1.; int x = argCount > 4 ? args[4] : 0; int y = argCount > 5 ? args[5] : 0; int z = argCount > 6 ? args[6] : 0; @@ -6059,17 +6026,18 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) int accelz = argCount > 12 ? args[12] : 0; int startalpha = argCount > 13 ? args[13] : 0xFF; // Byte trans int fadestep = argCount > 14 ? args[14] : -1; + double endsize = argCount > 15 ? args[15] : -1.; startalpha = clamp(startalpha, 0, 255); // Clamp to byte lifetime = clamp(lifetime, 0, 255); // Clamp to byte fadestep = clamp(fadestep, -1, 255); // Clamp to byte inc. -1 (indicating automatic) - size = clamp(size, 0, 65535); // Clamp to word + size = fabs(size); if (lifetime != 0) P_SpawnParticle(DVector3(ACSToDouble(x), ACSToDouble(y), ACSToDouble(z)), DVector3(ACSToDouble(xvel), ACSToDouble(yvel), ACSToDouble(zvel)), DVector3(ACSToDouble(accelx), ACSToDouble(accely), ACSToDouble(accelz)), - color, fullbright, startalpha/255., lifetime, size, fadestep/255.); + color, startalpha/255., lifetime, size, endsize, fadestep/255., fullbright); } break; @@ -9130,7 +9098,7 @@ scriptwait: break; case PCD_GETCVAR: - STACK(1) = GetCVar(activator, FBehavior::StaticLookupString(STACK(1)), false); + STACK(1) = DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(STACK(1))), false); break; case PCD_SETHUDSIZE: diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 25838459d..7919b8d46 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -252,7 +252,6 @@ void P_InitEffects () blood2 = ParticleColor(RPART(kind)/3, GPART(kind)/3, BPART(kind)/3); } - void P_ThinkParticles () { int i; @@ -262,13 +261,19 @@ void P_ThinkParticles () prev = NULL; while (i != NO_PARTICLE) { - BYTE oldtrans; - particle = Particles + i; i = particle->tnext; + if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN))) + { + prev = particle; + continue; + } + + BYTE oldtrans; oldtrans = particle->trans; particle->trans -= particle->fade; - if (oldtrans < particle->trans || --particle->ttl == 0) + particle->size += particle->sizestep; + if (oldtrans < particle->trans || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it memset (particle, 0, sizeof(particle_t)); if (prev) @@ -309,8 +314,14 @@ void P_ThinkParticles () } } +enum PSFlag +{ + PS_FULLBRIGHT = 1, + PS_NOTIMEFREEZE = 1 << 5, +}; -void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, bool fullbright, double startalpha, int lifetime, WORD size, double fadestep) +void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, + double fadestep, double sizestep, int flags) { particle_t *particle = NewParticle(); @@ -324,8 +335,10 @@ void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &a if (fadestep < 0) particle->fade = FADEFROMTTL(lifetime); else particle->fade = int(fadestep * 255); particle->ttl = lifetime; - particle->bright = fullbright; - particle->size = (WORD)size; + particle->bright = !!(flags & PS_FULLBRIGHT); + particle->size = size; + particle->sizestep = sizestep; + particle->notimefreeze = !!(flags & PS_NOTIMEFREEZE); } } diff --git a/src/p_effect.h b/src/p_effect.h index 033bf042c..614702a49 100644 --- a/src/p_effect.h +++ b/src/p_effect.h @@ -59,13 +59,15 @@ struct particle_t DVector3 Acc; BYTE ttl; BYTE trans; - WORD size; + double size; + double sizestep; BYTE bright; BYTE fade; int color; WORD tnext; WORD snext; subsector_t * subsector; + bool notimefreeze; }; extern particle_t *Particles; @@ -83,7 +85,7 @@ particle_t *JitterParticle (int ttl); particle_t *JitterParticle (int ttl, double drift); void P_ThinkParticles (void); -void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, bool fullbright, double startalpha, int lifetime, WORD size, double fadestep); +void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags = 0); void P_InitEffects (void); void P_RunEffects (void); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 97167f245..21455207b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2789,10 +2789,10 @@ void P_NightmareRespawn (AActor *mobj) mo->Prev.Z = z; // Do not interpolate Z position if we changed it since spawning. // spawn a teleport fog at old spot because of removal of the body? - P_SpawnTeleportFog(mobj, mobj->PosPlusZ(TELEFOGHEIGHT), true, true); + P_SpawnTeleportFog(mobj, mobj->Pos(), true, true); // spawn a teleport fog at the new spot - P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint, z + TELEFOGHEIGHT), false, true); + P_SpawnTeleportFog(mobj, DVector3(mobj->SpawnPoint, z), false, true); // remove the old monster mobj->Destroy (); @@ -4685,7 +4685,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) if (multiplayer) { - Spawn ("TeleportFog", mobj->Vec3Angle(20., mobj->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); + P_SpawnTeleportFog(mobj, mobj->Vec3Angle(20., mobj->Angles.Yaw, 0.), false, true); } // "Fix" for one of the starts on exec.wad MAP01: If you start inside the ceiling, diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index a3dbd0899..f65e2f402 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -88,7 +88,8 @@ void P_SpawnTeleportFog(AActor *mobj, const DVector3 &pos, bool beforeTele, bool } else { - mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), pos, ALLOW_REPLACE); + double fogDelta = mobj->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; + mo = Spawn((beforeTele ? mobj->TeleFogSourceType : mobj->TeleFogDestType), DVector3(pos, pos.Z + fogDelta), ALLOW_REPLACE); } if (mo != NULL && setTarget) @@ -191,10 +192,9 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) { if (!predicting) { - double fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; DVector2 vector = angle.ToVector(20); DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y); - P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z() + fogDelta), false, true); + P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true); } if (thing->player) diff --git a/src/p_things.cpp b/src/p_things.cpp index cad3022b0..98826268c 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -98,7 +98,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, i mobj->Angles.Yaw = (angle != 1000000. ? angle : spot->Angles.Yaw); if (fog) { - P_SpawnTeleportFog(mobj, spot->PosPlusZ(TELEFOGHEIGHT), false, true); + P_SpawnTeleportFog(mobj, spot->Pos(), false, true); } if (mobj->flags & MF_SPECIAL) mobj->flags |= MF_DROPPED; // Don't respawn @@ -673,7 +673,7 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in // We need these to check out. if (!ref || !classname || distance <= 0) - return nullptr; + return false; int counter = 0; bool result = false; diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 032aa8bf5..f0f1e2ea8 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -117,10 +117,7 @@ void P_Ticker (void) // Since things will be moving, it's okay to interpolate them in the renderer. r_NoInterpolate = false; - if (!bglobal.freeze && !(level.flags2 & LEVEL2_FROZEN)) - { - P_ThinkParticles (); // [RH] make the particles think - } + P_ThinkParticles(); // [RH] make the particles think for (i = 0; i 0) { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } - FinishThingdef(); timer.Unclock(); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index f171edaeb..9c8464417 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -513,6 +513,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) return 0; } +//========================================================================== +// +// GetCVar +// +// NON-ACTION function that works like ACS's GetCVar. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCVar) +{ + if (numret > 0) + { + assert(ret != nullptr); + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(cvarname); + + FBaseCVar *cvar = GetCVar(self, cvarname); + if (cvar == nullptr) + { + ret->SetFloat(0); + } + else + { + ret->SetFloat(cvar->GetGenericRep(CVAR_Float).Float); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ @@ -3147,6 +3177,7 @@ enum SPFflag SPF_RELVEL = 1 << 2, SPF_RELACCEL = 1 << 3, SPF_RELANG = 1 << 4, + SPF_NOTIMEFREEZE = 1 << 5, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) @@ -3155,7 +3186,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) PARAM_COLOR (color); PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (lifetime) { lifetime = 35; } - PARAM_INT_OPT (size) { size = 1; } + PARAM_FLOAT_OPT (size) { size = 1.; } PARAM_ANGLE_OPT (angle) { angle = 0.; } PARAM_FLOAT_OPT (xoff) { xoff = 0; } PARAM_FLOAT_OPT (yoff) { yoff = 0; } @@ -3168,11 +3199,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) PARAM_FLOAT_OPT (accelz) { accelz = 0; } PARAM_FLOAT_OPT (startalpha) { startalpha = 1.; } PARAM_FLOAT_OPT (fadestep) { fadestep = -1.; } + PARAM_FLOAT_OPT (sizestep) { sizestep = 0.; } startalpha = clamp(startalpha, 0., 1.); if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); - size = clamp(size, 0, 65535); // Clamp to word - + size = fabs(size); if (lifetime != 0) { if (flags & SPF_RELANG) angle += self->Angles.Yaw; @@ -3199,7 +3230,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnParticle) acc.X = accelx * c + accely * s; acc.Y = accelx * s - accely * c; } - P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, !!(flags & SPF_FULLBRIGHT), startalpha, lifetime, size, fadestep); + P_SpawnParticle(self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, sizestep, flags); } return 0; } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 9ec605626..ac6b7eda3 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -208,7 +208,7 @@ public: virtual bool isConstant() const; virtual void RequestAddress(); virtual VMFunction *GetDirectFunction(); - bool IsNumeric() const { return ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT; } + bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); } bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } virtual ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index c888f97d5..d500458a2 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -358,10 +358,22 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { - FxExpression *x = basex; - basex = NULL; - delete this; - return x; + if (basex->ValueType != TypeName) + { + FxExpression *x = basex; + basex = NULL; + delete this; + return x; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( + if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression * x = new FxConstant(0, ScriptPosition); + delete this; + return x; + } } else if (basex->ValueType->GetRegType() == REGT_FLOAT) { @@ -374,12 +386,9 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) } return this; } - else - { - ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); - delete this; - return NULL; - } + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return NULL; } //========================================================================== @@ -443,14 +452,26 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) } else if (basex->ValueType->GetRegType() == REGT_INT) { - if (basex->isConstant()) + if (basex->ValueType != TypeName) { - ExpVal constval = static_cast(basex)->GetValue(); - FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( + if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); + FxExpression *x = new FxConstant(0.0, ScriptPosition); delete this; return x; } - return this; } else { @@ -3903,7 +3924,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) { /* lax */ // Since this happens in released WADs it must pass without a terminal error... :( - ScriptPosition.Message(MSG_WARNING, + ScriptPosition.Message(MSG_OPTERROR, "Unknown class name '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); } @@ -4074,7 +4095,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) destination = scope->FindState(names.Size()-1, &names[1], false); if (destination == NULL) { - ScriptPosition.Message(MSG_WARNING, "Unknown state jump destination"); + ScriptPosition.Message(MSG_OPTERROR, "Unknown state jump destination"); /* lax */ return this; } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 3ec4c624d..db6ef14a0 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -457,7 +457,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor) } if (bag.StateSet) { - bag.ScriptPosition.Message(MSG_WARNING, + bag.ScriptPosition.Message(MSG_OPTERROR, "'skip_super' must appear before any state definitions."); return; } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index cc0569fff..2ce48b036 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -47,6 +47,7 @@ ACTOR Actor native //: Thinker native int GetSpawnHealth(); native int GetGibHealth(); native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); + native float GetCVar(string cvar); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. @@ -214,7 +215,7 @@ ACTOR Actor native //: Thinker native void A_SetScale(float scalex, float scaley = 0, int ptr = AAPTR_DEFAULT, bool usezero = false); native void A_SetMass(int mass); native void A_SpawnDebris(class spawntype, bool transfer_translation = false, float mult_h = 1, float mult_v = 1); - native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, int size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1); + native void A_SpawnParticle(color color1, int flags = 0, int lifetime = 35, float size = 1, float angle = 0, float xoff = 0, float yoff = 0, float zoff = 0, float velx = 0, float vely = 0, float velz = 0, float accelx = 0, float accely = 0, float accelz = 0, float startalphaf = 1, float fadestepf = -1, float sizestep = 0); native state A_CheckSight(state label); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 911e1036b..f5072d55e 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -539,6 +539,7 @@ enum SPF_RELVEL = 1 << 2, SPF_RELACCEL = 1 << 3, SPF_RELANG = 1 << 4, + SPF_NOTIMEFREEZE = 1 << 5, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index 8fafdcfa4..d0fb1a157 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -1,5 +1,16 @@ // Must be sorted in identification order (easiest to recognize first!) +IWad +{ + Name = "Delaweare" + Autoname = "delaweare" + Game = "Doom" + Config = "Delaweare" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "TITLEMAP", "ROVEA0", "GRLURD01", "SQOUI01" + BannerColors = "00 00 00", "ff ff ff" +} + IWad { Name = "The Adventures of Square" @@ -393,4 +404,5 @@ Names "hacx.wad" "hacx2.wad" "square1.pk3" + "delaweare.wad" }