# Conflicts:
#	src/g_level.cpp
This commit is contained in:
Christoph Oelckers 2016-06-01 11:45:57 +02:00
commit 18ebe92cfc
18 changed files with 343 additions and 198 deletions

View file

@ -29,6 +29,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
endif() endif()
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON ) option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON )
option( DYN_OPENAL "Dynamically load OpenAL" ON )
if( APPLE ) if( APPLE )
option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON ) option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON )
@ -239,6 +240,16 @@ if( NOT NO_OPENAL )
mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR) mark_as_advanced(CLEAR OPENAL_INCLUDE_DIR)
if( OPENAL_INCLUDE_DIR ) if( OPENAL_INCLUDE_DIR )
include_directories( ${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() else()
set( NO_OPENAL ON ) set( NO_OPENAL ON )
endif() endif()

View file

@ -152,11 +152,6 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
} }
else else
{ {
if (hubLoad)
DestroyMostThinkers();
else
DestroyAllThinkers();
// Prevent the constructor from inserting thinkers into a list. // Prevent the constructor from inserting thinkers into a list.
bSerialOverride = true; bSerialOverride = true;

View file

@ -1480,6 +1480,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
int i = level.totaltime; int i = level.totaltime;
Renderer->StartSerialize(arc); Renderer->StartSerialize(arc);
if (arc.IsLoading()) P_DestroyThinkers(hubLoad);
gl_SerializeGlobals(arc); gl_SerializeGlobals(arc);
arc << level.flags arc << level.flags

View file

@ -61,11 +61,14 @@ void ASkyViewpoint::Destroy ()
// remove all sector references to ourselves. // remove all sector references to ourselves.
for (auto &s : sectorPortals) for (auto &s : sectorPortals)
{ {
if (s.mSkybox == this) s.mSkybox = 0; if (s.mSkybox == this)
{
s.mSkybox = 0;
// This is necessary to entirely disable EE-style skyboxes // This is necessary to entirely disable EE-style skyboxes
// if their viewpoint gets deleted. // if their viewpoint gets deleted.
s.mFlags |= PORTSF_SKYFLATONLY; s.mFlags |= PORTSF_SKYFLATONLY;
} }
}
Super::Destroy(); Super::Destroy();
} }

View file

