ZDoom / gzdoom

GZDoom is a feature centric port for all Doom engine games, based on ZDoom, adding an OpenGL renderer and powerful scripting capabilities
http://zdoom.org
GNU General Public License v3.0
2.56k stars 552 forks source link

[BUG] GetSpriteTexture() pulls garbage data when iterating over states whose sprites aren't currently loaded #2697

Open jekyllgrim opened 3 months ago

jekyllgrim commented 3 months ago

GZDoom version

g4.13pre-122-g76c8b6da5

Which game are you running with GZDoom?

Doom

What Operating System are you using?

Windows 10

Please describe your specific OS version

Windows 10 Pro

Relevant hardware info

No response

Have you checked that no other similar issue already exists?

A clear and concise description of what the bug is.

When trying to iterate over states using nextstate in a loop, calling GetSpriteTexture() seems to occasionaly obtain garbage data. This only happens if you're calling this on a static state pointer obtained through GetDefaultByType(), not if you're doing this on a pointer to an actual instance of an actor.

Specifically I noticed this by trying to do this with KeyGreen (a Heretic key) while playing Doom. When trying to iterate over its Spawn state sequence, GetSpriteTexture obtains TNT1A0 as expected from its spawnstate (since textures for it don't exist), but if you continue iterating through the following states, it keeps obtaining PLYC (the player crouch sprites for me).

Steps to reproduce the behaviour.

Explain how to reproduce

  1. Load Doom with the attached zip archive Nextstate sprite bug.zip
  2. In the console type netevent TestActorState:KeyGreen (you can also test other classes by typing their name after the colon). In the console you'll see an output listing state poiners and their sprite textures.
  3. Instead of returning TNT1A0 for all states (or perhaps AKYY), the console will output TNT1A0 for the first state, and PLYC for the rest.

Your configuration

https://gist.github.com/jekyllgrim/cf2e87fc33e40388fa7d01e7965a321f

Provide a Log

https://gist.github.com/jekyllgrim/902bc1e753727a93df4512ae4d343158

jekyllgrim commented 3 months ago

To add to this: there is a workaround solution for this. Apparently, <State pointer>.sprite, despite being defined as int, can be cast to SpriteID and then cast to a string.

So technically this issue can be "fixed" with:

// 'st' is assumed to be a previously obtained state pointer
TextureID sprtTex = st.GetSpriteTexture(0);
String sprtTexName = TexMan.GetName(sprtTex);
if (sprtTex.Isvalid() && st.sprt != 0 && sprtTexName.IndexOf(""..SpriteID(st.sprite)) >= 0)
{
  // sprtTex is valid
}

But of course it's only a workaround.

This also kinda reveals another issue: sprite in the State struct is for some reason an int, even though it seems like it should be a SpriteID.