- Removed ABossEye::Serialize because it didn't do anything.

- Fixed the issues with .96x's railgun code and added it to the current
  version.
- Fixed: Setting of the friendly Minotaur's angle was inconsistent and
  could cause it to move backwards in a féw situation.
- Fixed: The minotaur did checks for type by checking for the MF_FRIENDLY
  flag, not by checking for the actor class. That made it impossible to
  spawn friendly 'normal' minotaurs.
- Moved a few virtual methods which are only applicable to the friendly
  minotaur to AMinotaurFriend.
- Fixed: The friendly minotaur checked the master's health instead of
  the target's when deciding whether to switch targets. Replaced with
  MF4_NOTARGETSWITCH.
- Fixed: maybedrawnow must not draw the console unless the background
  texture has been set up.

SVN r66 (trunk)
This commit is contained in:
Christoph Oelckers 2006-04-23 20:12:27 +00:00
parent b229d07500
commit 790ff69f52
20 changed files with 312 additions and 241 deletions

View file

@ -1,4 +1,19 @@
April 22, 2006 (Changes by Graf Zahl) April 22, 2006 (Changes by Graf Zahl)
- Removed ABossEye::Serialize because it didn't do anything.
- Fixed the issues with .96x's railgun code and added it to the current
version.
- Fixed: Setting of the friendly Minotaur's angle was inconsistent and
could cause it to move backwards in a féw situation.
- Fixed: The minotaur did checks for type by checking for the MF_FRIENDLY
flag, not by checking for the actor class. That made it impossible to
spawn friendly 'normal' minotaurs.
- Moved a few virtual methods which are only applicable to the friendly
minotaur to AMinotaurFriend.
- Fixed: The friendly minotaur checked the master's health instead of
the target's when deciding whether to switch targets. Replaced with
MF4_NOTARGETSWITCH.
- Fixed: maybedrawnow must not draw the console unless the background
texture has been set up.
- Fixed: V_InitCustomFonts initialized lastlump to -1 instead of 0. - Fixed: V_InitCustomFonts initialized lastlump to -1 instead of 0.
- Fixed: CreateTexture never checked whether it could read from the - Fixed: CreateTexture never checked whether it could read from the
texture lump. Since the minimum valid length is 13 bytes for a texture lump. Since the minimum valid length is 13 bytes for a

View file

