mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-17 17:11:19 +00:00
- cleaned up setPointer interface.
- ZDoom part of setPointer/setActivator, submitted by FDARI. SVN r3230 (trunk)
This commit is contained in:
parent
61dfb608f4
commit
5d65ab6e6c
7 changed files with 257 additions and 170 deletions
|
@ -616,6 +616,7 @@ add_executable( zdoom WIN32
|
||||||
${SYSTEM_SOURCES}
|
${SYSTEM_SOURCES}
|
||||||
${X86_SOURCES}
|
${X86_SOURCES}
|
||||||
x86.cpp
|
x86.cpp
|
||||||
|
actorptrselect.cpp
|
||||||
am_map.cpp
|
am_map.cpp
|
||||||
b_bot.cpp
|
b_bot.cpp
|
||||||
b_func.cpp
|
b_func.cpp
|
||||||
|
|
|
@ -715,6 +715,11 @@ public:
|
||||||
int SpawnHealth();
|
int SpawnHealth();
|
||||||
int GibHealth();
|
int GibHealth();
|
||||||
|
|
||||||
|
inline bool isMissile(bool precise=true)
|
||||||
|
{
|
||||||
|
return (flags&MF_MISSILE) || (precise && GetDefault()->flags&MF_MISSILE);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for monsters that count as kill but excludes all friendlies.
|
// Check for monsters that count as kill but excludes all friendlies.
|
||||||
bool CountsAsKill() const
|
bool CountsAsKill() const
|
||||||
{
|
{
|
||||||
|
@ -1046,6 +1051,7 @@ inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
|
||||||
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
|
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrintMiscActorInfo(AActor * query);
|
void PrintMiscActorInfo(AActor * query);
|
||||||
|
|
||||||
#define S_FREETARGMOBJ 1
|
#define S_FREETARGMOBJ 1
|
||||||
|
|
179
src/actorptrselect.cpp
Normal file
179
src/actorptrselect.cpp
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#include "actorptrselect.h"
|
||||||
|
#include "actor.h"
|
||||||
|
#include "d_player.h"
|
||||||
|
#include "p_pspr.h"
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Standard pointer acquisition functions
|
||||||
|
//
|
||||||
|
// Possible effective results at run-time
|
||||||
|
// assigntovariable = NULL (or a RETURN statement is issued)
|
||||||
|
// P_BulletSlope(pointer_owner, &temporary), assigntovariable = temporary
|
||||||
|
// assigntovariable = pointer_owner->target or ...->master or ...->tracer
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
COPY_AAPTR
|
||||||
|
|
||||||
|
Result overview in order of priority:
|
||||||
|
|
||||||
|
1. Caller is player and a player specific selector is specified: Player specific selector is used.
|
||||||
|
2. Caller is non-null and a general actor selector is specified: General actor selector is used.
|
||||||
|
3. A static actor selector is specified: Static actor selector is used.
|
||||||
|
4. The origin actor is used.
|
||||||
|
|
||||||
|
Only one selector of each type can be used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AAPTR_RESOLVE_PLAYERNUM(playernum) (playeringame[playernum] ? players[playernum].mo : NULL)
|
||||||
|
|
||||||
|
AActor *COPY_AAPTR(AActor *origin, int selector)
|
||||||
|
{
|
||||||
|
if (origin)
|
||||||
|
{
|
||||||
|
if (origin->player)
|
||||||
|
{
|
||||||
|
switch (selector & AAPTR_PLAYER_SELECTORS)
|
||||||
|
{
|
||||||
|
case AAPTR_PLAYER_GETTARGET:
|
||||||
|
{
|
||||||
|
AActor *gettarget = NULL;
|
||||||
|
P_BulletSlope(origin, &gettarget);
|
||||||
|
return gettarget;
|
||||||
|
}
|
||||||
|
case AAPTR_PLAYER_GETCONVERSATION:
|
||||||
|
return origin->player->ConversationNPC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (selector & AAPTR_GENERAL_SELECTORS)
|
||||||
|
{
|
||||||
|
case AAPTR_TARGET: return origin->target;
|
||||||
|
case AAPTR_MASTER: return origin->master;
|
||||||
|
case AAPTR_TRACER: return origin->tracer;
|
||||||
|
case AAPTR_FRIENDPLAYER:
|
||||||
|
return origin->FriendPlayer ? AAPTR_RESOLVE_PLAYERNUM(origin->FriendPlayer - 1) : NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (selector & AAPTR_STATIC_SELECTORS)
|
||||||
|
{
|
||||||
|
case AAPTR_PLAYER1: return AAPTR_RESOLVE_PLAYERNUM(0);
|
||||||
|
case AAPTR_PLAYER2: return AAPTR_RESOLVE_PLAYERNUM(1);
|
||||||
|
case AAPTR_PLAYER3: return AAPTR_RESOLVE_PLAYERNUM(2);
|
||||||
|
case AAPTR_PLAYER4: return AAPTR_RESOLVE_PLAYERNUM(3);
|
||||||
|
case AAPTR_PLAYER5: return AAPTR_RESOLVE_PLAYERNUM(4);
|
||||||
|
case AAPTR_PLAYER6: return AAPTR_RESOLVE_PLAYERNUM(5);
|
||||||
|
case AAPTR_PLAYER7: return AAPTR_RESOLVE_PLAYERNUM(6);
|
||||||
|
case AAPTR_PLAYER8: return AAPTR_RESOLVE_PLAYERNUM(7);
|
||||||
|
case AAPTR_NULL: return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// [FDARI] Exported logic for guarding against loops in Target (for missiles) and Master (for all) chains.
|
||||||
|
// It is called from multiple locations.
|
||||||
|
// The code may be in need of optimisation.
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Checks whether this actor is a missile
|
||||||
|
// Unfortunately this was buggy in older versions of the code and many
|
||||||
|
// released DECORATE monsters rely on this bug so it can only be fixed
|
||||||
|
// with an optional flag
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void VerifyTargetChain(AActor *self, bool preciseMissileCheck)
|
||||||
|
{
|
||||||
|
if (!self || !self->isMissile(preciseMissileCheck)) return;
|
||||||
|
|
||||||
|
AActor *origin = self;
|
||||||
|
AActor *next = origin->target;
|
||||||
|
|
||||||
|
// origin: the most recent actor that has been verified as appearing only once
|
||||||
|
// next: the next actor to be verified; will be "origin" in the next iteration
|
||||||
|
|
||||||
|
while (next && next->isMissile(preciseMissileCheck)) // we only care when there are missiles involved
|
||||||
|
{
|
||||||
|
AActor *compare = self;
|
||||||
|
// every new actor must prove not to be the first actor in the chain, or any subsequent actor
|
||||||
|
// any actor up to and including "origin" has only appeared once
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (compare == next)
|
||||||
|
{
|
||||||
|
// if any of the actors from self to (inclusive) origin match the next actor,
|
||||||
|
// self has reached/created a loop
|
||||||
|
self->target = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (compare == origin) break; // when "compare" = origin, we know that the next actor is, and should be "next"
|
||||||
|
compare = compare->target;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin = next;
|
||||||
|
next = next->target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerifyMasterChain(AActor *self)
|
||||||
|
{
|
||||||
|
// See VerifyTargetChain for detailed comments.
|
||||||
|
|
||||||
|
if (!self) return;
|
||||||
|
AActor *origin = self;
|
||||||
|
AActor *next = origin->master;
|
||||||
|
while (next) // We always care (See "VerifyTargetChain")
|
||||||
|
{
|
||||||
|
AActor *compare = self;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (compare == next)
|
||||||
|
{
|
||||||
|
self->master = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (compare == origin) break;
|
||||||
|
compare = compare->master;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin = next;
|
||||||
|
next = next->master;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Checks whether this actor is a missile
|
||||||
|
// Unfortunately this was buggy in older versions of the code and many
|
||||||
|
// released DECORATE monsters rely on this bug so it can only be fixed
|
||||||
|
// with an optional flag
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void ASSIGN_AAPTR(AActor *toActor, int toSlot, AActor *ptr, int flags)
|
||||||
|
{
|
||||||
|
switch (toSlot)
|
||||||
|
{
|
||||||
|
case AAPTR_TARGET:
|
||||||
|
toActor->target = ptr;
|
||||||
|
if (!(PTROP_UNSAFETARGET & (flags))) VerifyTargetChain(toActor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AAPTR_MASTER:
|
||||||
|
toActor->master = ptr;
|
||||||
|
if (!(PTROP_UNSAFEMASTER & (flags))) VerifyMasterChain(toActor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AAPTR_TRACER:
|
||||||
|
toActor->tracer = ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "p_pspr.h"
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Standard pointer acquisition functions
|
// Standard pointer acquisition functions
|
||||||
//
|
//
|
||||||
// Use COPY_AAPTR(pointer_owner, AActor *assigntovariable, AAPTR selector)
|
|
||||||
// Use COPY_AAPTR_NOT_NULL to return from a function if the pointer is NULL
|
|
||||||
//
|
|
||||||
// Possible effective results at run-time
|
// Possible effective results at run-time
|
||||||
// assigntovariable = NULL (or a RETURN statement is issued)
|
// assigntovariable = NULL (or a RETURN statement is issued)
|
||||||
// P_BulletSlope(pointer_owner, &temporary), assigntovariable = temporary
|
// P_BulletSlope(pointer_owner, &temporary), assigntovariable = temporary
|
||||||
|
@ -16,6 +11,7 @@
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
class AActor;
|
||||||
|
|
||||||
// Pointer selectors (enum)
|
// Pointer selectors (enum)
|
||||||
|
|
||||||
|
@ -55,7 +51,7 @@ enum AAPTR
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PROCESS_AAPTR
|
COPY_AAPTR
|
||||||
|
|
||||||
Result overview in order of priority:
|
Result overview in order of priority:
|
||||||
|
|
||||||
|
@ -67,52 +63,36 @@ enum AAPTR
|
||||||
Only one selector of each type can be used.
|
Only one selector of each type can be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define AAPTR_RESOLVE_PLAYERNUM(playernum) (playeringame[playernum] ? players[playernum].mo : NULL)
|
AActor *COPY_AAPTR(AActor *origin, int selector);
|
||||||
|
|
||||||
static AActor *PROCESS_AAPTR(AActor *origin, int selector)
|
// Use COPY_AAPTR_NOT_NULL to return from a function if the pointer is NULL
|
||||||
{
|
#define COPY_AAPTR_NOT_NULL(source, destination, selector) { destination = COPY_AAPTR(source, selector); if (!destination) return; }
|
||||||
if (origin)
|
|
||||||
{
|
|
||||||
if (origin->player)
|
|
||||||
{
|
|
||||||
switch (selector & AAPTR_PLAYER_SELECTORS)
|
|
||||||
{
|
|
||||||
case AAPTR_PLAYER_GETTARGET:
|
|
||||||
{
|
|
||||||
AActor *gettarget = NULL;
|
|
||||||
P_BulletSlope(origin, &gettarget);
|
|
||||||
return gettarget;
|
|
||||||
}
|
|
||||||
case AAPTR_PLAYER_GETCONVERSATION:
|
|
||||||
return origin->player->ConversationNPC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (selector & AAPTR_GENERAL_SELECTORS)
|
|
||||||
{
|
|
||||||
case AAPTR_TARGET: return origin->target;
|
|
||||||
case AAPTR_MASTER: return origin->master;
|
|
||||||
case AAPTR_TRACER: return origin->tracer;
|
|
||||||
case AAPTR_FRIENDPLAYER:
|
|
||||||
return origin->FriendPlayer ? AAPTR_RESOLVE_PLAYERNUM(origin->FriendPlayer - 1) : NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (selector & AAPTR_STATIC_SELECTORS)
|
|
||||||
{
|
|
||||||
case AAPTR_PLAYER1: return AAPTR_RESOLVE_PLAYERNUM(0);
|
|
||||||
case AAPTR_PLAYER2: return AAPTR_RESOLVE_PLAYERNUM(1);
|
|
||||||
case AAPTR_PLAYER3: return AAPTR_RESOLVE_PLAYERNUM(2);
|
|
||||||
case AAPTR_PLAYER4: return AAPTR_RESOLVE_PLAYERNUM(3);
|
|
||||||
case AAPTR_PLAYER5: return AAPTR_RESOLVE_PLAYERNUM(4);
|
|
||||||
case AAPTR_PLAYER6: return AAPTR_RESOLVE_PLAYERNUM(5);
|
|
||||||
case AAPTR_PLAYER7: return AAPTR_RESOLVE_PLAYERNUM(6);
|
|
||||||
case AAPTR_PLAYER8: return AAPTR_RESOLVE_PLAYERNUM(7);
|
|
||||||
case AAPTR_NULL: return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return origin;
|
enum PTROP
|
||||||
}
|
{
|
||||||
|
PTROP_UNSAFETARGET = 1,
|
||||||
|
PTROP_UNSAFEMASTER = 2,
|
||||||
|
PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// [FDARI] Exported logic for guarding against loops in Target (for missiles) and Master (for all) chains.
|
||||||
|
// It is called from multiple locations.
|
||||||
|
// The code may be in need of optimisation.
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Checks whether this actor is a missile
|
||||||
|
// Unfortunately this was buggy in older versions of the code and many
|
||||||
|
// released DECORATE monsters rely on this bug so it can only be fixed
|
||||||
|
// with an optional flag
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void VerifyTargetChain(AActor *self, bool preciseMissileCheck=true);
|
||||||
|
void VerifyMasterChain(AActor *self);
|
||||||
|
void ASSIGN_AAPTR(AActor *toActor, int toSlot, AActor *ptr, int flags) ;
|
||||||
|
|
||||||
#define COPY_AAPTR_NOT_NULL(source, destination, selector) { destination = PROCESS_AAPTR(source, selector); if (!destination) return; }
|
|
||||||
#define COPY_AAPTR(source, destination, selector) { destination = PROCESS_AAPTR(source, selector); }
|
|
|
@ -71,6 +71,7 @@
|
||||||
#include "m_png.h"
|
#include "m_png.h"
|
||||||
#include "p_setup.h"
|
#include "p_setup.h"
|
||||||
#include "po_man.h"
|
#include "po_man.h"
|
||||||
|
#include "actorptrselect.h"
|
||||||
|
|
||||||
#include "g_shared/a_pickups.h"
|
#include "g_shared/a_pickups.h"
|
||||||
|
|
||||||
|
@ -3114,6 +3115,7 @@ enum EACSFunctions
|
||||||
ACSF_CheckSight,
|
ACSF_CheckSight,
|
||||||
ACSF_SpawnForced,
|
ACSF_SpawnForced,
|
||||||
ACSF_AnnouncerSound, // Skulltag
|
ACSF_AnnouncerSound, // Skulltag
|
||||||
|
ACSF_SetPointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
int DLevelScript::SideFromID(int id, int side)
|
int DLevelScript::SideFromID(int id, int side)
|
||||||
|
@ -3248,8 +3250,29 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||||
actor = SingleActorFromTID(args[0], activator);
|
actor = SingleActorFromTID(args[0], activator);
|
||||||
return actor != NULL? actor->velz : 0;
|
return actor != NULL? actor->velz : 0;
|
||||||
|
|
||||||
|
case ACSF_SetPointer:
|
||||||
|
if (activator)
|
||||||
|
{
|
||||||
|
AActor *ptr = SingleActorFromTID(args[1], activator);
|
||||||
|
if (argCount > 2)
|
||||||
|
{
|
||||||
|
ptr = COPY_AAPTR(ptr, args[2]);
|
||||||
|
}
|
||||||
|
if (ptr == activator) ptr = NULL;
|
||||||
|
ASSIGN_AAPTR(activator, args[0], ptr, (argCount > 3) ? args[3] : 0);
|
||||||
|
return ptr != NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
case ACSF_SetActivator:
|
case ACSF_SetActivator:
|
||||||
activator = SingleActorFromTID(args[0], NULL);
|
if (argCount > 1 && args[1] != AAPTR_DEFAULT) // condition (x != AAPTR_DEFAULT) is essentially condition (x).
|
||||||
|
{
|
||||||
|
activator = COPY_AAPTR(SingleActorFromTID(args[0], activator), args[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activator = SingleActorFromTID(args[0], NULL);
|
||||||
|
}
|
||||||
return activator != NULL;
|
return activator != NULL;
|
||||||
|
|
||||||
case ACSF_SetActivatorToTarget:
|
case ACSF_SetActivatorToTarget:
|
||||||
|
@ -3265,16 +3288,16 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||||
{
|
{
|
||||||
actor = actor->target;
|
actor = actor->target;
|
||||||
}
|
}
|
||||||
}
|
if (actor != NULL) // [FDARI] moved this (actor != NULL)-branch inside the other, so that it is only tried when it can be true
|
||||||
if (actor != NULL)
|
{
|
||||||
{
|
activator = actor;
|
||||||
activator = actor;
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case ACSF_GetActorViewHeight:
|
case ACSF_GetActorViewHeight:
|
||||||
actor = SingleActorFromTID(args[0], NULL);
|
actor = SingleActorFromTID(args[0], activator);
|
||||||
if (actor != NULL)
|
if (actor != NULL)
|
||||||
{
|
{
|
||||||
if (actor->player != NULL)
|
if (actor->player != NULL)
|
||||||
|
|
|
@ -137,99 +137,6 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState * State)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Checks whether this actor is a missile
|
|
||||||
// Unfortunately this was buggy in older versions of the code and many
|
|
||||||
// released DECORATE monsters rely on this bug so it can only be fixed
|
|
||||||
// with an optional flag
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
inline static bool isMissile(AActor * self, bool precise=true)
|
|
||||||
{
|
|
||||||
return self->flags&MF_MISSILE || (precise && self->GetDefault()->flags&MF_MISSILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Pointer-based operations
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
enum PTROP
|
|
||||||
{
|
|
||||||
PTROP_UNSAFETARGET = 1,
|
|
||||||
PTROP_UNSAFEMASTER = 2,
|
|
||||||
PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// [FDARI] Exported logic for guarding against loops in Target (for missiles) and Master (for all) chains.
|
|
||||||
// It is called from multiple locations.
|
|
||||||
// The code may be in need of optimisation.
|
|
||||||
|
|
||||||
void VerifyTargetChain(AActor *self, bool preciseMissileCheck=true)
|
|
||||||
{
|
|
||||||
if (!(self && isMissile(self, preciseMissileCheck))) return;
|
|
||||||
AActor *origin = self;
|
|
||||||
AActor *next = origin->target;
|
|
||||||
|
|
||||||
// origin: the most recent actor that has been verified as appearing only once
|
|
||||||
// next: the next actor to be verified; will be "origin" in the next iteration
|
|
||||||
|
|
||||||
while (next && isMissile(next, preciseMissileCheck)) // we only care when there are missiles involved
|
|
||||||
{
|
|
||||||
AActor *compare = self;
|
|
||||||
// every new actor must prove not to be the first actor in the chain, or any subsequent actor
|
|
||||||
// any actor up to and including "origin" has only appeared once
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (compare == next)
|
|
||||||
{
|
|
||||||
// if any of the actors from self to (inclusive) origin match the next actor,
|
|
||||||
// self has reached/created a loop
|
|
||||||
self->target = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (compare == origin) break; // when "compare" = origin, we know that the next actor is, and should be "next"
|
|
||||||
compare = compare->target;
|
|
||||||
}
|
|
||||||
|
|
||||||
origin = next;
|
|
||||||
next = next->target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VerifyMasterChain(AActor *self)
|
|
||||||
{
|
|
||||||
// See VerifyTargetChain for detailed comments.
|
|
||||||
|
|
||||||
if (!self) return;
|
|
||||||
AActor *origin = self;
|
|
||||||
AActor *next = origin->master;
|
|
||||||
while (next) // We always care (See "VerifyTargetChain")
|
|
||||||
{
|
|
||||||
AActor *compare = self;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (compare == next)
|
|
||||||
{
|
|
||||||
self->master = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (compare == origin) break;
|
|
||||||
compare = compare->master;
|
|
||||||
}
|
|
||||||
|
|
||||||
origin = next;
|
|
||||||
next = next->master;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// A_RearrangePointers
|
// A_RearrangePointers
|
||||||
|
@ -308,7 +215,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RearrangePointers)
|
||||||
// A_TransferPointer
|
// A_TransferPointer
|
||||||
//
|
//
|
||||||
// Copy one pointer (MASTER, TARGET or TRACER) from this actor (SELF),
|
// Copy one pointer (MASTER, TARGET or TRACER) from this actor (SELF),
|
||||||
// or from an this actor's MASTER, TARGET or TRACER.
|
// or from this actor's MASTER, TARGET or TRACER.
|
||||||
//
|
//
|
||||||
// You can copy any one of that actor's pointers
|
// You can copy any one of that actor's pointers
|
||||||
//
|
//
|
||||||
|
@ -333,31 +240,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer)
|
||||||
|
|
||||||
// Exchange pointers with actors to whom you have pointers (or with yourself, if you must)
|
// Exchange pointers with actors to whom you have pointers (or with yourself, if you must)
|
||||||
|
|
||||||
COPY_AAPTR(self, source, ptr_source);
|
source = COPY_AAPTR(self, ptr_source);
|
||||||
COPY_AAPTR_NOT_NULL(self, recepient, ptr_recepient); // pick an actor to store the provided pointer value
|
COPY_AAPTR_NOT_NULL(self, recepient, ptr_recepient); // pick an actor to store the provided pointer value
|
||||||
|
|
||||||
// convert source from dataprovider to data
|
// convert source from dataprovider to data
|
||||||
|
|
||||||
COPY_AAPTR(source, source, ptr_sourcefield);
|
source = COPY_AAPTR(source, ptr_sourcefield);
|
||||||
|
|
||||||
if (source == recepient) source = NULL; // The recepient should not acquire a pointer to itself; will write NULL
|
if (source == recepient) source = NULL; // The recepient should not acquire a pointer to itself; will write NULL
|
||||||
|
|
||||||
if (ptr_recepientfield == AAPTR_DEFAULT) ptr_recepientfield = ptr_sourcefield; // If default: Write to same field as data was read from
|
if (ptr_recepientfield == AAPTR_DEFAULT) ptr_recepientfield = ptr_sourcefield; // If default: Write to same field as data was read from
|
||||||
|
|
||||||
switch (ptr_recepientfield) // assignment and safeguards (optional)
|
ASSIGN_AAPTR(recepient, ptr_recepientfield, source, flags);
|
||||||
{
|
|
||||||
case AAPTR_TARGET:
|
|
||||||
recepient->target = source;
|
|
||||||
if (!(PTROP_UNSAFETARGET & flags)) VerifyTargetChain(recepient);
|
|
||||||
break;
|
|
||||||
case AAPTR_MASTER:
|
|
||||||
recepient->master = source;
|
|
||||||
if (!(PTROP_UNSAFEMASTER & flags)) VerifyMasterChain(recepient);
|
|
||||||
break;
|
|
||||||
case AAPTR_TRACER:
|
|
||||||
recepient->tracer = source;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1033,10 +927,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
|
||||||
|
|
||||||
// handle projectile shooting projectiles - track the
|
// handle projectile shooting projectiles - track the
|
||||||
// links back to a real owner
|
// links back to a real owner
|
||||||
if (isMissile(self, !!(flags & CMF_TRACKOWNER)))
|
if (self->isMissile(!!(flags & CMF_TRACKOWNER)))
|
||||||
{
|
{
|
||||||
AActor * owner=self ;//->target;
|
AActor * owner=self ;//->target;
|
||||||
while (isMissile(owner, !!(flags & CMF_TRACKOWNER)) && owner->target) owner=owner->target;
|
while (owner->isMissile(!!(flags & CMF_TRACKOWNER)) && owner->target) owner=owner->target;
|
||||||
targ=owner;
|
targ=owner;
|
||||||
missile->target=owner;
|
missile->target=owner;
|
||||||
// automatic handling of seeker missiles
|
// automatic handling of seeker missiles
|
||||||
|
@ -1777,7 +1671,7 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
||||||
|
|
||||||
mo->angle=self->angle;
|
mo->angle=self->angle;
|
||||||
if (flags & SIXF_TRANSFERPITCH) mo->pitch = self->pitch;
|
if (flags & SIXF_TRANSFERPITCH) mo->pitch = self->pitch;
|
||||||
while (originator && isMissile(originator)) originator = originator->target;
|
while (originator && originator->isMissile()) originator = originator->target;
|
||||||
|
|
||||||
if (flags & SIXF_TELEFRAG)
|
if (flags & SIXF_TELEFRAG)
|
||||||
{
|
{
|
||||||
|
|
|
@ -472,6 +472,10 @@
|
||||||
Name="!Source Files"
|
Name="!Source Files"
|
||||||
Filter="c;cpp"
|
Filter="c;cpp"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\actorptrselect.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\am_map.cpp"
|
RelativePath=".\src\am_map.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue