- Removed AT_GAME_SET(PowerInvulnerable) due to the problems it caused. The two

occurences in the code that depended on it were changed accordingly.
  Invulnerability colormaps are now being set by the items exclusively.
- Changed many checks for the friendly Minotaur to a new flag MF5_SUMMONEDMONSTER
  so that it can hopefully be generalized to be usable elsewhere later.
- Added Gez's submission for converting the Minotaur to DECORATE.


SVN r1120 (trunk)
This commit is contained in:
Christoph Oelckers 2008-08-06 19:25:59 +00:00
parent d7d07aad16
commit bf281a4372
14 changed files with 18821 additions and 18824 deletions

View file

@ -3,6 +3,12 @@ August 6, 2008
GCC defaults to extended precision instead, unlike Visual C++. GCC defaults to extended precision instead, unlike Visual C++.
August 6, 2008 (Changes by Graf Zahl) August 6, 2008 (Changes by Graf Zahl)
- Removed AT_GAME_SET(PowerInvulnerable) due to the problems it caused. The two
occurences in the code that depended on it were changed accordingly.
Invulnerability colormaps are now being set by the items exclusively.
- Changed many checks for the friendly Minotaur to a new flag MF5_SUMMONEDMONSTER
so that it can hopefully be generalized to be usable elsewhere later.
- Added Gez's submission for converting the Minotaur to DECORATE.
- Fixed a few minor DECORATE bugs. - Fixed a few minor DECORATE bugs.
- Changed coordinate storage for EntityBoss so that it works properly even - Changed coordinate storage for EntityBoss so that it works properly even
when the pod is not used to spawn it. when the pod is not used to spawn it.

View file

@ -305,6 +305,7 @@ enum
MF5_PUFFGETSOWNER = 0x00800000, // [BB] Sets the owner of the puff to the player who fired it MF5_PUFFGETSOWNER = 0x00800000, // [BB] Sets the owner of the puff to the player who fired it
MF5_SPECIALFIREDAMAGE=0x01000000, // Special treatment of PhoenixFX1 turned into a flag to removr MF5_SPECIALFIREDAMAGE=0x01000000, // Special treatment of PhoenixFX1 turned into a flag to removr
// dependence of main engine code of specific actor types. // dependence of main engine code of specific actor types.
MF5_SUMMONEDMONSTER = 0x02000000, // To mark the friendly Minotaur. Hopefully to be generalized later.
// --- mobj.renderflags --- // --- mobj.renderflags ---

View file

@ -191,6 +191,18 @@ ACTOR(PhoenixPuff)
ACTOR(FlameEnd) ACTOR(FlameEnd)
ACTOR(FloatPuff) ACTOR(FloatPuff)
// Minotaur stuff
ACTOR(MinotaurDecide)
ACTOR(MinotaurAtk1)
ACTOR(MinotaurAtk2)
ACTOR(MinotaurAtk3)
ACTOR(MinotaurCharge)
ACTOR(MntrFloorFire)
ACTOR(MinotaurLook)
ACTOR(MinotaurRoam)
ACTOR(MinotaurChase)
ACTOR(MinotaurDeath)
ACTOR(BatSpawnInit) ACTOR(BatSpawnInit)
ACTOR(BatSpawn) ACTOR(BatSpawn)

View file