@ -205,7 +205,7 @@ CUSTOM_CVAR (Int, msgmidcolor2, 4, CVAR_ARCHIVE)
static void maybedrawnow (bool tick, bool force) static void maybedrawnow (bool tick, bool force)
{ {
if (ConsoleDrawing || screen->IsLocked ()) if (ConsoleDrawing || !gotconback || screen->IsLocked ())
{ {
return; return;
} }

View file

@ -76,10 +76,11 @@ public:
{ {
INVUL_Start, INVUL_Start,
INVUL_Active, INVUL_Active,
INVUL_Stop INVUL_Stop,
INVUL_GetAlpha
}; };
virtual void SpecialInvulnerabilityHandling (EInvulState state); virtual void SpecialInvulnerabilityHandling (EInvulState state, fixed_t * pAlpha=NULL);
void BeginPlay (); void BeginPlay ();
void Die (AActor *source, AActor *inflictor); void Die (AActor *source, AActor *inflictor);

View file

@ -86,8 +86,6 @@ END_DEFAULTS
class ABossEye : public AActor class ABossEye : public AActor
{ {
DECLARE_ACTOR (ABossEye, AActor) DECLARE_ACTOR (ABossEye, AActor)
public:
void Serialize (FArchive &arc);
}; };
FState ABossEye::States[] = FState ABossEye::States[] =
@ -108,11 +106,6 @@ IMPLEMENT_ACTOR (ABossEye, Doom, 89, 0)
PROP_SeeState (S_BRAINEYESEE) PROP_SeeState (S_BRAINEYESEE)
END_DEFAULTS END_DEFAULTS
void ABossEye::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
IMPLEMENT_STATELESS_ACTOR (ABossTarget, Doom, 87, 0) IMPLEMENT_STATELESS_ACTOR (ABossTarget, Doom, 87, 0)
PROP_HeightFixed (32) PROP_HeightFixed (32)
PROP_Flags (MF_NOBLOCKMAP|MF_NOSECTOR) PROP_Flags (MF_NOBLOCKMAP|MF_NOSECTOR)

View file

@ -8,6 +8,7 @@
#include "p_enemy.h" #include "p_enemy.h"
#include "a_action.h" #include "a_action.h"
#include "a_hexenglobal.h" #include "a_hexenglobal.h"
#include "templates.h"
// The cleric --------------------------------------------------------------- // The cleric ---------------------------------------------------------------
@ -140,7 +141,7 @@ fixed_t AClericPlayer::GetJumpZ ()
return FRACUNIT*39/4; // ~9.75 return FRACUNIT*39/4; // ~9.75
} }
void AClericPlayer::SpecialInvulnerabilityHandling (EInvulState state) void AClericPlayer::SpecialInvulnerabilityHandling (EInvulState state, fixed_t * pAlpha)
{ {
if (state == INVUL_Active) if (state == INVUL_Active)
{ {
@ -176,6 +177,10 @@ void AClericPlayer::SpecialInvulnerabilityHandling (EInvulState state)
RenderStyle = STYLE_Normal; RenderStyle = STYLE_Normal;
alpha = OPAQUE; alpha = OPAQUE;
} }
else if (state == INVUL_GetAlpha)
{
if (pAlpha != NULL) *pAlpha = MIN<fixed_t>(FRACUNIT/4 + alpha*3/4, FRACUNIT);
}
} }
// Cleric Weapon Base Class ------------------------------------------------- // Cleric Weapon Base Class -------------------------------------------------

View file

@ -105,7 +105,7 @@ public:
void GiveDefaultInventory (); void GiveDefaultInventory ();
const char *GetSoundClass (); const char *GetSoundClass ();
fixed_t GetJumpZ (); fixed_t GetJumpZ ();
void SpecialInvulnerabilityHandling (EInvulState state); void SpecialInvulnerabilityHandling (EInvulState state, fixed_t * pAlpha);
}; };
class AClericWeapon : public AWeapon class AClericWeapon : public AWeapon
@ -125,7 +125,7 @@ public:
const char *GetSoundClass (); const char *GetSoundClass ();
fixed_t GetJumpZ (); fixed_t GetJumpZ ();
bool DoHealingRadius (APlayerPawn *other); bool DoHealingRadius (APlayerPawn *other);
void SpecialInvulnerabilityHandling (EInvulState state); void SpecialInvulnerabilityHandling (EInvulState state, fixed_t * pAlpha);
}; };
class AMageWeapon : public AWeapon class AMageWeapon : public AWeapon

View file

