mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9420826094
32 changed files with 431 additions and 236 deletions
|
@ -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 )
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<ATeleportFog> (self->Pos(), ALLOW_REPLACE);
|
||||
P_SpawnTeleportFog(self, self->Pos(), false, true);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon)
|
|||
|
||||
rebel->SetState (rebel->SeeState);
|
||||
rebel->Angles.Yaw = self->Angles.Yaw;
|
||||
Spawn<ATeleportFog> (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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <float.h>
|
||||
#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
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
119
src/p_things.cpp
119
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<AActor> 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)
|
||||
{
|
||||
|
|
|
@ -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)];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -124,6 +124,7 @@ enum
|
|||
MSG_WARNING,
|
||||
MSG_FATAL,
|
||||
MSG_ERROR,
|
||||
MSG_OPTERROR,
|
||||
MSG_DEBUG,
|
||||
MSG_LOG,
|
||||
MSG_DEBUGLOG,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
#ifndef NO_OPENAL
|
||||
|
||||
#ifdef DYN_OPENAL
|
||||
#define AL_NO_PROTOTYPES
|
||||
#endif // DYN_OPENAL
|
||||
|
||||
#include "al.h"
|
||||
#include "alc.h"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<AActor> 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<AActor> 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<AActor> 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<AActor> 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<AActor> 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<FxConstant*>(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<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition);
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(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<FxConstant*>(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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageTracer(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageChildren(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageSiblings(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_KillTarget(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_KillMaster(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_KillTracer(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_KillChildren(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_KillSiblings(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class<Actor> 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<Actor> 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<Actor> 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<Actor> 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<Actor> 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<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_KillTarget(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_KillMaster(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_KillTracer(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_KillChildren(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_KillSiblings(name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT);
|
||||
action native A_RemoveTarget(int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_RemoveMaster(int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
action native A_RemoveTracer(int flags = 0, class<Actor> filter = "None", name species = "None");
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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.";
|
||||
|
||||
|
|
Loading…
Reference in a new issue