- Added Gez's seeker missile submission.

SVN r1905 (trunk)
This commit is contained in:
Christoph Oelckers 2009-10-09 20:54:28 +00:00
parent 819158a8fe
commit 4a81f55fb0
13 changed files with 74 additions and 139 deletions

View file

@ -1,4 +1,5 @@
October 9, 2009 (Changes by Graf Zahl) October 9, 2009 (Changes by Graf Zahl)
- Added Gez's seeker missile submission.
- Added Gez's thing activation submission. - Added Gez's thing activation submission.
- added a NULL pointer check to fog spawning in unmorphing code. - added a NULL pointer check to fog spawning in unmorphing code.
- fixed: frozen corpses need to be treated as solid by z-movement code. - fixed: frozen corpses need to be treated as solid by z-movement code.

View file

@ -217,7 +217,7 @@ enum
MF3_CRASHED = 0x00200000, // Actor entered its crash state MF3_CRASHED = 0x00200000, // Actor entered its crash state
MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles) 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) 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_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things
MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact
MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood
@ -608,7 +608,7 @@ public:
virtual bool SpecialBlastHandling (AActor *source, fixed_t strength); virtual bool SpecialBlastHandling (AActor *source, fixed_t strength);
// Called by RoughBlockCheck // 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. // Plays the actor's ActiveSound if its voice isn't already making noise.
void PlayActiveSound (); void PlayActiveSound ();

View file

@ -145,36 +145,6 @@ bool AHolySpirit::SpecialBlastHandling (AActor *source, fixed_t strength)
return true; 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 // A_CHolyAttack2

View file

@ -9,7 +9,6 @@ class AHolySpirit : public AActor
public: public:
bool Slam (AActor *thing); bool Slam (AActor *thing);
bool SpecialBlastHandling (AActor *source, fixed_t strength); bool SpecialBlastHandling (AActor *source, fixed_t strength);
bool IsOkayToAttack (AActor *link);
}; };
class AFighterWeapon : public AWeapon class AFighterWeapon : public AWeapon

View file

@ -88,7 +88,6 @@ class AMageStaffFX2 : public AActor
DECLARE_CLASS(AMageStaffFX2, AActor) DECLARE_CLASS(AMageStaffFX2, AActor)
public: public:
int SpecialMissileHit (AActor *victim); int SpecialMissileHit (AActor *victim);
bool IsOkayToAttack (AActor *link);
bool SpecialBlastHandling (AActor *source, fixed_t strength); bool SpecialBlastHandling (AActor *source, fixed_t strength);
}; };
@ -106,41 +105,6 @@ int AMageStaffFX2::SpecialMissileHit (AActor *victim)
return -1; 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) bool AMageStaffFX2::SpecialBlastHandling (AActor *source, fixed_t strength)
{ {
// Reflect to originator // Reflect to originator

View file

@ -82,49 +82,6 @@ void AMinotaurFriend::Serialize (FArchive &arc)
arc << StartTime; 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) void AMinotaurFriend::Die (AActor *source, AActor *inflictor)
{ {
Super::Die (source, inflictor); Super::Die (source, inflictor);

View file

@ -20,7 +20,6 @@ class AMinotaurFriend : public AMinotaur
public: public:
int StartTime; int StartTime;
bool IsOkayToAttack (AActor *target);
void Die (AActor *source, AActor *inflictor); void Die (AActor *source, AActor *inflictor);
bool OkayToSwitchTarget (AActor *other); bool OkayToSwitchTarget (AActor *other);
void BeginPlay (); void BeginPlay ();

View file

@ -2693,36 +2693,59 @@ void AActor::PlayActiveSound ()
bool AActor::IsOkayToAttack (AActor *link) bool AActor::IsOkayToAttack (AActor *link)
{ {
if (player) // Minotaur looking around player if (!(player // Original AActor::IsOkayToAttack was only for players
{ // || (flags & MF_FRIENDLY) // Maybe let friendly monsters use the function as well?
if ((link->flags3 & MF3_ISMONSTER) || (link->player && (link != this))) || (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
if (IsFriend(link)) { // Normal monsters and other actors always return false.
{
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)
{
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)) 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; 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; return false;
} }

View file

@ -342,12 +342,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSoundEx)
// Generic seeker missile function // Generic seeker missile function
// //
//========================================================================== //==========================================================================
static FRandom pr_seekermissile ("SeekerMissile");
enum
{
SMF_LOOK = 1,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile)
{ {
ACTION_PARAM_START(2); ACTION_PARAM_START(5);
ACTION_PARAM_INT(ang1, 0); ACTION_PARAM_INT(ang1, 0);
ACTION_PARAM_INT(ang2, 1); 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); P_SeekerMissile(self, clamp<int>(ang1, 0, 90) * ANGLE_1, clamp<int>(ang2, 0, 90) * ANGLE_1);
} }

View file

@ -92,6 +92,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags), DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags),
DEFINE_FLAG(MF, STEALTH, AActor, flags), DEFINE_FLAG(MF, STEALTH, AActor, flags),
DEFINE_FLAG(MF, ICECORPSE, AActor, flags), DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2), DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2), DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2), DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2),
@ -121,6 +122,7 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF2, DORMANT, AActor, flags2), DEFINE_FLAG(MF2, DORMANT, AActor, flags2),
DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2), DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2),
DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2), DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2),
DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3), DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3),
DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3), DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3),
DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3), DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3),
@ -141,13 +143,15 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF3, NOTARGET, AActor, flags3), DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
DEFINE_FLAG(MF3, DONTGIB, AActor, flags3), DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3), DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3),
DEFINE_FLAG(MF3, FULLVOLDEATH, 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, FOILINVUL, AActor, flags3),
DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3), DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3), DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3),
DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3), DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3),
DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3), DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3),
DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4), DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4),
DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4), DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4),
DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4), DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4),

View file

@ -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_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_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
action native A_StopSoundEx(coerce name slot); 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_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_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); action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, bool aimfacing = false);

View file

@ -76,6 +76,9 @@ const int BF_USEAMMO = 1;
const int BF_DONTWARN = 2; const int BF_DONTWARN = 2;
const int BF_AFFECTBOSSES = 4; const int BF_AFFECTBOSSES = 4;
// Flags for A_SeekerMissile
const int SMF_LOOK = 1;
// Activation flags // Activation flags
enum enum
{ {
@ -97,6 +100,8 @@ const int AF_TriggerTargets = 4;
const int AF_MonsterTrigger = 8; const int AF_MonsterTrigger = 8;
const int AF_MissileTrigger = 16; const int AF_MissileTrigger = 16;
const int AF_ClearSpecial = 32; const int AF_ClearSpecial = 32;
const int AF_NoDeathSpecial = 64;
const int AF_TriggerActs = 128;
// constants for A_PlaySound // constants for A_PlaySound
enum enum

View file

@ -125,6 +125,7 @@ ACTOR MageStaffFX2 native
DamageType "Fire" DamageType "Fire"
Projectile Projectile
+SEEKERMISSILE +SEEKERMISSILE
+SCREENSEEKER
+EXTREMEDEATH +EXTREMEDEATH
DeathSound "MageStaffExplode" DeathSound "MageStaffExplode"