@ -173,7 +173,7 @@ bool AMagePlayer::DoHealingRadius (APlayerPawn *other)
return false; return false;
} }
void AMagePlayer::SpecialInvulnerabilityHandling (EInvulState state) void AMagePlayer::SpecialInvulnerabilityHandling (EInvulState state, fixed_t * pAlpha)
{ {
if (state == INVUL_Start) if (state == INVUL_Start)
{ {
@ -183,6 +183,10 @@ void AMagePlayer::SpecialInvulnerabilityHandling (EInvulState state)
{ {
flags2 &= ~MF2_REFLECTIVE; flags2 &= ~MF2_REFLECTIVE;
} }
else if (state == INVUL_GetAlpha && pAlpha != NULL)
{
*pAlpha = FIXED_MAX;
}
} }
// Mage Weapon Base Class --------------------------------------------------- // Mage Weapon Base Class ---------------------------------------------------

View file

@ -132,7 +132,7 @@ bool AArtiDarkServant::Use (bool pickup)
void A_Summon (AActor *actor) void A_Summon (AActor *actor)
{ {
AMinotaur *mo; AMinotaurFriend *mo;
mo = Spawn<AMinotaurFriend> (actor->x, actor->y, actor->z); mo = Spawn<AMinotaurFriend> (actor->x, actor->y, actor->z);
if (mo) if (mo)

View file

@ -139,24 +139,12 @@ IMPLEMENT_ACTOR (AMinotaur, Heretic, 9, 0)
PROP_ActiveSound ("minotaur/active") PROP_ActiveSound ("minotaur/active")
END_DEFAULTS END_DEFAULTS
void AMinotaur::BeginPlay ()
{
Super::BeginPlay ();
StartTime = -1;
}
void AMinotaur::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << StartTime;
}
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 (!(flags & MF_FRIENDLY)) if (!IsKindOf(RUNTIME_CLASS(AMinotaurFriend)))
{ {
// 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;
@ -169,11 +157,8 @@ void AMinotaur::Tick ()
void AMinotaur::NoBlockingSet () void AMinotaur::NoBlockingSet ()
{ {
if (!(flags & MF_FRIENDLY)) P_DropItem (this, "ArtiSuperHealth", 0, 51);
{ P_DropItem (this, "PhoenixRodAmmo", 10, 84);
P_DropItem (this, "ArtiSuperHealth", 0, 51);
P_DropItem (this, "PhoenixRodAmmo", 10, 84);
}
} }
bool AMinotaur::Slam (AActor *thing) bool AMinotaur::Slam (AActor *thing)
@ -197,91 +182,6 @@ int AMinotaur::DoSpecialDamage (AActor *target, int damage)
return damage; return damage;
} }
bool AMinotaur::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->IsKindOf (RUNTIME_CLASS(AMinotaur))) &&
(link->tracer == tracer))
{
return false;
}
if (multiplayer && !deathmatch && link->player)
{
return false;
}
if (P_CheckSight (this, link))
{
return true;
}
}
return false;
}
void AMinotaur::Die (AActor *source, AActor *inflictor)
{
Super::Die (source, inflictor);
if (tracer && tracer->health > 0 && tracer->player)
{
// Search thinker list for minotaur
TThinkerIterator<AMinotaur> iterator;
AMinotaur *mo;
while ((mo = iterator.Next()) != NULL)
{
if (mo->health <= 0) continue;
// [RH] Minotaurs can't be morphed, so this isn't needed
//if (!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs
if (mo->flags&MF_CORPSE) continue;
if (mo->StartTime >= 0 && (level.maptime - StartTime) >= MAULATORTICS) continue;
if (mo->tracer != NULL && mo->tracer->player == tracer->player) break;
}
if (mo == NULL)
{
AInventory *power = tracer->FindInventory (RUNTIME_CLASS(APowerMinotaur));
if (power != NULL)
{
power->Destroy ();
}
}
}
}
bool AMinotaur::OkayToSwitchTarget (AActor *other)
{ // Minotaurs with masters never change their target until
// they've killed their current one.
if (tracer != NULL && tracer->health > 0)
return false;
if (other == tracer)
return false; // Do not target the master
return Super::OkayToSwitchTarget (other);
}
// Minotaur Friend ---------------------------------------------------------- // Minotaur Friend ----------------------------------------------------------
IMPLEMENT_STATELESS_ACTOR (AMinotaurFriend, Hexen, -1, 0) IMPLEMENT_STATELESS_ACTOR (AMinotaurFriend, Hexen, -1, 0)
@ -323,6 +223,99 @@ AT_GAME_SET (Minotaur)
} }
} }
void AMinotaurFriend::BeginPlay ()
{
Super::BeginPlay ();
StartTime = -1;
}
void AMinotaurFriend::Serialize (FArchive &arc)
{
Super::Serialize (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->IsKindOf (RUNTIME_CLASS(AMinotaur))) &&
(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);
if (tracer && tracer->health > 0 && tracer->player)
{
// Search thinker list for minotaur
TThinkerIterator<AMinotaurFriend> iterator;
AMinotaurFriend *mo;
while ((mo = iterator.Next()) != NULL)
{
if (mo->health <= 0) continue;
// [RH] Minotaurs can't be morphed, so this isn't needed
//if (!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs
if (mo->flags&MF_CORPSE) continue;
if (mo->StartTime >= 0 && (level.maptime - StartTime) >= MAULATORTICS) continue;
if (mo->tracer != NULL && mo->tracer->player == tracer->player) break;
}
if (mo == NULL)
{
AInventory *power = tracer->FindInventory (RUNTIME_CLASS(APowerMinotaur));
if (power != NULL)
{
power->Destroy ();
}
}
}
}
bool AMinotaurFriend::OkayToSwitchTarget (AActor *other)
{
if (other == tracer) return false; // Do not target the master
return Super::OkayToSwitchTarget (other);
}
void AMinotaurFriend::NoBlockingSet () void AMinotaurFriend::NoBlockingSet ()
{ {
// Do not drop anything // Do not drop anything
@ -358,6 +351,7 @@ IMPLEMENT_ACTOR (AMinotaurFX1, Raven, -1, 0)
PROP_DamageType (MOD_FIRE) PROP_DamageType (MOD_FIRE)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY) PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT) PROP_Flags2 (MF2_NOTELEPORT)
PROP_Flags4 (MF4_NOTARGETSWITCH)
PROP_RenderStyle (STYLE_Add) PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_MNTRFX1) PROP_SpawnState (S_MNTRFX1)
@ -531,7 +525,7 @@ void A_MinotaurAtk1 (AActor *actor)
void A_MinotaurDecide (AActor *actor) void A_MinotaurDecide (AActor *actor)
{ {
bool friendly = !!(actor->flags & MF_FRIENDLY); bool friendly = actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend));
angle_t angle; angle_t angle;
AActor *target; AActor *target;
int dist; int dist;
@ -630,6 +624,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));
if (!actor->target) if (!actor->target)
{ {
@ -639,7 +634,7 @@ void A_MinotaurAtk2 (AActor *actor)
if (actor->CheckMeleeRange()) if (actor->CheckMeleeRange())
{ {
int damage; int damage;
damage = pr_atk.HitDice ((actor->flags & MF_FRIENDLY) ? 3 : 5); damage = pr_atk.HitDice (friendly ? 3 : 5);
P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT); P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT);
P_TraceBleed (damage, actor->target, actor); P_TraceBleed (damage, actor->target, actor);
return; return;
@ -670,6 +665,7 @@ void A_MinotaurAtk3 (AActor *actor)
{ {
AActor *mo; AActor *mo;
player_t *player; player_t *player;
bool friendly = actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend));
if (!actor->target) if (!actor->target)
{ {
@ -680,7 +676,7 @@ void A_MinotaurAtk3 (AActor *actor)
{ {
int damage; int damage;
damage = pr_minotauratk3.HitDice ((actor->flags & MF_FRIENDLY) ? 3 : 5); damage = pr_minotauratk3.HitDice (friendly ? 3 : 5);
P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT); P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT);
P_TraceBleed (damage, actor->target, actor); P_TraceBleed (damage, actor->target, actor);
if ((player = actor->target->player) != NULL && if ((player = actor->target->player) != NULL &&
@ -787,7 +783,7 @@ void A_MinotaurFade2 (AActor *actor)
void A_MinotaurRoam (AActor *actor) void A_MinotaurRoam (AActor *actor)
{ {
AMinotaur *self = static_cast<AMinotaur *> (actor); AMinotaurFriend *self = static_cast<AMinotaurFriend *> (actor);
// In case pain caused him to skip his fade in. // In case pain caused him to skip his fade in.
actor->RenderStyle = STYLE_Normal; actor->RenderStyle = STYLE_Normal;
@ -829,14 +825,14 @@ void A_MinotaurRoam (AActor *actor)
void A_MinotaurLook (AActor *actor) void A_MinotaurLook (AActor *actor)
{ {
AMinotaur *self = static_cast<AMinotaur *> (actor);
if (!(self->flags & MF_FRIENDLY)) if (!actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)))
{ {
A_Look (actor); A_Look (actor);
return; return;
} }
AMinotaurFriend *self = static_cast<AMinotaurFriend *> (actor);
AActor *mo = NULL; AActor *mo = NULL;
player_t *player; player_t *player;
fixed_t dist; fixed_t dist;
@ -900,7 +896,13 @@ void A_MinotaurLook (AActor *actor)
void A_MinotaurChase (AActor *actor) void A_MinotaurChase (AActor *actor)
{ {
AMinotaur *self = static_cast<AMinotaur *> (actor); if (!actor->IsKindOf(RUNTIME_CLASS(AMinotaurFriend)))
{
A_Chase (actor);
return;
}
AMinotaurFriend *self = static_cast<AMinotaurFriend *> (actor);
// In case pain caused him to skip his fade in. // In case pain caused him to skip his fade in.
actor->RenderStyle = STYLE_Normal; actor->RenderStyle = STYLE_Normal;
@ -911,12 +913,6 @@ void A_MinotaurChase (AActor *actor)
return; return;
} }
if (!(self->flags & MF_FRIENDLY))
{
A_Chase (actor);
return;
}
if (pr_minotaurchase() < 30) if (pr_minotaurchase() < 30)
A_MinotaurLook (actor); // adjust to closest target A_MinotaurLook (actor); // adjust to closest target
@ -952,6 +948,7 @@ void A_MinotaurChase (AActor *actor)
if (!P_Move (actor)) if (!P_Move (actor))
{ {
P_NewChaseDir (actor); P_NewChaseDir (actor);
FaceMovementDirection (actor);
} }
// Active sound // Active sound

View file

@ -16,14 +16,8 @@ class AMinotaur : public AActor
public: public:
void NoBlockingSet (); void NoBlockingSet ();
int DoSpecialDamage (AActor *target, int damage); int DoSpecialDamage (AActor *target, int damage);
void BeginPlay ();
void Serialize (FArchive &arc);
public: public:
int StartTime;
bool IsOkayToAttack (AActor *target);
void Die (AActor *source, AActor *inflictor);
bool OkayToSwitchTarget (AActor *other);
bool Slam (AActor *); bool Slam (AActor *);
void Tick (); void Tick ();
}; };
@ -32,7 +26,14 @@ class AMinotaurFriend : public AMinotaur
{ {
DECLARE_STATELESS_ACTOR (AMinotaurFriend, AMinotaur) DECLARE_STATELESS_ACTOR (AMinotaurFriend, AMinotaur)
public: public:
int StartTime;
void NoBlockingSet (); void NoBlockingSet ();
bool IsOkayToAttack (AActor *target);
void Die (AActor *source, AActor *inflictor);
bool OkayToSwitchTarget (AActor *other);
void BeginPlay ();
void Serialize (FArchive &arc);
}; };
#endif //__RAVENSHARED_H__ #endif //__RAVENSHARED_H__

View file

@ -321,6 +321,22 @@ void APowerInvulnerable::EndEffect ()
} }
} }
//===========================================================================
//
// APowerInvuInvulnerable :: AlterWeaponSprite
//
//===========================================================================
void APowerInvulnerable::AlterWeaponSprite (vissprite_t *vis)
{
if (Owner->player->mo != NULL)
{
fixed_t wp_alpha;
Owner->player->mo->SpecialInvulnerabilityHandling (APlayerPawn::INVUL_GetAlpha, &wp_alpha);
if (wp_alpha != FIXED_MAX) vis->alpha = wp_alpha;
}
}
// Strength (aka Berserk) Powerup -------------------------------------------- // Strength (aka Berserk) Powerup --------------------------------------------
IMPLEMENT_STATELESS_ACTOR (APowerStrength, Any, -1, 0) IMPLEMENT_STATELESS_ACTOR (APowerStrength, Any, -1, 0)

View file

@ -59,6 +59,7 @@ protected:
void InitEffect (); void InitEffect ();
void DoEffect (); void DoEffect ();
void EndEffect (); void EndEffect ();
void AlterWeaponSprite (vissprite_t *vis);
}; };
class APowerStrength : public APowerup class APowerStrength : public APowerup