@ -20,132 +20,18 @@ static FRandom pr_minotaurslam ("MinotaurSlam");
static FRandom pr_minotaurroam ("MinotaurRoam"); static FRandom pr_minotaurroam ("MinotaurRoam");
static FRandom pr_minotaurchase ("MinotaurChase"); static FRandom pr_minotaurchase ("MinotaurChase");
void A_MinotaurDecide (AActor *);
void A_MinotaurAtk1 (AActor *);
void A_MinotaurAtk2 (AActor *);
void A_MinotaurAtk3 (AActor *);
void A_MinotaurCharge (AActor *);
void A_MntrFloorFire (AActor *);
void A_MinotaurFade0 (AActor *);
void A_MinotaurFade1 (AActor *);
void A_MinotaurFade2 (AActor *);
void A_MinotaurLook (AActor *); void A_MinotaurLook (AActor *);
void A_MinotaurRoam (AActor *);
void A_SmokePuffExit (AActor *);
void A_MinotaurChase (AActor *);
void P_MinotaurSlam (AActor *source, AActor *target); void P_MinotaurSlam (AActor *source, AActor *target);
// Class definitions -------------------------------------------------------- IMPLEMENT_CLASS(AMinotaur)
FState AMinotaur::States[] =
{
#define S_MNTR_LOOK 0
S_NORMAL (MNTR, 'A', 10, A_MinotaurLook , &States[S_MNTR_LOOK+1]),
S_NORMAL (MNTR, 'B', 10, A_MinotaurLook , &States[S_MNTR_LOOK+0]),
#define S_MNTR_ROAM (S_MNTR_LOOK+2)
S_NORMAL (MNTR, 'A', 5, A_MinotaurRoam , &States[S_MNTR_ROAM+1]),
S_NORMAL (MNTR, 'B', 5, A_MinotaurRoam , &States[S_MNTR_ROAM+2]),
S_NORMAL (MNTR, 'C', 5, A_MinotaurRoam , &States[S_MNTR_ROAM+3]),
S_NORMAL (MNTR, 'D', 5, A_MinotaurRoam , &States[S_MNTR_ROAM]),
#define S_MNTR_WALK (S_MNTR_ROAM+4)
S_NORMAL (MNTR, 'A', 5, A_MinotaurChase , &States[S_MNTR_WALK+1]),
S_NORMAL (MNTR, 'B', 5, A_MinotaurChase , &States[S_MNTR_WALK+2]),
S_NORMAL (MNTR, 'C', 5, A_MinotaurChase , &States[S_MNTR_WALK+3]),
S_NORMAL (MNTR, 'D', 5, A_MinotaurChase , &States[S_MNTR_WALK+0]),
#define S_MNTR_ATK1 (S_MNTR_WALK+4)
S_NORMAL (MNTR, 'V', 10, A_FaceTarget , &States[S_MNTR_ATK1+1]),
S_NORMAL (MNTR, 'W', 7, A_FaceTarget , &States[S_MNTR_ATK1+2]),
S_NORMAL (MNTR, 'X', 12, A_MinotaurAtk1 , &States[S_MNTR_WALK+0]),
#define S_MNTR_ATK2 (S_MNTR_ATK1+3)
S_NORMAL (MNTR, 'V', 10, A_MinotaurDecide , &States[S_MNTR_ATK2+1]),
S_NORMAL (MNTR, 'Y', 4, A_FaceTarget , &States[S_MNTR_ATK2+2]),
S_NORMAL (MNTR, 'Z', 9, A_MinotaurAtk2 , &States[S_MNTR_WALK+0]),
#define S_MNTR_ATK3 (S_MNTR_ATK2+3)
S_NORMAL (MNTR, 'V', 10, A_FaceTarget , &States[S_MNTR_ATK3+1]),
S_NORMAL (MNTR, 'W', 7, A_FaceTarget , &States[S_MNTR_ATK3+2]),
S_NORMAL (MNTR, 'X', 12, A_MinotaurAtk3 , &States[S_MNTR_WALK+0]),
S_NORMAL (MNTR, 'X', 12, NULL , &States[S_MNTR_ATK3+0]),
#define S_MNTR_ATK4 (S_MNTR_ATK3+4)
S_NORMAL (MNTR, 'U', 2, A_MinotaurCharge , &States[S_MNTR_ATK4+0]),
#define S_MNTR_PAIN (S_MNTR_ATK4+1)
S_NORMAL (MNTR, 'E', 3, NULL , &States[S_MNTR_PAIN+1]),
S_NORMAL (MNTR, 'E', 6, A_Pain , &States[S_MNTR_WALK+0]),
#define S_MNTR_DIE (S_MNTR_PAIN+2)
S_NORMAL (MNTR, 'F', 6, NULL , &States[S_MNTR_DIE+1]),
S_NORMAL (MNTR, 'G', 5, NULL , &States[S_MNTR_DIE+2]),
S_NORMAL (MNTR, 'H', 6, A_Scream , &States[S_MNTR_DIE+3]),
S_NORMAL (MNTR, 'I', 5, NULL , &States[S_MNTR_DIE+4]),
S_NORMAL (MNTR, 'J', 6, NULL , &States[S_MNTR_DIE+5]),
S_NORMAL (MNTR, 'K', 5, NULL , &States[S_MNTR_DIE+6]),
S_NORMAL (MNTR, 'L', 6, NULL , &States[S_MNTR_DIE+7]),
S_NORMAL (MNTR, 'M', 5, A_NoBlocking , &States[S_MNTR_DIE+8]),
S_NORMAL (MNTR, 'N', 6, NULL , &States[S_MNTR_DIE+9]),
S_NORMAL (MNTR, 'O', 5, NULL , &States[S_MNTR_DIE+10]),
S_NORMAL (MNTR, 'P', 6, NULL , &States[S_MNTR_DIE+11]),
S_NORMAL (MNTR, 'Q', 5, NULL , &States[S_MNTR_DIE+12]),
S_NORMAL (MNTR, 'R', 6, NULL , &States[S_MNTR_DIE+13]),
S_NORMAL (MNTR, 'S', 5, NULL , &States[S_MNTR_DIE+14]),
S_NORMAL (MNTR, 'T', -1, A_BossDeath , NULL),
#define S_MNTR_FADEIN (S_MNTR_DIE+15)
S_NORMAL (MNTR, 'A', 15, NULL , &States[S_MNTR_FADEIN+1]),
S_NORMAL (MNTR, 'A', 15, A_MinotaurFade1 , &States[S_MNTR_FADEIN+2]),
S_NORMAL (MNTR, 'A', 3, A_MinotaurFade2 , &States[S_MNTR_LOOK]),
#define S_MNTR_FADEOUT (S_MNTR_FADEIN+3)
S_NORMAL (MNTR, 'E', 6, NULL , &States[S_MNTR_FADEOUT+1]),
S_NORMAL (MNTR, 'E', 2, A_Scream , &States[S_MNTR_FADEOUT+2]),
S_NORMAL (MNTR, 'E', 5, A_SmokePuffExit , &States[S_MNTR_FADEOUT+3]),
S_NORMAL (MNTR, 'E', 5, NULL , &States[S_MNTR_FADEOUT+4]),
S_NORMAL (MNTR, 'E', 5, A_NoBlocking , &States[S_MNTR_FADEOUT+5]),
S_NORMAL (MNTR, 'E', 5, NULL , &States[S_MNTR_FADEOUT+6]),
S_NORMAL (MNTR, 'E', 5, A_MinotaurFade1 , &States[S_MNTR_FADEOUT+7]),
S_NORMAL (MNTR, 'E', 5, A_MinotaurFade0 , &States[S_MNTR_FADEOUT+8]),
S_NORMAL (MNTR, 'E', 10, A_BossDeath , NULL),
};
IMPLEMENT_ACTOR (AMinotaur, Heretic, 9, 0)
PROP_SpawnHealth (3000)
PROP_RadiusFixed (28)
PROP_HeightFixed (100)
PROP_Mass (800)
PROP_SpeedFixed (16)
PROP_Damage (7)
PROP_PainChance (25)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_DROPOFF)
PROP_Flags2 (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_BOSS|MF2_PUSHWALL)
PROP_Flags3 (MF3_NORADIUSDMG|MF3_DONTMORPH|MF3_NOTARGET)
PROP_Flags4 (MF4_BOSSDEATH)
PROP_SpawnState (S_MNTR_LOOK)
PROP_SeeState (S_MNTR_WALK)
PROP_PainState (S_MNTR_PAIN)
PROP_MeleeState (S_MNTR_ATK1)
PROP_MissileState (S_MNTR_ATK2)
PROP_DeathState (S_MNTR_DIE)
PROP_SeeSound ("minotaur/sight")
PROP_AttackSound ("minotaur/attack1")
PROP_PainSound ("minotaur/pain")
PROP_DeathSound ("minotaur/death")
PROP_ActiveSound ("minotaur/active")
END_DEFAULTS
void AMinotaur::Tick () void AMinotaur::Tick ()
{ {
Super::Tick (); Super::Tick ();
// The unfriendly Minotaur (Heretic's) is invulnerable while charging // The unfriendly Minotaur (Heretic's) is invulnerable while charging
if (!IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) if (!(flags5 & MF5_SUMMONEDMONSTER))
{ {
// Get MF_SKULLFLY bit and shift it so it matches MF2_INVULNERABLE // Get MF_SKULLFLY bit and shift it so it matches MF2_INVULNERABLE
DWORD flying = (flags & MF_SKULLFLY) << 3; DWORD flying = (flags & MF_SKULLFLY) << 3;
@ -185,45 +71,7 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage)
// Minotaur Friend ---------------------------------------------------------- // Minotaur Friend ----------------------------------------------------------
IMPLEMENT_STATELESS_ACTOR (AMinotaurFriend, Hexen, -1, 0) IMPLEMENT_CLASS(AMinotaurFriend)
PROP_SpawnState (S_MNTR_FADEIN)
PROP_DeathState (S_MNTR_FADEOUT)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (OPAQUE/3)
PROP_SpawnHealth (2500)
PROP_FlagsClear (MF_DROPOFF|MF_COUNTKILL)
PROP_FlagsSet (MF_FRIENDLY)
PROP_Flags2Clear (MF2_BOSS)
PROP_Flags2Set (MF2_TELESTOMP)
PROP_Flags3Set (MF3_STAYMORPHED)
PROP_Flags3Clear (MF3_DONTMORPH)
PROP_Flags4 (MF4_NOTARGETSWITCH)
END_DEFAULTS
AT_GAME_SET (Minotaur)
{
// Modify the Minotaur to accomodate the difference in Hexen's graphics.
// (Hexen's has fewer frames than Heretic's.) Sprites have not been loaded
// yet, so check the wad for their presence.
if (Wads.CheckNumForName ("MNTRZ1", ns_sprites) < 0 &&
Wads.CheckNumForName ("MNTRZ0", ns_sprites) < 0)
{
AMinotaur::States[S_MNTR_ATK1+0].SetFrame ('G');
AMinotaur::States[S_MNTR_ATK1+1].SetFrame ('H');
AMinotaur::States[S_MNTR_ATK1+2].SetFrame ('I');
AMinotaur::States[S_MNTR_ATK2+0].SetFrame ('G');
AMinotaur::States[S_MNTR_ATK2+1].SetFrame ('J');
AMinotaur::States[S_MNTR_ATK2+2].SetFrame ('K');
AMinotaur::States[S_MNTR_ATK3+0].SetFrame ('G');
AMinotaur::States[S_MNTR_ATK3+1].SetFrame ('H');
AMinotaur::States[S_MNTR_ATK3+2].SetFrame ('I');
AMinotaur::States[S_MNTR_ATK3+3].SetFrame ('I');
AMinotaur::States[S_MNTR_ATK4+0].SetFrame ('F');
RUNTIME_CLASS(AMinotaur)->ActorInfo->ChangeState(NAME_Death, &AMinotaur::States[S_MNTR_FADEOUT]);
}
}
void AMinotaurFriend::BeginPlay () void AMinotaurFriend::BeginPlay ()
{ {
@ -264,8 +112,7 @@ bool AMinotaurFriend::IsOkayToAttack (AActor *link)
{ {
return false; return false;
} }
if ((link->IsKindOf (RUNTIME_CLASS(AMinotaur))) && if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == tracer))
(link->tracer == tracer))
{ {
return false; return false;
} }
@ -303,7 +150,7 @@ void AMinotaurFriend::Die (AActor *source, AActor *inflictor)
if (mo == NULL) if (mo == NULL)
{ {
AInventory *power = tracer->FindInventory (RUNTIME_CLASS(APowerMinotaur)); AInventory *power = tracer->FindInventory (PClass::FindClass("PowerMinotaur"));
if (power != NULL) if (power != NULL)
{ {
power->Destroy (); power->Destroy ();
@ -333,6 +180,13 @@ void AMinotaurFriend::NoBlockingSet ()
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void A_MinotaurDeath (AActor *actor)
{
if (Wads.CheckNumForName ("MNTRF1", ns_sprites) < 0 &&
Wads.CheckNumForName ("MNTRF0", ns_sprites) < 0)
actor->SetState(actor->FindState ("FadeOut"));
}
void A_MinotaurAtk1 (AActor *actor) void A_MinotaurAtk1 (AActor *actor)
{ {
player_t *player; player_t *player;
@ -367,7 +221,7 @@ void A_MinotaurAtk1 (AActor *actor)
void A_MinotaurDecide (AActor *actor) void A_MinotaurDecide (AActor *actor)
{ {
bool friendly = actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)); bool friendly = !!(actor->flags5 & MF5_SUMMONEDMONSTER);
angle_t angle; angle_t angle;
AActor *target; AActor *target;
int dist; int dist;
@ -389,7 +243,7 @@ void A_MinotaurDecide (AActor *actor)
&& pr_minotaurdecide() < 150) && pr_minotaurdecide() < 150)
{ // Charge attack { // Charge attack
// Don't call the state function right away // Don't call the state function right away
actor->SetStateNF (&AMinotaur::States[S_MNTR_ATK4]); actor->SetStateNF (actor->FindState ("Charge"));
actor->flags |= MF_SKULLFLY; actor->flags |= MF_SKULLFLY;
if (!friendly) if (!friendly)
{ // Heretic's Minotaur is invulnerable during charge attack { // Heretic's Minotaur is invulnerable during charge attack
@ -405,7 +259,7 @@ void A_MinotaurDecide (AActor *actor)
&& dist < 9*64*FRACUNIT && dist < 9*64*FRACUNIT
&& pr_minotaurdecide() < (friendly ? 100 : 220)) && pr_minotaurdecide() < (friendly ? 100 : 220))
{ // Floor fire attack { // Floor fire attack
actor->SetState (&AMinotaur::States[S_MNTR_ATK3]); actor->SetState (actor->FindState ("Hammer"));
actor->special2 = 0; actor->special2 = 0;
} }
else else
@ -466,7 +320,7 @@ void A_MinotaurAtk2 (AActor *actor)
angle_t angle; angle_t angle;
fixed_t momz; fixed_t momz;
fixed_t z; fixed_t z;
bool friendly = actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)); bool friendly = !!(actor->flags5 & MF5_SUMMONEDMONSTER);
if (!actor->target) if (!actor->target)
{ {
@ -511,7 +365,7 @@ void A_MinotaurAtk3 (AActor *actor)
{ {
AActor *mo; AActor *mo;
player_t *player; player_t *player;
bool friendly = actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)); bool friendly = !!(actor->flags5 & MF5_SUMMONEDMONSTER);
if (!actor->target) if (!actor->target)
{ {
@ -541,7 +395,7 @@ void A_MinotaurAtk3 (AActor *actor)
} }
if (pr_minotauratk3() < 192 && actor->special2 == 0) if (pr_minotauratk3() < 192 && actor->special2 == 0)
{ {
actor->SetState (&AMinotaur::States[S_MNTR_ATK3+3]); actor->SetState (actor->FindState ("Hammer"));
actor->special2 = 1; actor->special2 = 1;
} }
} }
@ -602,25 +456,6 @@ void P_MinotaurSlam (AActor *source, AActor *target)
// tracer pointer to player that spawned it // tracer pointer to player that spawned it
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void A_MinotaurFade0 (AActor *actor)
{
actor->RenderStyle = STYLE_Translucent;
actor->alpha = OPAQUE/3;
}
void A_MinotaurFade1 (AActor *actor)
{
// Second level of transparency
actor->RenderStyle = STYLE_Translucent;
actor->alpha = OPAQUE*2/3;
}
void A_MinotaurFade2 (AActor *actor)
{
// Make fully visible
actor->RenderStyle = STYLE_Normal;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// A_MinotaurRoam // A_MinotaurRoam
@ -671,7 +506,6 @@ void A_MinotaurRoam (AActor *actor)
void A_MinotaurLook (AActor *actor) void A_MinotaurLook (AActor *actor)
{ {
if (!actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend))) if (!actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)))
{ {
A_Look (actor); A_Look (actor);
@ -722,8 +556,7 @@ void A_MinotaurLook (AActor *actor)
dist = P_AproxDistance (actor->x - mo->x, actor->y - mo->y); dist = P_AproxDistance (actor->x - mo->x, actor->y - mo->y);
if (dist > MINOTAUR_LOOK_DIST) continue; if (dist > MINOTAUR_LOOK_DIST) continue;
if ((mo == master) || (mo == actor)) continue; if ((mo == master) || (mo == actor)) continue;
if ((mo->IsKindOf (RUNTIME_CLASS(AMinotaur))) && if ((mo->flags5 & MF5_SUMMONEDMONSTER) && (mo->tracer == master)) continue;
(mo->tracer == master)) continue;
actor->target = mo; actor->target = mo;
break; // Found actor to attack break; // Found actor to attack
} }
@ -731,11 +564,11 @@ void A_MinotaurLook (AActor *actor)
if (actor->target) if (actor->target)
{ {
actor->SetStateNF (&AMinotaur::States[S_MNTR_WALK]); actor->SetStateNF (actor->SeeState);
} }
else else
{ {
actor->SetStateNF (&AMinotaur::States[S_MNTR_ROAM]); actor->SetStateNF (actor->FindState ("Roam"));
} }
} }
@ -764,7 +597,7 @@ void A_MinotaurChase (AActor *actor)
if (!actor->target || (actor->target->health <= 0) || if (!actor->target || (actor->target->health <= 0) ||
!(actor->target->flags&MF_SHOOTABLE)) !(actor->target->flags&MF_SHOOTABLE))
{ // look for a new target { // look for a new target
actor->SetState (&AMinotaur::States[S_MNTR_LOOK]); actor->SetState (actor->FindState ("Spawn"));
return; return;
} }
@ -803,14 +636,3 @@ void A_MinotaurChase (AActor *actor)
} }
} }
/*
void A_SmokePuffEntry(mobj_t *actor)
{
P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE);
}
*/
void A_SmokePuffExit (AActor *actor)
{
Spawn("MinotaurSmokeExit", actor->x, actor->y, actor->z, ALLOW_REPLACE);
}

