diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 75cf27cad..8c0a30ea0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif() option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON ) +option( DYN_OPENAL "Dynamically load OpenAL" ON ) if( APPLE ) option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON ) @@ -226,13 +227,23 @@ endif() if( NOT NO_OPENAL ) - find_package( OpenAL ) + find_package( OpenAL ) mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR) - if( OPENAL_INCLUDE_DIR ) - include_directories( ${OPENAL_INCLUDE_DIR} ) - else() + if( OPENAL_INCLUDE_DIR ) + include_directories( ${OPENAL_INCLUDE_DIR} ) + if( DYN_OPENAL ) + add_definitions( -DDYN_OPENAL ) + else() + mark_as_advanced(CLEAR OPENAL_LIBRARY) + if( OPENAL_LIBRARY ) + set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} ) + else() + set( NO_OPENAL ON ) + endif() + endif() + else() set( NO_OPENAL ON ) - endif() + endif() endif() if( NOT NO_FMOD ) diff --git a/src/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/dthinker.cpp b/src/dthinker.cpp index 230d0dd41..176df6c18 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -152,11 +152,6 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad) } else { - if (hubLoad) - DestroyMostThinkers(); - else - DestroyAllThinkers(); - // Prevent the constructor from inserting thinkers into a list. bSerialOverride = true; diff --git a/src/g_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_level.cpp b/src/g_level.cpp index d27747ccb..3cd36c900 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1479,6 +1479,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) int i = level.totaltime; Renderer->StartSerialize(arc); + if (arc.IsLoading()) P_DestroyThinkers(hubLoad); arc << level.flags << level.flags2 diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 6e85bd886..1da7cd712 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -61,10 +61,13 @@ void ASkyViewpoint::Destroy () // remove all sector references to ourselves. for (auto &s : sectorPortals) { - if (s.mSkybox == this) s.mSkybox = 0; - // This is necessary to entirely disable EE-style skyboxes - // if their viewpoint gets deleted. - s.mFlags |= PORTSF_SKYFLATONLY; + if (s.mSkybox == this) + { + s.mSkybox = 0; + // This is necessary to entirely disable EE-style skyboxes + // if their viewpoint gets deleted. + s.mFlags |= PORTSF_SKYFLATONLY; + } } Super::Destroy(); 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 3248e738c..7c031d243 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1328,6 +1328,18 @@ static int CheckInventory (AActor *activator, const char *type, bool max) } PClassActor *info = PClass::FindActor (type); + + if (info == NULL) + { + Printf ("ACS: I don't know what '%s' is.\n", type); + return 0; + } + else if (!info->IsDescendantOf(RUNTIME_CLASS(AInventory))) + { + Printf ("ACS: '%s' is not an inventory item.\n", type); + return 0; + } + AInventory *item = activator->FindInventory (info); if (max) @@ -3956,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); @@ -4464,7 +4477,8 @@ enum EACSFunctions ACSF_SetSectorTerrain, ACSF_SpawnParticle, ACSF_SetMusicVolume, - // 2 more left... + ACSF_CheckProximity, + // 1 more left... /* Zandronum's - these must be skipped when we reach 99! -100:ResetMap(0), @@ -6063,7 +6077,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) case ACSF_SetMusicVolume: I_SetMusicVolume(ACSToFloat(args[0])); break; - + + case ACSF_CheckProximity: + { + // [zombie] ACS version of A_CheckProximity + actor = SingleActorFromTID(args[0], activator); + PClass *classname = PClass::FindClass(FBehavior::StaticLookupString(args[1])); + double distance = ACSToDouble(args[2]); + int count = argCount >= 4 ? args[3] : 1; + int flags = argCount >= 5 ? args[4] : 0; + int ptr = argCount >= 6 ? args[5] : AAPTR_DEFAULT; + return P_Thing_CheckProximity(actor, classname, distance, count, flags, ptr); + } + default: break; } diff --git a/src/p_local.h b/src/p_local.h index 8e64c3414..f7862d45f 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -26,6 +26,7 @@ #include #include "doomtype.h" #include "vectors.h" +#include "dobject.h" const double NO_VALUE = FLT_MAX; @@ -160,6 +161,24 @@ bool P_Thing_CanRaise(AActor *thing); PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch); +bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr); + +enum CPXF +{ + CPXF_ANCESTOR = 1 << 0, + CPXF_LESSOREQUAL = 1 << 1, + CPXF_NOZ = 1 << 2, + CPXF_COUNTDEAD = 1 << 3, + CPXF_DEADONLY = 1 << 4, + CPXF_EXACT = 1 << 5, + CPXF_SETTARGET = 1 << 6, + CPXF_SETMASTER = 1 << 7, + CPXF_SETTRACER = 1 << 8, + CPXF_FARTHEST = 1 << 9, + CPXF_CLOSEST = 1 << 10, + CPXF_SETONPTR = 1 << 11, + CPXF_CHECKSIGHT = 1 << 12, +}; enum WARPF { diff --git a/src/p_map.cpp b/src/p_map.cpp index ce3fd9af2..69d18ce18 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4105,6 +4105,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, AActor *puff = NULL; int pflag = 0; int puffFlags = (flags & LAF_ISMELEEATTACK) ? PF_MELEERANGE : 0; + bool spawnSky = false; if (flags & LAF_NORANDOMPUFFZ) puffFlags |= PF_NORANDOMZ; @@ -4144,7 +4145,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) || (puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST)); - + + spawnSky = (puffDefaults && (puffDefaults->flags3 & MF3_SKYEXPLODE)); TData.MThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES)); TData.PuffSpecies = NAME_None; @@ -4210,7 +4212,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (trace.HitType != TRACE_HitActor) { // position a bit closer for puffs - if (trace.HitType != TRACE_HitWall || trace.Line->special != Line_Horizon) + if (trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky)) { DVector2 pos = P_GetOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4); puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget, 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_saveg.cpp b/src/p_saveg.cpp index b6e3b28ca..e64a97fca 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -519,6 +519,14 @@ void P_SerializeThinkers (FArchive &arc, bool hubLoad) DThinker::SerializeAll (arc, hubLoad); } +void P_DestroyThinkers(bool hubLoad) +{ + if (hubLoad) + DThinker::DestroyMostThinkers(); + else + DThinker::DestroyAllThinkers(); +} + //========================================================================== // // ArchiveSounds diff --git a/src/p_saveg.h b/src/p_saveg.h index c6c056004..eb3e4de2b 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -43,6 +43,7 @@ struct PNGHandle; void P_SerializePlayers (FArchive &arc, bool fakeload); void P_SerializeWorldActors(FArchive &arc); void P_SerializeWorld (FArchive &arc); +void P_DestroyThinkers(bool hubLoad); void P_SerializeThinkers (FArchive &arc, bool); void P_SerializePolyobjs (FArchive &arc); void P_SerializeSubsectors(FArchive &arc); 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 ba1b29a1a..98826268c 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -50,6 +50,7 @@ #include "r_utility.h" #include "p_spec.h" #include "math/cmath.h" +#include "actorptrselect.h" // Set of spawnable things for the Thing_Spawn and Thing_Projectile specials. FClassMap SpawnableThings; @@ -97,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 @@ -666,6 +667,122 @@ void InitSpawnablesFromMapinfo() InitClassMap(StrifeTypes, ConversationIDsFromMapinfo); } +bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr) +{ + AActor *ref = COPY_AAPTR(self, ptr); + + // We need these to check out. + if (!ref || !classname || distance <= 0) + return false; + + int counter = 0; + bool result = false; + double closer = distance, farther = 0, current = distance; + const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); + const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); + + TThinkerIterator it; + AActor *mo, *dist = nullptr; + + // [MC] Process of elimination, I think, will get through this as quickly and + // efficiently as possible. + while ((mo = it.Next())) + { + if (mo == ref) //Don't count self. + continue; + + // no unmorphed versions of currently morphed players. + if (mo->flags & MF_UNMORPHED) + continue; + + // Check inheritance for the classname. Taken partly from CheckClass DECORATE function. + if (flags & CPXF_ANCESTOR) + { + if (!(mo->IsKindOf(classname))) + continue; + } + // Otherwise, just check for the regular class name. + else if (classname != mo->GetClass()) + continue; + + // [MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use + // Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. + // Ripped from sphere checking in A_RadiusGive (along with a number of things). + if ((ref->Distance2D(mo) < distance && + ((flags & CPXF_NOZ) || + ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || + (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) + { + if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) + continue; + + if (ptrWillChange) + { + current = ref->Distance2D(mo); + + if ((flags & CPXF_CLOSEST) && (current < closer)) + { + dist = mo; + closer = current; // This actor's closer. Set the new standard. + } + else if ((flags & CPXF_FARTHEST) && (current > farther)) + { + dist = mo; + farther = current; + } + else if (!dist) + dist = mo; // Just get the first one and call it quits if there's nothing selected. + } + if (mo->flags6 & MF6_KILLED) + { + if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) + continue; + counter++; + } + else + { + if (flags & CPXF_DEADONLY) + continue; + counter++; + } + + // Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal. + if (counter > count) + { + result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true; + + // However, if we have one SET* flag and either the closest or farthest flags, keep the function going. + if (ptrWillChange && ptrDistPref) + continue; + else + break; + } + } + } + + if (ptrWillChange && dist != 0) + { + if (flags & CPXF_SETONPTR) + { + if (flags & CPXF_SETTARGET) ref->target = dist; + if (flags & CPXF_SETMASTER) ref->master = dist; + if (flags & CPXF_SETTRACER) ref->tracer = dist; + } + else + { + if (flags & CPXF_SETTARGET) self->target = dist; + if (flags & CPXF_SETMASTER) self->master = dist; + if (flags & CPXF_SETTRACER) self->tracer = dist; + } + } + + if (counter == count) + result = true; + else if (counter < count) + result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); + + return result; +} int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch) { diff --git a/src/posix/cocoa/st_console.mm b/src/posix/cocoa/st_console.mm index 5d82551bc..e38a5cc85 100644 --- a/src/posix/cocoa/st_console.mm +++ b/src/posix/cocoa/st_console.mm @@ -373,7 +373,8 @@ void FConsoleWindow::SetTitleText() } NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect]; - [titleText setStringValue:[NSString stringWithUTF8String:DoomStartupInfo.Name]]; + [titleText setStringValue:[NSString stringWithCString:DoomStartupInfo.Name + encoding:NSISOLatin1StringEncoding]]; [titleText setAlignment:NSCenterTextAlignment]; [titleText setTextColor:RGB(DoomStartupInfo.FgColor)]; [titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)]; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 7915fdccc..321cbce1b 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -684,9 +684,9 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, { sector_t *sec = P_PointInSector(pt[0], pt[2]); DVector2 disp = Displacements.getOffset(pgroup, sec->PortalGroup); - pos->X = pt[0] + (float)disp.X; + pos->X = pt[0] - (float)disp.X; pos->Y = !(chanflags & CHAN_LISTENERZ) ? pt[1] : (float)listenpos.Z; - pos->Z = pt[2] + (float)disp.Y; + pos->Z = pt[2] - (float)disp.Y; } else { @@ -701,7 +701,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (actor != NULL) { DVector2 disp = Displacements.getOffset(pgroup, actor->Sector->PortalGroup); - DVector3 posi = actor->Pos() + disp; + DVector3 posi = actor->Pos() - disp; *pos = { (float)posi.X, (float)posi.Z, (float)posi.Y }; } break; @@ -714,15 +714,15 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (chanflags & CHAN_AREA) { // listener must be reversely offset to calculate the proper sound origin. - CalcSectorSoundOrg(listenpos-disp, sector, channum, *pos); + CalcSectorSoundOrg(listenpos + disp, sector, channum, *pos); pos->X += (float)disp.X; pos->Z += (float)disp.Y; } else { - pos->X = (float)(sector->centerspot.X + disp.X); - pos->Z = (float)(sector->centerspot.Y + disp.Y); + pos->X = (float)(sector->centerspot.X - disp.X); + pos->Z = (float)(sector->centerspot.Y - disp.Y); chanflags |= CHAN_LISTENERZ; } } @@ -733,7 +733,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, if (poly != NULL) { DVector2 disp = Displacements.getOffset(pgroup, poly->CenterSubsector->sector->PortalGroup); - CalcPolyobjSoundOrg(listenpos-disp, poly, *pos); + CalcPolyobjSoundOrg(listenpos + disp, poly, *pos); pos->X += (float)disp.X; pos->Z += (float)disp.Y; } diff --git a/src/sc_man.cpp b/src/sc_man.cpp index dadbae0ed..da106927e 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -1038,11 +1038,17 @@ FScriptPosition &FScriptPosition::operator=(const FScriptPosition &other) // //========================================================================== +CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) + void FScriptPosition::Message (int severity, const char *message, ...) const { FString composed; if ((severity == MSG_DEBUG || severity == MSG_DEBUGLOG) && !developer) return; + if (severity == MSG_OPTERROR) + { + severity = strictdecorate ? MSG_ERROR : MSG_WARNING; + } if (message == NULL) { diff --git a/src/sc_man.h b/src/sc_man.h index b1231e547..359dd8140 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -124,6 +124,7 @@ enum MSG_WARNING, MSG_FATAL, MSG_ERROR, + MSG_OPTERROR, MSG_DEBUG, MSG_LOG, MSG_DEBUGLOG, diff --git a/src/sound/oalload.h b/src/sound/oalload.h index 3cee30d58..ca02d25d9 100644 --- a/src/sound/oalload.h +++ b/src/sound/oalload.h @@ -1,7 +1,7 @@ #ifndef OALDEF_H #define OALDEF_H -#ifndef NO_OPENAL +#if !defined NO_OPENAL && defined DYN_OPENAL #ifndef _WIN32 typedef void* FARPROC; diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 8ac41a04b..6dd204c86 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -83,6 +83,8 @@ bool IsOpenALPresent() { #ifdef NO_OPENAL return false; +#elif !defined DYN_OPENAL + return true; #else static bool cached_result = false; static bool done = false; @@ -425,10 +427,10 @@ public: virtual bool IsEnded() { return !Playing.load(); - } + } virtual FString GetStats() - { + { FString stats; size_t pos, len; ALfloat volume; @@ -1538,24 +1540,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } else { FVector3 dir = pos; if(AL.EXT_SOURCE_RADIUS) alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f); - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) - { + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { dir -= listener->position; - float mindist = rolloff->MinDistance/distscale; - FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); - float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; + float mindist = rolloff->MinDistance/distscale; + FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); + float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; - dir += listener->position; + dir += listener->position; } if(dist_sqr < (0.0004f*0.0004f)) { @@ -1566,8 +1568,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); - } + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + } } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); @@ -1799,7 +1801,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh { float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale); dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); - } + } } else if(!AL.EXT_SOURCE_RADIUS && areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) @@ -1822,7 +1824,7 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh else { alSourcei(source, AL_SOURCE_RELATIVE, AL_FALSE); - alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); + alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); getALError(); diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 09fe64d92..d69e2e367 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -12,7 +12,9 @@ #ifndef NO_OPENAL +#ifdef DYN_OPENAL #define AL_NO_PROTOTYPES +#endif // DYN_OPENAL #include "al.h" #include "alc.h" diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index a24e8831c..4bb247f94 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -431,11 +431,11 @@ void LoadActors () FScanner sc(lump); ParseDecorate (sc); } + FinishThingdef(); if (FScriptPosition::ErrorCounter > 0) { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } - FinishThingdef(); timer.Unclock(); if (!batchrun) Printf("DECORATE parsing took %.2f ms\n", timer.TimeMS()); // Base time: ~52 ms diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 86de07b5d..f171edaeb 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -483,6 +483,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt) return 0; } +//========================================================================== +// +// GetCrouchFactor +// +// NON-ACTION function to retrieve a player's crouching factor. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT_OPT(ptr) { ptr = AAPTR_PLAYER1; } + AActor *mobj = COPY_AAPTR(self, ptr); + + if (!mobj || !mobj->player) + { + ret->SetFloat(1); + } + else + { + ret->SetFloat(mobj->player->crouchfactor); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ @@ -5848,7 +5878,7 @@ enum DMSS DMSS_EITHER = 256, //Allow either type or species to be affected. }; -static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags, PClassActor *filter, FName species) +static void DoDamage(AActor *dmgtarget, AActor *inflictor, AActor *source, int amount, FName DamageType, int flags, PClassActor *filter, FName species) { bool filterpass = DoCheckClass(dmgtarget, filter, !!(flags & DMSS_EXFILTER)), speciespass = DoCheckSpecies(dmgtarget, species, !!(flags & DMSS_EXSPECIES)); @@ -5870,7 +5900,7 @@ static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageTy if (amount > 0) { //Should wind up passing them through just fine. - P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); + P_DamageMobj(dmgtarget, inflictor, source, amount, DamageType, dmgFlags); } else if (amount < 0) { @@ -5893,8 +5923,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } - DoDamage(self, self, amount, damagetype, flags, filter, species); + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); + + DoDamage(self, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5911,9 +5946,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->target != NULL) - DoDamage(self->target, self, amount, damagetype, flags, filter, species); + DoDamage(self->target, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5930,9 +5970,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->tracer != NULL) - DoDamage(self->tracer, self, amount, damagetype, flags, filter, species); + DoDamage(self->tracer, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5949,9 +5994,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) - DoDamage(self->master, self, amount, damagetype, flags, filter, species); + DoDamage(self->master, inflictor, source, amount, damagetype, flags, filter, species); return 0; } @@ -5968,6 +6018,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -5975,7 +6030,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren) while ( (mo = it.Next()) ) { if (mo->master == self) - DoDamage(mo, self, amount, damagetype, flags, filter, species); + DoDamage(mo, inflictor, source, amount, damagetype, flags, filter, species); } return 0; } @@ -5993,6 +6048,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6002,7 +6062,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings) while ((mo = it.Next())) { if (mo->master == self->master && mo != self) - DoDamage(mo, self, amount, damagetype, flags, filter, species); + DoDamage(mo, inflictor, source, amount, damagetype, flags, filter, species); } } return 0; @@ -6025,7 +6085,7 @@ enum KILS KILS_EITHER = 1 << 6, }; -static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags, PClassActor *filter, FName species) +static void DoKill(AActor *killtarget, AActor *inflictor, AActor *source, FName damagetype, int flags, PClassActor *filter, FName species) { bool filterpass = DoCheckClass(killtarget, filter, !!(flags & KILS_EXFILTER)), speciespass = DoCheckSpecies(killtarget, species, !!(flags & KILS_EXSPECIES)); @@ -6052,7 +6112,7 @@ static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags } if (!(flags & KILS_NOMONSTERS)) { - P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags); + P_DamageMobj(killtarget, inflictor, source, killtarget->health, damagetype, dmgFlags); } } } @@ -6070,9 +6130,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->target != NULL) - DoKill(self->target, self, damagetype, flags, filter, species); + DoKill(self->target, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6088,9 +6153,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->tracer != NULL) - DoKill(self->tracer, self, damagetype, flags, filter, species); + DoKill(self->tracer, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6106,9 +6176,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); if (self->master != NULL) - DoKill(self->master, self, damagetype, flags, filter, species); + DoKill(self->master, inflictor, source, damagetype, flags, filter, species); return 0; } @@ -6124,6 +6199,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6132,7 +6212,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { if (mo->master == self) { - DoKill(mo, self, damagetype, flags, filter, species); + DoKill(mo, inflictor, source, damagetype, flags, filter, species); } } return 0; @@ -6150,6 +6230,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) PARAM_INT_OPT (flags) { flags = 0; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_NAME_OPT (species) { species = NAME_None; } + PARAM_INT_OPT (src) { src = AAPTR_DEFAULT; } + PARAM_INT_OPT (inflict) { inflict = AAPTR_DEFAULT; } + + AActor *source = COPY_AAPTR(self, src); + AActor *inflictor = COPY_AAPTR(self, inflict); TThinkerIterator it; AActor *mo; @@ -6160,7 +6245,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { if (mo->master == self->master && mo != self) { - DoKill(mo, self, damagetype, flags, filter, species); + DoKill(mo, inflictor, source, damagetype, flags, filter, species); } } } @@ -6605,22 +6690,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetChaseThreshold) // Checks to see if a certain actor class is close to the // actor/pointer within distance, in numbers. //========================================================================== -enum CPXFflags -{ - CPXF_ANCESTOR = 1 << 0, - CPXF_LESSOREQUAL = 1 << 1, - CPXF_NOZ = 1 << 2, - CPXF_COUNTDEAD = 1 << 3, - CPXF_DEADONLY = 1 << 4, - CPXF_EXACT = 1 << 5, - CPXF_SETTARGET = 1 << 6, - CPXF_SETMASTER = 1 << 7, - CPXF_SETTRACER = 1 << 8, - CPXF_FARTHEST = 1 << 9, - CPXF_CLOSEST = 1 << 10, - CPXF_SETONPTR = 1 << 11, - CPXF_CHECKSIGHT = 1 << 12, -}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { PARAM_SELF_PROLOGUE(AActor); @@ -6638,120 +6707,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) ACTION_RETURN_STATE(NULL); } } - AActor *ref = COPY_AAPTR(self, ptr); - // We need these to check out. - if (!ref || !classname || distance <= 0) - { - ACTION_RETURN_STATE(NULL); - } - int counter = 0; - bool result = false; - double closer = distance, farther = 0, current = distance; - const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); - const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); - - TThinkerIterator it; - AActor *mo, *dist = NULL; - - //[MC] Process of elimination, I think, will get through this as quickly and - //efficiently as possible. - while ((mo = it.Next())) - { - if (mo == ref) //Don't count self. - continue; - - // no unmorphed versions of currently morphed players. - if (mo->flags & MF_UNMORPHED) - continue; - - //Check inheritance for the classname. Taken partly from CheckClass DECORATE function. - if (flags & CPXF_ANCESTOR) - { - if (!(mo->IsKindOf(classname))) - continue; - } - //Otherwise, just check for the regular class name. - else if (classname != mo->GetClass()) - continue; - - //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use - //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. - //Ripped from sphere checking in A_RadiusGive (along with a number of things). - if ((ref->Distance2D(mo) < distance && - ((flags & CPXF_NOZ) || - ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || - (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) - { - if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) - continue; - - if (ptrWillChange) - { - current = ref->Distance2D(mo); - - if ((flags & CPXF_CLOSEST) && (current < closer)) - { - dist = mo; - closer = current; //This actor's closer. Set the new standard. - } - else if ((flags & CPXF_FARTHEST) && (current > farther)) - { - dist = mo; - farther = current; - } - else if (!dist) - dist = mo; //Just get the first one and call it quits if there's nothing selected. - } - if (mo->flags6 & MF6_KILLED) - { - if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) - continue; - counter++; - } - else - { - if (flags & CPXF_DEADONLY) - continue; - counter++; - } - - //Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal. - if (counter > count) - { - result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true; - - //However, if we have one SET* flag and either the closest or farthest flags, keep the function going. - if (ptrWillChange && ptrDistPref) - continue; - else - break; - } - } - } - - if (ptrWillChange && dist != NULL) - { - if (flags & CPXF_SETONPTR) - { - if (flags & CPXF_SETTARGET) ref->target = dist; - if (flags & CPXF_SETMASTER) ref->master = dist; - if (flags & CPXF_SETTRACER) ref->tracer = dist; - } - else - { - if (flags & CPXF_SETTARGET) self->target = dist; - if (flags & CPXF_SETMASTER) self->master = dist; - if (flags & CPXF_SETTRACER) self->tracer = dist; - } - } - - if (counter == count) - result = true; - else if (counter < count) - result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); - - if (result && jump) + if (P_Thing_CheckProximity(self, classname, distance, count, flags, ptr) && jump) { ACTION_RETURN_STATE(jump); } 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 fbb16dc80..cc0569fff 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -46,6 +46,7 @@ ACTOR Actor native //: Thinker native float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); native int GetGibHealth(); + native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. @@ -289,17 +290,17 @@ ACTOR Actor native //: Thinker native void A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT); native void A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT); native void A_SetPainThreshold(int threshold, int ptr = AAPTR_DEFAULT); - native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); - action native A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None"); + native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillTarget(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillMaster(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillTracer(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillChildren(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); + action native A_KillSiblings(name damagetype = "none", int flags = 0, class filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); action native A_RemoveTarget(int flags = 0, class filter = "None", name species = "None"); action native A_RemoveMaster(int flags = 0, class filter = "None", name species = "None"); action native A_RemoveTracer(int flags = 0, class filter = "None", name species = "None"); 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" } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 001172185..f9050a27b 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -786,7 +786,7 @@ OB_MPPGAUNTLETS = "%o was bled dry by %k's gauntlets."; OB_MPPGOLDWAND = "%o was assaulted by %k's elven wand."; OB_MPPCROSSBOW = "%o was shafted by %k's ethereal crossbow."; OB_MPPBLASTER = "%o was ripped apart by %k's dragon claw."; -OB_MPPSKULLROD = "%k poured his hellstaff on %o."; +OB_MPPSKULLROD = "%k poured %p hellstaff on %o."; OB_MPPPHOENIXROD = "%o was burned down by %k's phoenix staff."; OB_MPPMACE = "%o was squished by %k's giant mace sphere.";