- Merged SetState and SetStateNF into a single function.

- Added new sprite #### and frame character # to specify the behavior of sprite ---- on a
  per-sprite and per-frame basis respectively.

SVN r2291 (trunk)
This commit is contained in:
Randy Heit 2010-04-19 02:46:50 +00:00
parent 768bdabbb6
commit 178587fff2
15 changed files with 85 additions and 160 deletions

View File

@ -912,8 +912,7 @@ public:
void SetOrigin (fixed_t x, fixed_t y, fixed_t z);
bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate);
bool SetState (FState *newstate);
bool SetStateNF (FState *newstate);
bool SetState (FState *newstate, bool nofunction=false);
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
bool isFast();
void SetIdle();

View File

@ -1354,8 +1354,8 @@ static int PatchFrame (int frameNum)
}
info->Tics = tics;
info->Misc1 = misc1;
info->Frame = (frame & 0x3f) |
(frame & 0x8000 ? SF_FULLBRIGHT : 0);
info->Frame = frame & 0x3f;
info->Fullbright = frame & 0x8000 ? true : false;
}
return result;

View File

@ -73,7 +73,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FogMove)
if (self->args[3]-- <= 0)
{
self->SetStateNF (self->FindState(NAME_Death));
self->SetState (self->FindState(NAME_Death), true);
return;
}

View File

@ -107,9 +107,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise)
{ // Reached it's target height
actor->args[0] = 1;
if (actor->args[1])
actor->SetStateNF (actor->FindState ("BloodThrustInit2"));
actor->SetState (actor->FindState ("BloodThrustInit2"), true);
else
actor->SetStateNF (actor->FindState ("ThrustInit2"));
actor->SetState (actor->FindState ("ThrustInit2"), true);
}
// Lose the dirt clump
@ -131,9 +131,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower)
{
self->args[0] = 0;
if (self->args[1])
self->SetStateNF (self->FindState ("BloodThrustInit1"));
self->SetState (self->FindState ("BloodThrustInit1"), true);
else
self->SetStateNF (self->FindState ("ThrustInit1"));
self->SetState (self->FindState ("ThrustInit1"), true);
}
}

View File

@ -192,7 +192,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
&& pr_minotaurdecide() < 150)
{ // Charge attack
// Don't call the state function right away
self->SetStateNF (self->FindState ("Charge"));
self->SetState (self->FindState ("Charge"), true);
self->flags |= MF_SKULLFLY;
if (!friendly)
{ // Heretic's Minotaur is invulnerable during charge attack
@ -524,11 +524,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurLook)
if (self->target)
{
self->SetStateNF (self->SeeState);
self->SetState (self->SeeState, true);
}
else
{
self->SetStateNF (self->FindState ("Roam"));
self->SetState (self->FindState ("Roam"), true);
}
}

View File

@ -113,6 +113,10 @@ void FActorInfo::StaticInit ()
// Sprite 1 is always ----
memcpy (temp.name, "----", 5);
sprites.Push (temp);
// Sprite 2 is always ####
memcpy (temp.name, "####", 5);
sprites.Push (temp);
}
Printf ("LoadActors: Load actor definitions.\n");

View File