View file

@ -5,7 +5,7 @@ class AActor;
class AMinotaur : public AActor class AMinotaur : public AActor
{ {
DECLARE_ACTOR (AMinotaur, AActor) DECLARE_CLASS (AMinotaur, AActor)
public: public:
void NoBlockingSet (); void NoBlockingSet ();
int DoSpecialDamage (AActor *target, int damage); int DoSpecialDamage (AActor *target, int damage);
@ -17,7 +17,7 @@ public:
class AMinotaurFriend : public AMinotaur class AMinotaurFriend : public AMinotaur
{ {
DECLARE_STATELESS_ACTOR (AMinotaurFriend, AMinotaur) DECLARE_CLASS (AMinotaurFriend, AMinotaur)
public: public:
int StartTime; int StartTime;

View file

@ -345,25 +345,6 @@ IMPLEMENT_STATELESS_ACTOR (APowerInvulnerable, Any, -1, 0)
PROP_Inventory_Icon ("SPSHLD0") PROP_Inventory_Icon ("SPSHLD0")
END_DEFAULTS END_DEFAULTS
// Need to set the default for each game here
AT_GAME_SET(PowerInvulnerable)
{
APowerInvulnerable * invul = GetDefault<APowerInvulnerable>();
switch (gameinfo.gametype)
{
case GAME_Doom:
case GAME_Strife:
invul->BlendColor = INVERSECOLOR;
break;
case GAME_Heretic:
invul->BlendColor = GOLDCOLOR;
break;
default:
break;
}
}
//=========================================================================== //===========================================================================
// //
// APowerInvulnerable :: InitEffect // APowerInvulnerable :: InitEffect

View file

@ -222,10 +222,18 @@ void cht_DoCheat (player_t *player, int cheat)
item = player->mo->FindInventory (BeholdPowers[i]); item = player->mo->FindInventory (BeholdPowers[i]);
if (item == NULL) if (item == NULL)
{ {
player->mo->GiveInventoryType (BeholdPowers[i]); if (i != 0)
if (cheat == CHT_BEHOLDS)
{ {
P_GiveBody (player->mo, -100); player->mo->GiveInventoryType (BeholdPowers[i]);
if (cheat == CHT_BEHOLDS)
{
P_GiveBody (player->mo, -100);
}
}
else
{
// Let's give the item here so that the power doesn't need colormap information.
player->mo->GiveInventoryType(PClass::FindClass("InvulnerabilitySphere"));
} }
} }
else else

View file

@ -1164,7 +1164,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
{ {
target->DamageType = mod; target->DamageType = mod;
} }
if (source && source->tracer && source->IsKindOf (RUNTIME_CLASS (AMinotaur))) if (source && source->tracer && (source->flags5 & MF5_SUMMONEDMONSTER))
{ // Minotaur's kills go to his master { // Minotaur's kills go to his master
// Make sure still alive and not a pointer to fighter head // Make sure still alive and not a pointer to fighter head
if (source->tracer->player && (source->tracer->player->mo == source->tracer)) if (source->tracer->player && (source->tracer->player->mo == source->tracer))

View file

@ -2492,7 +2492,8 @@ FUNC(LS_SetPlayerProperty)
{ // Give power to activator { // Give power to activator
if (power != 4) if (power != 4)
{ {
it->GiveInventoryType (powers[power]); APowerup *item = static_cast<APowerup*>(it->GiveInventoryType (powers[power]));
if (item != NULL && power == 0) item->BlendColor = INVERSECOLOR;
} }
else if (it->player - players == consoleplayer) else if (it->player - players == consoleplayer)
{ {

View file

@ -796,11 +796,14 @@ AInventory *AActor::GiveInventoryType (const PClass *type)
{ {
AInventory *item; AInventory *item;
item = static_cast<AInventory *>(Spawn (type, 0,0,0, NO_REPLACE)); if (type != NULL)
if (!item->TryPickup (this))
{ {
item->Destroy (); item = static_cast<AInventory *>(Spawn (type, 0,0,0, NO_REPLACE));
return NULL; if (!item->TryPickup (this))
{
item->Destroy ();
return NULL;
}
} }
return item; return item;
} }
@ -2439,8 +2442,7 @@ bool AActor::IsOkayToAttack (AActor *link)
{ {
return false; return false;
} }
if ((link->IsKindOf (RUNTIME_CLASS(AMinotaur))) && if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == this))
(link->tracer == this))
{ {
return false; return false;
} }

View file

@ -245,6 +245,7 @@ static flagdef ActorFlags[]=
DEFINE_FLAG(MF5, NOTIMEFREEZE, AActor, flags5), DEFINE_FLAG(MF5, NOTIMEFREEZE, AActor, flags5),
DEFINE_FLAG(MF5, PUFFGETSOWNER, AActor, flags5), // [BB] added PUFFGETSOWNER DEFINE_FLAG(MF5, PUFFGETSOWNER, AActor, flags5), // [BB] added PUFFGETSOWNER
DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5), DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5),
DEFINE_FLAG(MF5, SUMMONEDMONSTER, AActor, flags5),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -1290,6 +1290,7 @@ void FWadCollection::ScanForFlatHack (int startlump)
void FWadCollection::RenameSprites (int startlump) void FWadCollection::RenameSprites (int startlump)
{ {
bool renameAll; bool renameAll;
bool MNTRZfound = false;
static const DWORD HereticRenames[] = static const DWORD HereticRenames[] =
{ MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich { MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich
@ -1309,6 +1310,7 @@ void FWadCollection::RenameSprites (int startlump)
MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR
MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs
MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX
MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender
}; };
static const DWORD StrifeRenames[] = static const DWORD StrifeRenames[] =
@ -1359,6 +1361,19 @@ void FWadCollection::RenameSprites (int startlump)
renameAll = !!Args->CheckParm ("-oldsprites"); renameAll = !!Args->CheckParm ("-oldsprites");
for (DWORD i = startlump + 1;
i < NumLumps &&
*(DWORD *)LumpInfo[i].name != MAKE_ID('S','_','E','N') &&
*(((DWORD *)LumpInfo[i].name) + 1) != MAKE_ID('D',0,0,0);
++i)
{
if (!strncmp(LumpInfo[i].name, "MNTRZ", 5))
{
MNTRZfound = true;
break;
}
}
for (DWORD i = startlump + 1; for (DWORD i = startlump + 1;
i < NumLumps && i < NumLumps &&
*(DWORD *)LumpInfo[i].name != MAKE_ID('S','_','E','N') && *(DWORD *)LumpInfo[i].name != MAKE_ID('S','_','E','N') &&
@ -1375,6 +1390,24 @@ void FWadCollection::RenameSprites (int startlump)
*(DWORD *)LumpInfo[i].name = renames[j*2+1]; *(DWORD *)LumpInfo[i].name = renames[j*2+1];
} }
} }
if (gameinfo.gametype == GAME_Hexen)
{
if (CheckLumpName (i, "ARTIINVU"))
{
LumpInfo[i].name[4]='D'; LumpInfo[i].name[5]='E';
LumpInfo[i].name[6]='F'; LumpInfo[i].name[7]='N';
}
}
}
if (!MNTRZfound) //gameinfo.gametype == GAME_Hexen && LumpInfo[i].wadnum == IWAD_FILENUM)
{
if (*(DWORD *)LumpInfo[i].name == MAKE_ID('M', 'N', 'T', 'R'))
{
if (LumpInfo[i].name[4] >= 'F' && LumpInfo[i].name[4] <= 'K')
{
LumpInfo[i].name[4] += 'U' - 'F';
}
}
} }
// When not playing Doom rename all BLOD sprites to BLUD so that // When not playing Doom rename all BLOD sprites to BLUD so that

View file

@ -1,3 +1,133 @@
ACTOR Minotaur 9 native
{
Game Heretic
Health 3000
Radius 28
Height 100
Mass 800
Speed 16
Damage 7
Painchance 25
Monster
+DROPOFF
+FLOORCLIP
+BOSS
+NORADIUSDMG
+DONTMORPH
+NOTARGET
+BOSSDEATH
SeeSound "minotaur/sight"
AttackSound "minotaur/attack1"
PainSound "minotaur/pain"
DeathSound "minotaur/death"
ActiveSound "minotaur/active"
DropItem "ArtiSuperHealth", 51
DropItem "PhoenixRodAmmo", 84, 10
action native A_MinotaurDecide();
action native A_MinotaurAtk1();
action native A_MinotaurAtk2();
action native A_MinotaurAtk3();
action native A_MinotaurCharge();
action native A_MntrFloorFire();
action native A_MinotaurLook();
action native A_MinotaurRoam();
action native A_MinotaurChase();
action native A_MinotaurDeath();
States
{
Spawn:
MNTR AB 10 A_MinotaurLook
Loop
Roam:
MNTR ABCD 5 A_MinotaurRoam
Loop
See:
MNTR ABCD 5 A_MinotaurChase
Loop
Melee:
MNTR V 10 A_FaceTarget
MNTR W 7 A_FaceTarget
MNTR X 12 A_MinotaurAtk1
Goto See
Missile:
MNTR V 10 A_MinotaurDecide
MNTR Y 4 A_FaceTarget
MNTR Z 9 A_MinotaurAtk2
Goto See
Hammer:
MNTR V 10 A_FaceTarget
MNTR W 7 A_FaceTarget
MNTR X 12 A_MinotaurAtk3
Goto See
MNTR X 12
Loop
Charge:
MNTR U 2 A_MinotaurCharge
Loop
Pain:
MNTR E 3
MNTR E 6 A_Pain
Goto See
Death:
MNTR F 6 A_MinotaurDeath
MNTR G 5
MNTR H 6 A_Scream
MNTR I 5
MNTR J 6
MNTR K 5
MNTR L 6
MNTR M 5 A_NoBlocking
MNTR N 6
MNTR O 5
MNTR P 6
MNTR Q 5
MNTR R 6
MNTR S 5
MNTR T -1 A_BossDeath
Stop
FadeOut:
MNTR E 6
MNTR E 2 A_Scream
MNTR E 5 A_SpawnItemEx("MinotaurSmokeExit")
MNTR E 5
MNTR E 5 A_NoBlocking
MNTR E 5
MNTR E 5 A_SetTranslucent(0.66, 0)
MNTR E 5 A_SetTranslucent(0.33, 0)
MNTR E 10 A_BossDeath
Stop
}
}
ACTOR MinotaurFriend : Minotaur native
{
Game Hexen
Health 2500
-DROPOFF
-BOSS
-DONTMORPH
+FRIENDLY
+NOTARGETSWITCH
+STAYMORPHED
+TELESTOMP
+SUMMONEDMONSTER
RenderStyle Translucent
Alpha 0.3333
DropItem "None"
States
{
Spawn:
MNTR A 15
MNTR A 15 A_SetTranslucent(0.66, 0)
MNTR A 3 A_SetTranslucent(1, 0)
Goto Super::Spawn
Death:
Goto FadeOut
}
}
// Minotaur FX 1 ------------------------------------------------------------ // Minotaur FX 1 ------------------------------------------------------------
ACTOR MinotaurFX1 ACTOR MinotaurFX1

View file

@ -65,7 +65,7 @@ ACTOR ArtiFly : PowerupGiver 83
} }
} }
// Invulnerability Heretic --------------------------------------------------- // Invulnerability Heretic (Ring of invincibility) --------------------------
ACTOR ArtiInvulnerability : PowerupGiver 84 ACTOR ArtiInvulnerability : PowerupGiver 84
{ {
@ -87,7 +87,7 @@ ACTOR ArtiInvulnerability : PowerupGiver 84
} }
} }
// Invulnerability Hexen ---------------------------------------------------------- // Invulnerability Hexen (Icon of the defender) -----------------------------
ACTOR ArtiInvulnerability2 : PowerupGiver 84 ACTOR ArtiInvulnerability2 : PowerupGiver 84
{ {
@ -97,13 +97,13 @@ ACTOR ArtiInvulnerability2 : PowerupGiver 84
+FLOATBOB +FLOATBOB
+INVENTORY.PICKUPFLASH +INVENTORY.PICKUPFLASH
Inventory.RespawnTics 4230 Inventory.RespawnTics 4230
Inventory.Icon ARTIINVU Inventory.Icon ARTIDEFN
Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY2" Inventory.PickupMessage "$TXT_ARTIINVULNERABILITY2"
Powerup.Type Invulnerable Powerup.Type Invulnerable
States States
{ {
Spawn: Spawn:
INVU ABCD 3 DEFN ABCD 3
Loop Loop
} }
} }