mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- Added Gez's seeker missile submission.
SVN r1905 (trunk)
This commit is contained in:
parent
819158a8fe
commit
4a81f55fb0
13 changed files with 74 additions and 139 deletions
|
@ -1,4 +1,5 @@
|
|||
October 9, 2009 (Changes by Graf Zahl)
|
||||
- Added Gez's seeker missile submission.
|
||||
- Added Gez's thing activation submission.
|
||||
- added a NULL pointer check to fog spawning in unmorphing code.
|
||||
- fixed: frozen corpses need to be treated as solid by z-movement code.
|
||||
|
|
|
@ -217,7 +217,7 @@ enum
|
|||
MF3_CRASHED = 0x00200000, // Actor entered its crash state
|
||||
MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles)
|
||||
MF3_AVOIDMELEE = 0x00800000, // Avoids melee attacks (same as MBF's monster_backing but must be explicitly set)
|
||||
/* = 0x01000000, */
|
||||
MF3_SCREENSEEKER = 0x01000000, // Fails the IsOkayToAttack test if potential target is outside player FOV
|
||||
MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things
|
||||
MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact
|
||||
MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood
|
||||
|
@ -608,7 +608,7 @@ public:
|
|||
virtual bool SpecialBlastHandling (AActor *source, fixed_t strength);
|
||||
|
||||
// Called by RoughBlockCheck
|
||||
virtual bool IsOkayToAttack (AActor *target);
|
||||
bool IsOkayToAttack (AActor *target);
|
||||
|
||||
// Plays the actor's ActiveSound if its voice isn't already making noise.
|
||||
void PlayActiveSound ();
|
||||
|
|
|
@ -145,36 +145,6 @@ bool AHolySpirit::SpecialBlastHandling (AActor *source, fixed_t strength)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AHolySpirit::IsOkayToAttack (AActor *link)
|
||||
{
|
||||
if ((link->flags3&MF3_ISMONSTER ||
|
||||
(link->player && link != target))
|
||||
&& !(link->flags2&MF2_DORMANT))
|
||||
{
|
||||
if (target != NULL && link->IsFriend(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(link->flags & MF_SHOOTABLE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (multiplayer && !deathmatch && link->player && target != NULL && target->player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (link == target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (P_CheckSight (this, link))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_CHolyAttack2
|
||||
|
|
|
@ -9,7 +9,6 @@ class AHolySpirit : public AActor
|
|||
public:
|
||||
bool Slam (AActor *thing);
|
||||
bool SpecialBlastHandling (AActor *source, fixed_t strength);
|
||||
bool IsOkayToAttack (AActor *link);
|
||||
};
|
||||
|
||||
class AFighterWeapon : public AWeapon
|
||||
|
|
|
@ -88,7 +88,6 @@ class AMageStaffFX2 : public AActor
|
|||
DECLARE_CLASS(AMageStaffFX2, AActor)
|
||||
public:
|
||||
int SpecialMissileHit (AActor *victim);
|
||||
bool IsOkayToAttack (AActor *link);
|
||||
bool SpecialBlastHandling (AActor *source, fixed_t strength);
|
||||
};
|
||||
|
||||
|
@ -106,41 +105,6 @@ int AMageStaffFX2::SpecialMissileHit (AActor *victim)
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool AMageStaffFX2::IsOkayToAttack (AActor *link)
|
||||
{
|
||||
if (((link->flags3 & MF3_ISMONSTER) || link->player) && !(link->flags2 & MF2_DORMANT))
|
||||
{
|
||||
if (!(link->flags & MF_SHOOTABLE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (multiplayer && !deathmatch && link->player && target->player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (link == target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (target != NULL && target->IsFriend(link))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (P_CheckSight (this, link))
|
||||
{
|
||||
AActor *master = target;
|
||||
angle_t angle = R_PointToAngle2 (master->x, master->y,
|
||||
link->x, link->y) - master->angle;
|
||||
angle >>= 24;
|
||||
if (angle>226 || angle<30)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AMageStaffFX2::SpecialBlastHandling (AActor *source, fixed_t strength)
|
||||
{
|
||||
// Reflect to originator
|
||||
|
|
|
@ -82,49 +82,6 @@ void AMinotaurFriend::Serialize (FArchive &arc)
|
|||
arc << StartTime;
|
||||
}
|
||||
|
||||
bool AMinotaurFriend::IsOkayToAttack (AActor *link)
|
||||
{
|
||||
if ((link->flags3 & MF3_ISMONSTER) && (link != tracer))
|
||||
{
|
||||
if (!((link->flags ^ flags) & MF_FRIENDLY))
|
||||
{ // Don't attack friends
|
||||
if (link->flags & MF_FRIENDLY)
|
||||
{
|
||||
if (!deathmatch || link->FriendPlayer == 0 || FriendPlayer == 0 ||
|
||||
link->FriendPlayer != FriendPlayer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!(link->flags&MF_SHOOTABLE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (link->flags2&MF2_DORMANT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == tracer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (multiplayer && !deathmatch && link->player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (P_CheckSight (this, link))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AMinotaurFriend::Die (AActor *source, AActor *inflictor)
|
||||
{
|
||||
Super::Die (source, inflictor);
|
||||
|
|
|
@ -20,7 +20,6 @@ class AMinotaurFriend : public AMinotaur
|
|||
public:
|
||||
int StartTime;
|
||||
|
||||
bool IsOkayToAttack (AActor *target);
|
||||
void Die (AActor *source, AActor *inflictor);
|
||||
bool OkayToSwitchTarget (AActor *other);
|
||||
void BeginPlay ();
|
||||
|
|
|
@ -2693,36 +2693,59 @@ void AActor::PlayActiveSound ()
|
|||
|
||||
bool AActor::IsOkayToAttack (AActor *link)
|
||||
{
|
||||
if (player) // Minotaur looking around player
|
||||
{
|
||||
if ((link->flags3 & MF3_ISMONSTER) || (link->player && (link != this)))
|
||||
{
|
||||
if (IsFriend(link))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(link->flags & MF_SHOOTABLE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (link->flags2 & MF2_DORMANT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == this))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (multiplayer && !deathmatch && link->player)
|
||||
{
|
||||
if (!(player // Original AActor::IsOkayToAttack was only for players
|
||||
// || (flags & MF_FRIENDLY) // Maybe let friendly monsters use the function as well?
|
||||
|| (flags5 & MF5_SUMMONEDMONSTER) // AMinotaurFriend has its own version, generalized to other summoned monsters
|
||||
|| (flags2 & MF2_SEEKERMISSILE))) // AHolySpirit and AMageStaffFX2 as well, generalized to other seeker missiles
|
||||
{ // Normal monsters and other actors always return false.
|
||||
return false;
|
||||
}
|
||||
// Standard things to eliminate: an actor shouldn't attack itself,
|
||||
// or a non-shootable, dormant, non-player-and-non-monster actor.
|
||||
if (link == this) return false;
|
||||
if (!(link->player||(link->flags3 & MF3_ISMONSTER)))return false;
|
||||
if (!(link->flags & MF_SHOOTABLE)) return false;
|
||||
if (link->flags2 & MF2_DORMANT) return false;
|
||||
|
||||
// An actor shouldn't attack friendly actors. The reference depends
|
||||
// on the type of actor: for a player's actor, itself; for a projectile,
|
||||
// its target; and for a summoned minion, its tracer.
|
||||
AActor * Friend = NULL;
|
||||
if (player) Friend = this;
|
||||
else if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer;
|
||||
else if (flags2 & MF2_SEEKERMISSILE) Friend = target;
|
||||
else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo;
|
||||
|
||||
// Friend checks
|
||||
if (link == Friend) return false;
|
||||
if (Friend == NULL) return false;
|
||||
if (Friend->IsFriend(link)) return false;
|
||||
if ((link->flags5 & MF5_SUMMONEDMONSTER) // No attack against minions on the same side
|
||||
&& (link->tracer == Friend)) return false;
|
||||
if (multiplayer && !deathmatch // No attack against fellow players in coop
|
||||
&& link->player && Friend->player) return false;
|
||||
if (((flags & link->flags) & MF_FRIENDLY) // No friendly infighting amongst minions
|
||||
&& IsFriend(link)) return false;
|
||||
|
||||
// Now that all the actor checks are made, the line of sight can be checked
|
||||
if (P_CheckSight (this, link))
|
||||
{
|
||||
// AMageStaffFX2::IsOkayToAttack had an extra check here, generalized with a flag,
|
||||
// to only allow the check to succeed if the enemy was in a ~84° FOV of the player
|
||||
if (flags3 & MF3_SCREENSEEKER)
|
||||
{
|
||||
angle_t angle = R_PointToAngle2(Friend->x,
|
||||
Friend->y, link->x, link->y) - Friend->angle;
|
||||
angle >>= 24;
|
||||
if (angle>226 || angle<30)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Other actors are not concerned by this check
|
||||
else return true;
|
||||
}
|
||||
// The sight check was failed, or the angle wasn't right for a screenseeker
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -342,12 +342,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSoundEx)
|
|||
// Generic seeker missile function
|
||||
//
|
||||
//==========================================================================
|
||||
static FRandom pr_seekermissile ("SeekerMissile");
|
||||
enum
|
||||
{
|
||||
SMF_LOOK = 1,
|
||||
};
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_START(5);
|
||||
ACTION_PARAM_INT(ang1, 0);
|
||||
ACTION_PARAM_INT(ang2, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
ACTION_PARAM_INT(chance, 3);
|
||||
ACTION_PARAM_INT(distance, 4);
|
||||
|
||||
if ((flags & SMF_LOOK) && (self->tracer == 0) && (pr_seekermissile()<chance))
|
||||
{
|
||||
self->tracer = P_RoughMonsterSearch (self, distance);
|
||||
}
|
||||
P_SeekerMissile(self, clamp<int>(ang1, 0, 90) * ANGLE_1, clamp<int>(ang2, 0, 90) * ANGLE_1);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags),
|
||||
DEFINE_FLAG(MF, STEALTH, AActor, flags),
|
||||
DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
|
||||
|
||||
DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2),
|
||||
|
@ -121,6 +122,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF2, DORMANT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2),
|
||||
|
||||
DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3),
|
||||
|
@ -141,13 +143,15 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, SCREENSEEKER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3),
|
||||
|
||||
DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4),
|
||||
|
|
|
@ -178,7 +178,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
|
||||
action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
|
||||
action native A_StopSoundEx(coerce name slot);
|
||||
action native A_SeekerMissile(int threshold, int turnmax);
|
||||
action native A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
|
||||
action native A_Jump(int chance = 256, state label, ...);
|
||||
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
|
||||
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, bool aimfacing = false);
|
||||
|
|
|
@ -76,6 +76,9 @@ const int BF_USEAMMO = 1;
|
|||
const int BF_DONTWARN = 2;
|
||||
const int BF_AFFECTBOSSES = 4;
|
||||
|
||||
// Flags for A_SeekerMissile
|
||||
const int SMF_LOOK = 1;
|
||||
|
||||
// Activation flags
|
||||
enum
|
||||
{
|
||||
|
@ -97,6 +100,8 @@ const int AF_TriggerTargets = 4;
|
|||
const int AF_MonsterTrigger = 8;
|
||||
const int AF_MissileTrigger = 16;
|
||||
const int AF_ClearSpecial = 32;
|
||||
const int AF_NoDeathSpecial = 64;
|
||||
const int AF_TriggerActs = 128;
|
||||
|
||||
// constants for A_PlaySound
|
||||
enum
|
||||
|
|
|
@ -125,6 +125,7 @@ ACTOR MageStaffFX2 native
|
|||
DamageType "Fire"
|
||||
Projectile
|
||||
+SEEKERMISSILE
|
||||
+SCREENSEEKER
|
||||
+EXTREMEDEATH
|
||||
DeathSound "MageStaffExplode"
|
||||
|
||||
|
|
Loading…
Reference in a new issue