View file

@ -152,8 +152,8 @@ int FRandom::Random2 ()
int FRandom::Random2 (int mask) int FRandom::Random2 (int mask)
{ {
int t = (*this)(mask); int t = (*this)() & mask;
int u = (*this)(mask); int u = (*this)() & mask;
return t - u; return t - u;
} }

View file

@ -420,7 +420,7 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i
} }
} }
void P_DrawRailTrail (vec3_t start, vec3_t end) void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int color2, float maxdiff, bool silent)
{ {
float length; float length;
int steps, i; int steps, i;
@ -433,33 +433,44 @@ void P_DrawRailTrail (vec3_t start, vec3_t end)
if (length) if (length)
{ {
// The railgun's sound is special. It gets played from the
// point on the slug's trail that is closest to the hearing player.
AActor *mo = players[consoleplayer].camera;
vec3_t point;
float r;
float dirz;
length = 1 / length; length = 1 / length;
if (abs(mo->x - FLOAT2FIXED(start[0])) < 20 * FRACUNIT if (!silent)
&& (mo->y - FLOAT2FIXED(start[1])) < 20 * FRACUNIT)
{ // This player (probably) fired the railgun
S_Sound (mo, CHAN_WEAPON, "weapons/railgf", 1, ATTN_NORM);
}
else
{ {
// Only consider sound in 2D (for now, anyway) int sound;
r = ((start[1] - FIXED2FLOAT(mo->y)) * (-dir[1]) -
(start[0] - FIXED2FLOAT(mo->x)) * (dir[0])) * length * length;
dirz = dir[2]; // Allow other sounds than 'weapons/railgf'!
dir[2] = 0; if (!source->player) sound = source->AttackSound;
VectorMA (start, r, dir, point); else if (source->player->ReadyWeapon) sound = source->player->ReadyWeapon->AttackSound;
dir[2] = dirz; else sound = NULL;
if (!sound) sound=S_FindSound("weapons/railgf");
S_Sound (FLOAT2FIXED(point[0]), FLOAT2FIXED(point[1]), // The railgun's sound is special. It gets played from the
CHAN_WEAPON, "weapons/railgf", 1, ATTN_NORM); // point on the slug's trail that is closest to the hearing player.
AActor *mo = players[consoleplayer].camera;
vec3_t point;
float r;
float dirz;
if (abs(mo->x - FLOAT2FIXED(start[0])) < 20 * FRACUNIT
&& (mo->y - FLOAT2FIXED(start[1])) < 20 * FRACUNIT)
{ // This player (probably) fired the railgun
S_SoundID (mo, CHAN_WEAPON, sound, 1, ATTN_NORM);
}
else
{
// Only consider sound in 2D (for now, anyway)
r = ((start[1] - FIXED2FLOAT(mo->y)) * (-dir[1]) -
(start[0] - FIXED2FLOAT(mo->x)) * (dir[0])) * length * length;
dirz = dir[2];
dir[2] = 0;
VectorMA (start, r, dir, point);
dir[2] = dirz;
S_SoundID (FLOAT2FIXED(point[0]), FLOAT2FIXED(point[1]), mo->z,
CHAN_WEAPON, sound, 1, ATTN_NORM);
}
} }
} }
else else
@ -473,73 +484,113 @@ void P_DrawRailTrail (vec3_t start, vec3_t end)
VectorScale2 (extend, 3); VectorScale2 (extend, 3);
VectorScale (dir, 3, step); VectorScale (dir, 3, step);
VectorCopy (start, pos); if (color1 != -1)
deg = 270;
for (i = steps; i; i--)
{ {
particle_t *p = NewParticle (); color1 = color1==0? -1: ColorMatcher.Pick(RPART(color1), GPART(color1), BPART(color1));
vec3_t tempvec; VectorCopy (start, pos);
deg = 270;
if (!p) for (i = steps; i; i--)
return;
p->trans = 255;
p->ttl = 35;
p->fade = FADEFROMTTL(35);
p->size = 3;
RotatePointAroundVector (tempvec, dir, extend, deg);
p->velx = FLOAT2FIXED(tempvec[0])>>4;
p->vely = FLOAT2FIXED(tempvec[1])>>4;
p->velz = FLOAT2FIXED(tempvec[2])>>4;
VectorAdd (tempvec, pos, tempvec);
deg += 14;
if (deg >= 360)
deg -= 360;
p->x = FLOAT2FIXED(tempvec[0]);
p->y = FLOAT2FIXED(tempvec[1]);
p->z = FLOAT2FIXED(tempvec[2]);
VectorAdd (pos, step, pos);
{ {
int rand = M_Random(); particle_t *p = NewParticle ();
vec3_t tempvec;
if (rand < 155) if (!p)
p->color = rblue2; return;
else if (rand < 188)
p->color = rblue1; p->trans = 255;
else if (rand < 222) p->ttl = 35;
p->color = rblue3; p->fade = FADEFROMTTL(35);
p->size = 3;
RotatePointAroundVector (tempvec, dir, extend, deg);
p->velx = FLOAT2FIXED(tempvec[0])>>4;
p->vely = FLOAT2FIXED(tempvec[1])>>4;
p->velz = FLOAT2FIXED(tempvec[2])>>4;
VectorAdd (tempvec, pos, tempvec);
deg += 14;
if (deg >= 360)
deg -= 360;
p->x = FLOAT2FIXED(tempvec[0]);
p->y = FLOAT2FIXED(tempvec[1]);
p->z = FLOAT2FIXED(tempvec[2]);
VectorAdd (pos, step, pos);
if (color1==-1)
{
int rand = M_Random();
if (rand < 155)
p->color = rblue2;
else if (rand < 188)
p->color = rblue1;
else if (rand < 222)
p->color = rblue3;
else
p->color = rblue4;
}
else else
p->color = rblue4; {
p->color = color1;
}
} }
} }
VectorCopy (start, pos); if (color2 != -1)
for (i = steps; i; i--)
{ {
particle_t *p = JitterParticle (33); color2 = color2==0? -1: ColorMatcher.Pick(RPART(color2), GPART(color2), BPART(color2));
vec3_t diff;
VectorSet (diff, 0, 0, 0);
if (!p) VectorCopy (start, pos);
return; for (i = steps; i; i--)
p->size = 2;
p->x = FLOAT2FIXED(pos[0]);
p->y = FLOAT2FIXED(pos[1]);
p->z = FLOAT2FIXED(pos[2]);
p->accz -= FRACUNIT/4096;
VectorAdd (pos, step, pos);
{ {
int rand = M_Random(); particle_t *p = JitterParticle (33);
if (rand < 85) if (!p)
p->color = grey4; return;
else if (rand < 170)
p->color = grey2; if (maxdiff > 0)
{
int rnd = M_Random ();
if (rnd & 1)
diff[0] = clamp<float> (diff[0] + ((rnd & 8) ? 1 : -1), -maxdiff, maxdiff);
if (rnd & 2)
diff[1] = clamp<float> (diff[1] + ((rnd & 16) ? 1 : -1), -maxdiff, maxdiff);
if (rnd & 4)
diff[2] = clamp<float> (diff[2] + ((rnd & 32) ? 1 : -1), -maxdiff, maxdiff);
}
vec3_t postmp;
VectorCopy (pos, postmp);
VectorAdd (postmp, diff, postmp);
p->size = 2;
p->x = FLOAT2FIXED(postmp[0]);
p->y = FLOAT2FIXED(postmp[1]);
p->z = FLOAT2FIXED(postmp[2]);
if (color1 != -1)
p->accz -= FRACUNIT/4096;
VectorAdd (pos, step, pos);
if (color2==-1)
{
{
int rand = M_Random();
if (rand < 85)
p->color = grey4;
else if (rand < 170)
p->color = grey2;
else
p->color = grey1;
}
p->color = white;
}
else else
p->color = grey1; {
p->color = color2;
}
} }
p->color = white;
} }
} }