@ -44,20 +44,28 @@
#include "dobject.h"
#include "doomdef.h"
const BYTE SF_FULLBRIGHT = 0x40;
struct Baggage;
class FScanner;
struct FActorInfo;
class FArchive;
// Sprites that are fixed in position because they can have special meanings.
enum
{
SPR_TNT1, // The empty sprite
SPR_FIXED, // Do not change sprite or frame
SPR_NOCHANGE, // Do not change sprite (frame change is okay)
};
struct FState
{
WORD sprite;
SWORD Tics;
long Misc1; // Was changed to SBYTE, reverted to long for MBF compat
long Misc2; // Was changed to BYTE, reverted to long for MBF compat
BYTE Frame;
int Misc1; // Was changed to SBYTE, reverted to long for MBF compat
int Misc2; // Was changed to BYTE, reverted to long for MBF compat
BYTE Frame:6;
BYTE Fullbright:1; // State is fullbright
BYTE SameFrame:1; // Ignore Frame (except when spawning actor)
BYTE DefineFlags; // Unused byte so let's use it during state creation.
short Light;
FState *NextState;
@ -66,11 +74,15 @@ struct FState
inline int GetFrame() const
{
return Frame & ~(SF_FULLBRIGHT);
return Frame;
}
inline bool GetSameFrame() const
{
return SameFrame;
}
inline int GetFullbright() const
{
return Frame & SF_FULLBRIGHT ? 0x10 /*RF_FULLBRIGHT*/ : 0;
return Fullbright ? 0x10 /*RF_FULLBRIGHT*/ : 0;
}
inline int GetTics() const
{
@ -90,7 +102,7 @@ struct FState
}
inline void SetFrame(BYTE frame)
{
Frame = (Frame & SF_FULLBRIGHT) | (frame-'A');
Frame = frame - 'A';
}
void SetAction(PSymbolActionFunction *func, bool setdefaultparams = true)
{

View File

@ -528,7 +528,7 @@ int AActor::GetTics(FState * newstate)
//
//==========================================================================
bool AActor::SetState (FState *newstate)
bool AActor::SetState (FState *newstate, bool nofunction)
{
if (debugfile && player && (player->cheats & CF_PREDICTING))
fprintf (debugfile, "for pl %td: SetState while predicting!\n", player-players);
@ -554,37 +554,41 @@ bool AActor::SetState (FState *newstate)
tics = GetTics(newstate);
renderflags = (renderflags & ~RF_FULLBRIGHT) | newstate->GetFullbright();
newsprite = newstate->sprite;
if (newsprite != 1)
{
// Sprite 1 is ----, which means "do not change the sprite"
frame = newstate->GetFrame();
if (!(flags4 & MF4_NOSKIN) && newsprite == SpawnState->sprite)
{ // [RH] If the new sprite is the same as the original sprite, and
// this actor is attached to a player, use the player's skin's
// sprite. If a player is not attached, do not change the sprite
// unless it is different from the previous state's sprite; a
// player may have been attached, died, and respawned elsewhere,
// and we do not want to lose the skin on the body. If it wasn't
// for Dehacked, I would move sprite changing out of the states
// altogether, since actors rarely change their sprites after
// spawning.
if (player != NULL)
{
sprite = skins[player->userinfo.skin].sprite;
if (newsprite != SPR_FIXED)
{ // okay to change sprite and/or frame
if (!newstate->GetSameFrame())
{ // okay to change frame
frame = newstate->GetFrame();
}
if (newsprite != SPR_NOCHANGE)
{ // okay to change sprite
if (!(flags4 & MF4_NOSKIN) && newsprite == SpawnState->sprite)
{ // [RH] If the new sprite is the same as the original sprite, and
// this actor is attached to a player, use the player's skin's
// sprite. If a player is not attached, do not change the sprite
// unless it is different from the previous state's sprite; a
// player may have been attached, died, and respawned elsewhere,
// and we do not want to lose the skin on the body. If it wasn't
// for Dehacked, I would move sprite changing out of the states
// altogether, since actors rarely change their sprites after
// spawning.
if (player != NULL)
{
sprite = skins[player->userinfo.skin].sprite;
}
else if (newsprite != prevsprite)
{
sprite = newsprite;
}
}
else if (newsprite != prevsprite)
else
{
sprite = newsprite;
}
}
else
{
sprite = newsprite;
}
}
if (newstate->CallAction(this, this))
if (!nofunction && newstate->CallAction(this, this))
{
// Check whether the called action function resulted in destroying the actor
if (ObjectFlags & OF_EuthanizeMe)
@ -600,69 +604,6 @@ bool AActor::SetState (FState *newstate)
return true;
}
//----------------------------------------------------------------------------
//
// FUNC AActor::SetStateNF
//
// Same as SetState, but does not call the state function.
//
//----------------------------------------------------------------------------
bool AActor::SetStateNF (FState *newstate)
{
do
{
if (newstate == NULL)
{
state = NULL;
Destroy ();
return false;
}
int prevsprite, newsprite;
if (state != NULL)
{
prevsprite = state->sprite;
}
else
{
prevsprite = -1;
}
state = newstate;
tics = GetTics(newstate);
renderflags = (renderflags & ~RF_FULLBRIGHT) | newstate->GetFullbright();
newsprite = newstate->sprite;
if (newsprite != 1)
{
// Sprite 1 is ----, which means "do not change the sprite"
frame = newstate->GetFrame();
if (!(flags4 & MF4_NOSKIN) && newsprite == SpawnState->sprite)
{
if (player != NULL && gameinfo.gametype != GAME_Hexen)
{
sprite = skins[player->userinfo.skin].sprite;
}
else if (newsprite != prevsprite)
{
sprite = newsprite;
}
}
else
{
sprite = newsprite;
}
}
newstate = newstate->GetNextState();
} while (tics == 0);
if (screen != NULL)
{
screen->StateChanged(this);
}
return true;
}
//============================================================================
//
// AActor :: AddInventory

View File

@ -61,13 +61,12 @@ static FRandom pr_gunshot ("GunShot");
//
//---------------------------------------------------------------------------
void P_SetPsprite (player_t *player, int position, FState *state)
void P_SetPsprite (player_t *player, int position, FState *state, bool nofunction)
{
pspdef_t *psp;
if (position == ps_weapon)
{
// A_WeaponReady will re-set these as needed
if (position == ps_weapon && !nofunction)
{ // A_WeaponReady will re-set these as needed
player->cheats &= ~(CF_WEAPONREADY | CF_WEAPONREADYALT | CF_WEAPONBOBBING | CF_WEAPONSWITCHOK);
}
@ -97,7 +96,7 @@ void P_SetPsprite (player_t *player, int position, FState *state)
psp->sy = state->GetMisc2()<<FRACBITS;
}
if (player->mo != NULL)
if (!nofunction && player->mo != NULL)
{
if (state->CallAction(player->mo, player->ReadyWeapon))
{
@ -112,40 +111,6 @@ void P_SetPsprite (player_t *player, int position, FState *state)
} while (!psp->tics); // An initial state of 0 could cycle through.
}
//---------------------------------------------------------------------------
//
// PROC P_SetPspriteNF
//
// Identical to P_SetPsprite, without calling the action function
//---------------------------------------------------------------------------
void P_SetPspriteNF (player_t *player, int position, FState *state)
{
pspdef_t *psp;
psp = &player->psprites[position];
do
{
if (state == NULL)
{ // Object removed itself.
psp->state = NULL;
break;
}
psp->state = state;
psp->tics = state->GetTics(); // could be 0
if (state->GetMisc1())
{ // Set coordinates.
psp->sx = state->GetMisc1()<<FRACBITS;
}
if (state->GetMisc2())
{
psp->sy = state->GetMisc2()<<FRACBITS;
}
state = psp->state->GetNextState();
} while (!psp->tics); // An initial state of 0 could cycle through.
}
//---------------------------------------------------------------------------
//
// PROC P_BringUpWeapon

View File

@ -79,8 +79,7 @@ class player_t;
class AActor;
struct FState;
void P_SetPsprite (player_t *player, int position, FState *state);
void P_SetPspriteNF (player_t *player, int position, FState *state);
void P_SetPsprite (player_t *player, int position, FState *state, bool nofunction=false);
void P_CalcSwing (player_t *player);
void P_BringUpWeapon (player_t *player);
void P_FireWeapon (player_t *player);

View File

@ -824,23 +824,28 @@ bool FStateDefinitions::SetLoop()
bool FStateDefinitions::AddStates(FState *state, const char *framechars)
{
bool error = false;
int frame = 0;
while (*framechars)
{
int frame;
if (*framechars == '^')
frame = '\\'-'A';
bool noframe = false;
if (*framechars == '#')
noframe = true;
else if (*framechars == '^')
frame = '\\' - 'A';
else
frame = ((*framechars)&223)-'A';
frame = (*framechars & 223) - 'A';
framechars++;
if (frame<0 || frame>28)
if (frame < 0 || frame > 28)
{
frame = 0;
error = true;
}
state->Frame=(state->Frame&(SF_FULLBRIGHT))|frame;
state->Frame = frame;
state->SameFrame = noframe;
StateArray.Push(*state);
}
laststate = &StateArray[StateArray.Size() - 1];

View File

@ -1054,7 +1054,7 @@ void R_SetupFrame (AActor *actor)
((player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) &&
(camera->RenderStyle.BlendOp != STYLEOP_None) &&
!(camera->renderflags & RF_INVISIBLE) &&
camera->sprite != 0) // Sprite 0 is always TNT1
camera->sprite != SPR_TNT1)
{
// [RH] Use chasecam view
P_AimCamera (camera, iview->nviewx, iview->nviewy, iview->nviewz, viewsector);

View File

@ -684,7 +684,7 @@ static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states, FScanne
{
sc.ScriptError ("* must come after a frame");
}
state.Frame |= SF_FULLBRIGHT;
state.Fullbright = true;
}
else if (*token < 'A' || *token > ']')
{

View File

@ -244,7 +244,7 @@ do_stop:
{
if (sc.Compare("BRIGHT"))
{
state.Frame |= SF_FULLBRIGHT;
state.Fullbright = true;
continue;
}
if (sc.Compare("OFFSET"))

View File

@ -282,7 +282,7 @@ ACTOR Actor native //: Thinker
Stop
GenericFreezeDeath:
// Generic freeze death frames. Woo!
"----" A 5 A_GenericFreezeDeath
"####" "#" 5 A_GenericFreezeDeath
"----" A 1 A_FreezeDeathChunks
Wait
GenericCrush: