Classes:PSprite
The PSprite class is a dedicated class designed to process and handle states and sprite animations for classes based on StateProvider—namely, Weapon and CustomInventory. While the states and animations are defined in the Weapon/CustomInventory directly, they're displayed by a PSprite. A new instance of a PSprite is created for each new sprite layer.
PSprites are stored in the psprites linked list in the PlayerInfo struct.
PSprites have their own coordinate system compared to the HUD and are drawn underneath it. Unlike HUD elements, world lighting can directly affect PSprites. Players support multiple layers of PSprites denoted by their id. They are also ordered by id meaning layers with greater ids are drawn on top of other layers. For this reason what id you give you a PSprite should be considered carefully when adding overlays. PSprites can be created via PlayerInfo's GetPSprite(), SetPSprite(), and SetSafeFlash() functions. PSprites with an id of 0 are invalid and cannot be created.
Certain rules are preserved when players are ticking their PSprites:
- If the Caller is null, the PSprite is destroyed.
- If the Caller is an Inventory item and its owner is not the same as the PSprite's owner, the PSprite is destroyed.
- If the Caller is a Weapon and it's not the PSprite owner's current ReadyWeapon, the PSprite is destroyed.
These rules can be changed by creating a custom player class that overrides TickPSprites().
Functions that are intended to be called from a PSprite (e.g. a function in a weapon's state) should have the action
keyword. This allows the PSprite to properly set up the self, invoker, and stateInfo parameters to pass to it.
There are a few default layer ids that should be noted:
- PSP_STRIFEHANDS (-1) - Used for displaying the player's hand in Strife. This has special caller and state functionality and should be avoided entirely.
- PSP_WEAPON (1) - Displays the player's current ReadyWeapon.
- PSP_FLASH (1000) - Displays the muzzle flash when firing a weapon.
- PSP_TARGETCENTER (0x7FFFFFFF - 2) - Displays the center of the targeting powerup reticle from Strife. This should be avoided unless using from the appropriate powerup.
- PSP_TARGETLEFT (0x7FFFFFFF - 1) - Displays the left-hand side of the targeting powerup reticle from Strife. This should be avoided unless using from the appropriate powerup.
- PSP_TARGETRIGHT (0x7FFFFFFF) - Displays the right-hand side of the targeting powerup reticle from Strife. This should be avoided unless using from the appropriate powerup.
Fields
Readonly
- readonly State CurState
- State data for the PSprite's current state.
- readonly PSprite Next
- A pointer to the next PSprite in the linked list. The head of the list is stored the owner's PlayerInfo, reachable with
player.psprites
.
- readonly PlayerInfo Owner
- The PlayerInfo struct of the player that owns this PSprite.
- readonly int ID
- The ID given to the PSprite on creation.
Modifiable
- Actor Caller
- The actor that owns the state this PSprite is using.
- SpriteID Sprite
- The current sprite being displayed by the PSprite. This is the same as GetSpriteIndex("SPRT").
- int Frame
- The current frame of the sprite being displayed by the PSprite. In this case A = 0, B = 1, etc.
- bool processPending
- If set to false, the PSprite will not call its [[|Tick|Tick()]]. Usually only relevant when first creating a PSprite so it does not tick on the same frame.
- double x
- The current x offset from the center of the screen. Positive values shift right.
- double y
- The current y offset from the center of the screen. Positive values shift down.
- double oldx
- The x offset on the previous frame. Used for interpolation.
- double oldy
- The y offset on the previous frame. Used for interpolation.
- Vector2 baseScale
- The base scalar to apply to the PSprite before any other transformations. Used by the Weapon.WeaponScaleX/Weapon.WeaponScaleY properties.
- Vector2 pivot
- The pivot point to transform the PSprite about. This is relative to the PSprite's alignment. If
bPivotPercent
. is set to true, this acts instead like a scalar of the sprite's texture size.
- Vector2 scale
- The x and y scalars. This scales about the PSprite's pivot point.
- double rotation
- The angle the PSprite it rotated by. This rotates it around its pivot point. Positive values rotate counter-clockwise.
- int HAlign
- The horizontal alignment of the PSprite.
- PSPA_LEFT
- Align to the leftmost part of the sprite's texture.
- PSPA_CENTER
- Align to the sprite texture's horizontal center.
- PSPA_RIGHT
- Align to the rightmost part of the sprite's texture.
- int VAlign
- The vertical alignment of the PSprite.
- PSPA_TOP
- Align to the top of the sprite's texture.
- PSPA_CENTER
- Align to the sprite texture's vertical center.
- PSPA_BOTTOM
- Align to the bottom of the sprite's texture.
- Vector2 Coord0
- The offset for the top left coordinate of the sprite's texture.
- Vector2 Coord1
- The offset for the bottom left coordinate of the sprite's texture.
- Vector2 Coord2
- The offset for the top right coordinate of the sprite's texture.
- Vector2 Coord3
- The offset for the bottom right coordinate of the sprite's texture.
- double alpha
- The current transparency. The PSprite must have a renderstyle set that can use it.
- bool firstTic
- Denotes that it's the first tic of the PSprite. This is used to disable interpolation.
- bool InterpolateTic
- All transformations of this PSprite should be interpolated for this tic only.
- int Tics
- The number of tics remaining in the current state.
- uint Translation
- The color translation to apply to the sprite.
- bool bAddWeapon
- Apply the weapon layer's offsets to this PSprite.
- bool bAddBob
- Weapon bobbing offsets apply to this PSprite.
- bool bPowDouble
- Allow the duration of all states to be cut in half if the owner has the powerup.
- bool bCVarFast
- Allow the sv_fastweapons cheat to apply to this PSprite.
- bool bFlip
- The sprite is mirrored across the y axis.
- bool bMirror
- The offsets for the PSprite are mirrored across the y axis.
- bool bPlayerTranslated
- Applies the same translation rules as the player to the PSprite.
- bool bPivotPercent
- If true, the
pivot
field is read as a scale of the sprite's texture size instead of a coordinate offset.
- bool bInterpolate
- If true, all actions are interpolated (offsetting, rotating, scaling).
Methods
Non-static
- void SetState(State newstate, bool pending = false)
- Same as SetState but for the PSprite. The same can be achieved with player.SetPSprite().
- void Tick()
- PSprite's Tick.
- void ResetInterpolation()
PlayerInfo PSprite methods
The following methods are called on a PlayerInfo pointer to set up and interact with PSprites. These methods have to be called on a PlayerInfo pointer. For example, when doing it from a PlayerPawn actor, the prefix for them would be self.player
(or just player
). Same for calling from a Weapon state or a weapon action function, (since in the context of weapon states self
is the player pawn owner, while invoker
is the weapon itself).
- PSprite FindPSprite(int id)
- Finds a PSprite instance on the layer
id
and returns a pointer to it. If it doesn't exists, returns null. This allows modifying a PSprite instance directly, much like various A_Overlay* functions do, and also allows checking that a certain PSprite layer already exists.
- PSprite GetPSprite(int id)
- Same as
FindPSprite
, but if the PSprite doesn't exist, this function will create it and return a pointer to it.
- void SetPSprite(int id, State stat, bool pending = false)
- Sets the PSprite on the specified layer to the specified state (if the layer doesn't exist, it'll be created first). Basically, combines
GetPSprite
and SetState. - Generally, this is the same as A_Overlay, with one small difference: if
A_Overlay
is called on a layer that already exists, it'll reset its offsets before moving to the new state, whereasSetPSprite
won't. The latter may be useful when there's a need to move a PSprite layer to a different state while retaining previously set offsets. In addition, this function can be called from anywhere, whereas A_Overlay can only be called from a weapon state or weapon action function.
- void SetSafeFlash(Weapon weap, State flashstate, int index)
- Verifies that
flashstate + index
exists in the state table of the passed weapon (or a weapon class it inherits from) before setting the PSP_FLASH layer. This is mainly useful for preventing crashes if an offset state isn't guaranteed to exist i.e. a child class overrides it.
ZScript definition
Note: The ZScript definition below is for reference and may be different in the current version of GZDoom.The most up-to-date version of this code can be found on GZDoom GitHub. |
class PSprite : Object native play
{
enum PSPLayers
{
STRIFEHANDS = -1,
WEAPON = 1,
FLASH = 1000,
TARGETCENTER = 0x7fffffff - 2,
TARGETLEFT,
TARGETRIGHT,
};
native readonly State CurState;
native Actor Caller;
native readonly PSprite Next;
native readonly PlayerInfo Owner;
native SpriteID Sprite;
native int Frame;
//native readonly int RenderStyle; had to be blocked because the internal representation was not ok. Renderstyle is still pending a proper solution.
native readonly int ID;
native Bool processPending;
native double x;
native double y;
native double oldx;
native double oldy;
native Vector2 baseScale;
native Vector2 pivot;
native Vector2 scale;
native double rotation;
native int HAlign, VAlign;
native Vector2 Coord0; // [MC] Not the actual coordinates. Just the offsets by A_OverlayVertexOffset.
native Vector2 Coord1;
native Vector2 Coord2;
native Vector2 Coord3;
native double alpha;
native Bool firstTic;
native bool InterpolateTic;
native int Tics;
native TranslationID Translation;
native bool bAddWeapon;
native bool bAddBob;
native bool bPowDouble;
native bool bCVarFast;
native bool bFlip;
native bool bMirror;
native bool bPlayerTranslated;
native bool bPivotPercent;
native bool bInterpolate;
native void SetState(State newstate, bool pending = false);
//------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------
void Tick()
{
if (processPending)
{
if (Caller)
{
Caller.PSpriteTick(self);
if (bDestroyed)
return;
}
if (processPending)
{
// drop tic count and possibly change state
if (Tics != -1) // a -1 tic count never changes
{
Tics--;
// [BC] Apply double firing speed.
if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--;
if (!Tics && Caller != null) SetState(CurState.NextState);
}
}
}
}
void ResetInterpolation()
{
oldx = x;
oldy = y;
}
}