View file

@ -58,7 +58,7 @@ void P_RunEffects (void);
void P_RunEffect (AActor *actor, int effects); void P_RunEffect (AActor *actor, int effects);
void P_DrawRailTrail (vec3_t start, vec3_t end); void P_DrawRailTrail (AActor * source, vec3_t start, vec3_t end, int color1, int color2, float maxdiff = 0, bool silent = false);
void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind); void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind);
void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind); void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind);
void P_DisconnectEffect (AActor *actor); void P_DisconnectEffect (AActor *actor);

View file

@ -303,7 +303,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target,
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
void P_TraceBleed (int damage, AActor *target); // random direction version void P_TraceBleed (int damage, AActor *target); // random direction version
void P_RailAttack (AActor *source, int damage, int offset); // [RH] Shoot a railgun void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false); // [RH] Shoot a railgun
bool P_HitFloor (AActor *thing); bool P_HitFloor (AActor *thing);
bool P_HitWater (AActor *thing, sector_t *sec); bool P_HitWater (AActor *thing, sector_t *sec);
bool P_CheckMissileSpawn (AActor *missile); bool P_CheckMissileSpawn (AActor *missile);

View file

@ -2961,7 +2961,7 @@ static bool ProcessRailHit (FTraceResults &res)
return true; return true;
} }
void P_RailAttack (AActor *source, int damage, int offset) void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent)
{ {
fixed_t vx, vy, vz; fixed_t vx, vy, vz;
angle_t angle, pitch; angle_t angle, pitch;
@ -3064,7 +3064,7 @@ void P_RailAttack (AActor *source, int damage, int offset)
} }
VectorFixedSet (end, trace.X, trace.Y, trace.Z); VectorFixedSet (end, trace.X, trace.Y, trace.Z);
P_DrawRailTrail (start, end); P_DrawRailTrail (source, start, end, color1, color2, maxdiff, silent);
} }
// //