@ -1328,6 +1328,18 @@ static int CheckInventory (AActor *activator, const char *type, bool max)
} }
PClassActor *info = PClass::FindActor (type); 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); AInventory *item = activator->FindInventory (info);
if (max) if (max)
@ -4464,7 +4476,8 @@ enum EACSFunctions
ACSF_SetSectorTerrain, ACSF_SetSectorTerrain,
ACSF_SpawnParticle, ACSF_SpawnParticle,
ACSF_SetMusicVolume, ACSF_SetMusicVolume,
// 2 more left... ACSF_CheckProximity,
// 1 more left...
/* Zandronum's - these must be skipped when we reach 99! /* Zandronum's - these must be skipped when we reach 99!
-100:ResetMap(0), -100:ResetMap(0),
@ -6064,6 +6077,18 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
I_SetMusicVolume(ACSToFloat(args[0])); I_SetMusicVolume(ACSToFloat(args[0]));
break; 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: default:
break; break;
} }

View file

@ -26,6 +26,7 @@
#include <float.h> #include <float.h>
#include "doomtype.h" #include "doomtype.h"
#include "vectors.h" #include "vectors.h"
#include "dobject.h"
const double NO_VALUE = FLT_MAX; const double NO_VALUE = FLT_MAX;
@ -160,6 +161,24 @@ bool P_Thing_CanRaise(AActor *thing);
PClassActor *P_GetSpawnableType(int spawnnum); PClassActor *P_GetSpawnableType(int spawnnum);
void InitSpawnablesFromMapinfo(); 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); 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 enum WARPF
{ {

View file

@ -4105,6 +4105,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
AActor *puff = NULL; AActor *puff = NULL;
int pflag = 0; int pflag = 0;
int puffFlags = (flags & LAF_ISMELEEATTACK) ? PF_MELEERANGE : 0; int puffFlags = (flags & LAF_ISMELEEATTACK) ? PF_MELEERANGE : 0;
bool spawnSky = false;
if (flags & LAF_NORANDOMPUFFZ) if (flags & LAF_NORANDOMPUFFZ)
puffFlags |= PF_NORANDOMZ; puffFlags |= PF_NORANDOMZ;
@ -4145,6 +4146,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
(t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) || (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) ||
(puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST)); (puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST));
spawnSky = (puffDefaults && (puffDefaults->flags3 & MF3_SKYEXPLODE));
TData.MThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES)); TData.MThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES));
TData.PuffSpecies = NAME_None; TData.PuffSpecies = NAME_None;
@ -4210,7 +4212,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
if (trace.HitType != TRACE_HitActor) if (trace.HitType != TRACE_HitActor)
{ {
// position a bit closer for puffs // 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); 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, puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget,

View file

@ -524,6 +524,14 @@ void P_SerializeThinkers (FArchive &arc, bool hubLoad)
DThinker::SerializeAll (arc, hubLoad); DThinker::SerializeAll (arc, hubLoad);
} }
void P_DestroyThinkers(bool hubLoad)
{
if (hubLoad)
DThinker::DestroyMostThinkers();
else
DThinker::DestroyAllThinkers();
}
//========================================================================== //==========================================================================
// //
// ArchiveSounds // ArchiveSounds

View file

@ -43,6 +43,7 @@ struct PNGHandle;
void P_SerializePlayers (FArchive &arc, bool fakeload); void P_SerializePlayers (FArchive &arc, bool fakeload);
void P_SerializeWorldActors(FArchive &arc); void P_SerializeWorldActors(FArchive &arc);
void P_SerializeWorld (FArchive &arc); void P_SerializeWorld (FArchive &arc);
void P_DestroyThinkers(bool hubLoad);
void P_SerializeThinkers (FArchive &arc, bool); void P_SerializeThinkers (FArchive &arc, bool);
void P_SerializePolyobjs (FArchive &arc); void P_SerializePolyobjs (FArchive &arc);
void P_SerializeSubsectors(FArchive &arc); void P_SerializeSubsectors(FArchive &arc);

View file

@ -50,6 +50,7 @@
#include "r_utility.h" #include "r_utility.h"
#include "p_spec.h" #include "p_spec.h"
#include "math/cmath.h" #include "math/cmath.h"
#include "actorptrselect.h"
// Set of spawnable things for the Thing_Spawn and Thing_Projectile specials. // Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
FClassMap SpawnableThings; FClassMap SpawnableThings;
@ -666,6 +667,122 @@ void InitSpawnablesFromMapinfo()
InitClassMap(StrifeTypes, ConversationIDsFromMapinfo); 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 nullptr;
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) int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch)
{ {

View file

@ -373,7 +373,8 @@ void FConsoleWindow::SetTitleText()
} }
NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect]; NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect];
[titleText setStringValue:[NSString stringWithUTF8String:DoomStartupInfo.Name]]; [titleText setStringValue:[NSString stringWithCString:DoomStartupInfo.Name
encoding:NSISOLatin1StringEncoding]];
[titleText setAlignment:NSCenterTextAlignment]; [titleText setAlignment:NSCenterTextAlignment];
[titleText setTextColor:RGB(DoomStartupInfo.FgColor)]; [titleText setTextColor:RGB(DoomStartupInfo.FgColor)];
[titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)]; [titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)];

View file

@ -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]); sector_t *sec = P_PointInSector(pt[0], pt[2]);
DVector2 disp = Displacements.getOffset(pgroup, sec->PortalGroup); 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->Y = !(chanflags & CHAN_LISTENERZ) ? pt[1] : (float)listenpos.Z;
pos->Z = pt[2] + (float)disp.Y; pos->Z = pt[2] - (float)disp.Y;
} }
else else
{ {
@ -701,7 +701,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
if (actor != NULL) if (actor != NULL)
{ {
DVector2 disp = Displacements.getOffset(pgroup, actor->Sector->PortalGroup); 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 }; *pos = { (float)posi.X, (float)posi.Z, (float)posi.Y };
} }
break; break;
@ -714,15 +714,15 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
if (chanflags & CHAN_AREA) if (chanflags & CHAN_AREA)
{ {
// listener must be reversely offset to calculate the proper sound origin. // 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->X += (float)disp.X;
pos->Z += (float)disp.Y; pos->Z += (float)disp.Y;
} }
else else
{ {
pos->X = (float)(sector->centerspot.X + disp.X); pos->X = (float)(sector->centerspot.X - disp.X);
pos->Z = (float)(sector->centerspot.Y + disp.Y); pos->Z = (float)(sector->centerspot.Y - disp.Y);
chanflags |= CHAN_LISTENERZ; chanflags |= CHAN_LISTENERZ;
} }
} }
@ -733,7 +733,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
if (poly != NULL) if (poly != NULL)
{ {
DVector2 disp = Displacements.getOffset(pgroup, poly->CenterSubsector->sector->PortalGroup); 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->X += (float)disp.X;
pos->Z += (float)disp.Y; pos->Z += (float)disp.Y;
} }

View file

@ -1,7 +1,7 @@
#ifndef OALDEF_H #ifndef OALDEF_H
#define OALDEF_H #define OALDEF_H
#ifndef NO_OPENAL #if !defined NO_OPENAL && defined DYN_OPENAL
#ifndef _WIN32 #ifndef _WIN32
typedef void* FARPROC; typedef void* FARPROC;

View file

@ -83,6 +83,8 @@ bool IsOpenALPresent()
{ {
#ifdef NO_OPENAL #ifdef NO_OPENAL
return false; return false;
#elif !defined DYN_OPENAL
return true;
#else #else
static bool cached_result = false; static bool cached_result = false;
static bool done = false; static bool done = false;

View file

@ -12,7 +12,9 @@
#ifndef NO_OPENAL #ifndef NO_OPENAL
#ifdef DYN_OPENAL
#define AL_NO_PROTOTYPES #define AL_NO_PROTOTYPES
#endif // DYN_OPENAL
#include "al.h" #include "al.h"
#include "alc.h" #include "alc.h"

View file

@ -483,6 +483,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetZAt)
return 0; 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__ // __decorate_internal_state__
@ -5848,7 +5878,7 @@ enum DMSS
DMSS_EITHER = 256, //Allow either type or species to be affected. 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)), bool filterpass = DoCheckClass(dmgtarget, filter, !!(flags & DMSS_EXFILTER)),
speciespass = DoCheckSpecies(dmgtarget, species, !!(flags & DMSS_EXSPECIES)); 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) if (amount > 0)
{ //Should wind up passing them through just fine. { //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) else if (amount < 0)
{ {
@ -5893,8 +5923,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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; return 0;
} }
@ -5911,9 +5946,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) 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; return 0;
} }
@ -5930,9 +5970,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) 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; return 0;
} }
@ -5949,9 +5994,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) 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; return 0;
} }
@ -5968,6 +6018,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
@ -5975,7 +6030,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
while ( (mo = it.Next()) ) while ( (mo = it.Next()) )
{ {
if (mo->master == self) if (mo->master == self)
DoDamage(mo, self, amount, damagetype, flags, filter, species); DoDamage(mo, inflictor, source, amount, damagetype, flags, filter, species);
} }
return 0; return 0;
} }
@ -5993,6 +6048,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
@ -6002,7 +6062,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
while ((mo = it.Next())) while ((mo = it.Next()))
{ {
if (mo->master == self->master && mo != self) 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; return 0;
@ -6025,7 +6085,7 @@ enum KILS
KILS_EITHER = 1 << 6, 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)), bool filterpass = DoCheckClass(killtarget, filter, !!(flags & KILS_EXFILTER)),
speciespass = DoCheckSpecies(killtarget, species, !!(flags & KILS_EXSPECIES)); 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)) 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_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) if (self->target != NULL)
DoKill(self->target, self, damagetype, flags, filter, species); DoKill(self->target, inflictor, source, damagetype, flags, filter, species);
return 0; return 0;
} }
@ -6088,9 +6153,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) if (self->tracer != NULL)
DoKill(self->tracer, self, damagetype, flags, filter, species); DoKill(self->tracer, inflictor, source, damagetype, flags, filter, species);
return 0; return 0;
} }
@ -6106,9 +6176,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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) if (self->master != NULL)
DoKill(self->master, self, damagetype, flags, filter, species); DoKill(self->master, inflictor, source, damagetype, flags, filter, species);
return 0; return 0;
} }
@ -6124,6 +6199,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
@ -6132,7 +6212,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
{ {
if (mo->master == self) if (mo->master == self)
{ {
DoKill(mo, self, damagetype, flags, filter, species); DoKill(mo, inflictor, source, damagetype, flags, filter, species);
} }
} }
return 0; return 0;
@ -6150,6 +6230,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_CLASS_OPT (filter, AActor){ filter = NULL; } PARAM_CLASS_OPT (filter, AActor){ filter = NULL; }
PARAM_NAME_OPT (species) { species = NAME_None; } 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; TThinkerIterator<AActor> it;
AActor *mo; AActor *mo;
@ -6160,7 +6245,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
{ {
if (mo->master == self->master && mo != self) 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 // Checks to see if a certain actor class is close to the
// actor/pointer within distance, in numbers. // 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) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
{ {
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);
@ -6638,120 +6707,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
ACTION_RETURN_STATE(NULL); ACTION_RETURN_STATE(NULL);
} }
} }
AActor *ref = COPY_AAPTR(self, ptr);
// We need these to check out. if (P_Thing_CheckProximity(self, classname, distance, count, flags, ptr) && jump)
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)
{ {
ACTION_RETURN_STATE(jump); ACTION_RETURN_STATE(jump);
} }

View file

@ -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 float GetZAt(float px = 0, float py = 0, float angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT);
native int GetSpawnHealth(); native int GetSpawnHealth();
native int GetGibHealth(); native int GetGibHealth();
native float GetCrouchFactor(int ptr = AAPTR_PLAYER1);
// Action functions // Action functions
// Meh, MBF redundant functions. Only for DeHackEd support. // 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_SetSpeed(float speed, int ptr = AAPTR_DEFAULT);
native void A_SetFloatSpeed(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_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_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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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_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_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"); action native A_RemoveTracer(int flags = 0, class<Actor> filter = "None", name species = "None");

View file

@ -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_MPPGOLDWAND = "%o was assaulted by %k's elven wand.";
OB_MPPCROSSBOW = "%o was shafted by %k's ethereal crossbow."; OB_MPPCROSSBOW = "%o was shafted by %k's ethereal crossbow.";
OB_MPPBLASTER = "%o was ripped apart by %k's dragon claw."; 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_MPPPHOENIXROD = "%o was burned down by %k's phoenix staff.";
OB_MPPMACE = "%o was squished by %k's giant mace sphere."; OB_MPPMACE = "%o was squished by %k's giant mace sphere.";