View file

@ -449,8 +449,9 @@ bool APlayerPawn::DoHealingRadius (APlayerPawn *other)
return false; return false;
} }
void APlayerPawn::SpecialInvulnerabilityHandling (EInvulState setting) void APlayerPawn::SpecialInvulnerabilityHandling (EInvulState setting, fixed_t * pAlpha)
{ {
if (setting == INVUL_GetAlpha && pAlpha!=NULL) *pAlpha=FIXED_MAX; // indicates no change
} }
/* /*

View file

@ -1668,8 +1668,8 @@ static int ProcessStates(FActorInfo * actor, AActor * defaults, Baggage &bag)
else else
{ {
int c = V_GetColor (NULL, sc_String); int c = V_GetColor (NULL, sc_String);
// 0 needs to be the default so we have to add 1 here! // 0 needs to be the default so we have to mark the color.
v = 1 + ColorMatcher.Pick (RPART (c), GPART (c), BPART (c)); v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
} }
break; break;

View file

@ -874,14 +874,7 @@ void A_RailAttack (AActor * self)
if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo
} }
// Need to keep the default colors P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, Silent);
if (Color1==0) Color1 = ColorMatcher.Pick (0, 0, 255);
else if (Color1>0) Color1--;
if (Color2==0) Color2 = ColorMatcher.Pick (255, 255, 255);
else if (Color2>0) Color2--;
P_RailAttack (self, Damage, Spawnofs_XY/*, Color1, Color2, MaxDiff, Silent*/);
} }
//========================================================================== //==========================================================================
@ -938,14 +931,7 @@ void A_CustomRailgun (AActor *actor)
} }
} }
// Need to keep the default colors P_RailAttack (actor, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, Silent);
if (Color1==0) Color1 = ColorMatcher.Pick (0, 0, 255);
else if (Color1>0) Color1--;
if (Color2==0) Color2 = ColorMatcher.Pick (255, 255, 255);
else if (Color2>0) Color2--;
P_RailAttack (actor, Damage, Spawnofs_XY/*, Color1, Color2, MaxDiff, Silent*/);
} }
//=========================================================================== //===========================================================================