(I tend to be quite good with boards and all, or so they said, but doubt got the best of me. I'm very sorry if this is the wrong forum.)
So I got my game, Unkillable. There's a big red button and an SE sprite that fires a gun when the button is pushed. It's in a small niche (?) in the wall, together with three shootable objects in a line. Pushing the button a couple times causes these objects to be hit and destroyed. Standing in the same line, you should get hit yourself when pressing the button a fourth time. But it doesn't work: the shot ends up at the far wall!
And, in the likely case that doesn't inform enough, here's an annotated excerpt of console.txt:
Welcome to Unkillable. Enjoy the ride.
//The killer is sprite #73, a hidden sprite that's set up to fire a gun in it's direction when triggered.
//Angle of the shot is only peppered if aim > 0, so this sprite will always fire straight forward, unlike the player.
//The first three shots are caught by a set of breakable ornaments...
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = -1, hitsprite = 2, hitsect = 31, hitxyz(30720,32896,5120). Hittype is 2.
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = -1, hitsprite = 3, hitsect = 31, hitxyz(30976,32896,5120). Hittype is 2.
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = -1, hitsprite = 4, hitsect = 31, hitxyz(31232,32896,5120). Hittype is 2.
//Now that the ornaments are gone, the player is standing right in the gun's line of fire.
//We push the button on the wall to trigger the sprite once more...
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = 73, hitsprite = -1, hitsect = 12, hitxyz(35328,32896,5120). Hittype is 4.
//...and it shoots into the wall behind us, which incidentally has the same index. We try some more to be sure...
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = 73, hitsprite = -1, hitsect = 12, hitxyz(35328,32896,5120). Hittype is 4.
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
DoAttack: hitwall = 73, hitsprite = -1, hitsect = 12, hitxyz(35328,32896,5120). Hittype is 4.
DoAttack: killer is 73, aim 0. Pos = (28417,32896,5120), ang 0.
//If this had worked, hittype would've been 3, hitx somewhere between 28417 and 35328 and the player hurt.
//Here's what it looks like when the player shoots that same wall...
DoAttack: killer is -2, aim 10. Pos = (34281,32503,2048), ang 95.
DoAttack: hitwall = 73, hitsprite = -1, hitsect = 12, hitxyz(35327,32852,1916). Hittype is 4.
//Note: Killer -2 is always the player.
Kyoufu Kawa at
...hello? Anybody in here? :(
Awesoken at
Please realize that there are only a handful of people (probably not more than 5) on these forums who are familiar enough with the Build code to answer your question. Most people are merely beta-tester/lurkers/leeches : P Anyway, it's great to see someone new working with the Build code.
I'm not sure what your bug is, but I can point out things that look suspicious. I assume you're using hitscan(). I'm not quite sure what you mean by "hittype". Is this something specific to the Duke code? If that's the clipmask you are using to pass to hitscan, it is wrong. You need to set some of the high 16 bits or else hitscan won't hit any sprites. Make sure those high 16 bits, when shifted down 16 bits will generate a non-zero value when ANDed with the player sprite's cstat. Please refer to the "2/9/96" entry of BUILD2.TXT for more information.
Finally, this might sound stupid, but are you maintaining a sprite object for the player position and updating its x/y/z/sectnum on every frame?
Kyoufu Kawa at
1. Hittype is not a Duke thing. I'm basing this on KenBuild, remember?
2. Clipmask is okay. The three sprites that stand in front of the gun sprite are hit after all.
3. I think I do update it, it's something I hardly touched since it worked. I'll check it out in a minute and call back.
A short explanation on HitType:
After calling Hitscan, I call a function that takes all values returned by Hitscan and determines what we hit. It then returns the appropriate value as found in the following enum { HITA_NOTHING, HITA_SPRITE, HITA_BREAKER, HITA_PLAYER, HITA_WALL, HITA_WALLBREAKER, HITA_PANEL, HITA_FLOOR, HITA_CEILING, HITA_HEDGE, HITA_SKY, HITA_WATERSURFACE, HITA_WATERFALL, HITA_BUTTON }.
HITA_PLAYER is never returned. Considering it's returned by the following code...
it might be a player/playersprite location mismatch... TO THE ON-SCREEN DEBUG MOBILE!
Update: Quick testing shows that the player and the player's sprite are equal in position.
Awesoken at
Are you updating the player sprite's sectnum properly? Please note: if you overwrite the sectnum of the sprite structure directly, it will corrupt Build's internal linked lists. For example:
Edit: Exactly that code. Found it in only one place. Lemme put it in context...
if (Player.dimensionmode != 3)
{
if (((ssync[snum].bits&32) > 0) && (Player.zoom > 48)) Player.zoom -= (Player.zoom>>4);
if (((ssync[snum].bits&16) > 0) && (Player.zoom < 4096)) Player.zoom += (Player.zoom>>4);
}
//Update sprite representation of player
// -should be after movement, but before shooting code
setsprite(Player.playersprite,Player.posx,Player.posy,Player.posz+EYEHEIGHT);
sprite[Player.playersprite].ang = Player.ang;
if (Player.health >= 0)
{
if ((Player.cursectnum < 0) || (Player.cursectnum >= numsectors))
{ //How did you get in the wrong sector?
HurtAPlayer(-TICSPERFRAME, 0,KILLER_ENVIRONMENT);
...
Are you updating the player sprite's sectnum properly? Please note: if you overwrite the sectnum of the sprite structure directly, it will corrupt Build's internal linked lists.
Can you elaborate on this corruption? I'm curious, because people have been doing just that via CONs in EDuke for quite a while now. I've added a "setsprite" keyword to give access to the setsprite function, but I'm interested in how/why this corruption occurs, where it occurs, and why I've never seen/heard anything about it until now.
I'm looking through build.txt and build2.txt for any notes about it, but I'm not finding any.
plugwash at
Awesoken said
Are you updating the player sprite's sectnum properly? Please note: if you overwrite the sectnum of the sprite structure directly, it will corrupt Build's internal linked lists. For example:
right but that doesn't let you control which sector the sprite ends up in if there is more than one at the specified coordinates.
TX at
plugwash said
Awesoken said
Are you updating the player sprite's sectnum properly? Please note: if you overwrite the sectnum of the sprite structure directly, it will corrupt Build's internal linked lists. For example:
right but that doesn't let you control which sector the sprite ends up in if there is more than one at the specified coordinates.
If there is more than one sector at the specified set of coordinates, how are you going to know which sector to put it in yourself? The methods of detection will return the same value as setsprite uses, as setsprite itself calls updatesector.
Hey Ken, why is setsprite calling updatesector rather than updatesectorz, with updatesectorz #ifdef'd out?
Awesoken at
Kyoufu Kawa: Actually, the "Player" structure is not part of the original KenBuild source.
Some other fields which can affect hitscan are: picnum and clipdist. The height of the collision box is controlled by tilesizy[sprite[?].picnum], and the width is controlled by sprite[?].clipdist. If your sprite index has null dimensions (0x0) in the ART file, that would cause a problem.
TX: Try searching for "setsprite" in BUILD.TXT. You will find several warnings telling you not to modify the sprite's sectnum directly. Headspritesect[], nextspritesect[], and prevspritesect[] form a doubly-linked list of sprites for each sector. If you start modifying sectnums without updating the pointers properly (with insertspritesect(), deletespritesect(), or some of the higher-level functions which call these internally (setsprite(), movesprite(), etc..)), things will go bad.
plugwash: That's a valid point, but I was trying to give a simple example here. This would only be a problem for truly overlapping sectors. Even so, updatesector() searches the neighboring sectors first, so as long as your sprite doesn't skip through 2 sector border lines in one move, there will be no problem.
JonoF at
Hey Ken, why is setsprite calling updatesector rather than updatesectorz, with updatesectorz #ifdef'd out?
Duke3D uses updatesector() and Shadow Warrior uses updatesectorz(). Originally the Shadow Warrior source was overriding the engine's version of setsprite() with an almost identical one that called updatesectorz() rather than updatesector(). I unified it all by transplanting updatesectorz() back into the engine code and set up a macro to determine which behaviour setsprite() should use.
Jonathon
plugwash at
seems like the sw version was a fix done to support shadow warriors SOS system (which iirc actually places the sectors over each other in game coordinates).
TX at
Awesoken said
TX: Try searching for "setsprite" in BUILD.TXT. You will find several warnings telling you not to modify the sprite's sectnum directly. Headspritesect[], nextspritesect[], and prevspritesect[] form a doubly-linked list of sprites for each sector. If you start modifying sectnums without updating the pointers properly (with insertspritesect(), deletespritesect(), or some of the higher-level functions which call these internally (setsprite(), movesprite(), etc..)), things will go bad.
Ta. I was searching for "sectnum," the comment actually wrote out "sector number" -- no wonder I couldn't find it. :)
JonoF said
Hey Ken, why is setsprite calling updatesector rather than updatesectorz, with updatesectorz #ifdef'd out?
Duke3D uses updatesector() and Shadow Warrior uses updatesectorz(). Originally the Shadow Warrior source was overriding the engine's version of setsprite() with an almost identical one that called updatesectorz() rather than updatesector(). I unified it all by transplanting updatesectorz() back into the engine code and set up a macro to determine which behaviour setsprite() should use.
Jonathon
Aha. I assume nothing bad will happen if I define it in Duke as well. Perhaps things like the glitches on Hollywood Holocaust where you can end up in the arcade from the window sill in the hidden red room will go away as well. Hrm...
Edit: Ken, I'm assuming the same is true about the linked lists for statnums?
Kyoufu Kawa at
Awesoken said
Kyoufu Kawa: Actually, the "Player" structure is not part of the original KenBuild source.
Some other fields which can affect hitscan are: picnum and clipdist. The height of the collision box is controlled by tilesizy[sprite[?].picnum], and the width is controlled by sprite[?].clipdist. If your sprite index has null dimensions (0x0) in the ART file, that would cause a problem.
Ho sheet! That gives two more symptoms to check! I'll be right back!
I've doublechecked it, Player.playersprite and playersprite[snum] are effectively equals. That leaves only the collision box.
Edit: Player picnum=1030, tilesizx[1030] = 0, clipdist = 64 and it was indeed blank. How stupid I am. m(_ _)m
Edit: It works now. Thank you Mr. Silverman (and all you other cool guys)
Awesoken at
Perhaps things like the glitches on Hollywood Holocaust where you can end up in the arcade from the window sill in the hidden red room will go away as well.
It will only help if the sectors aren't overlapping. In your example, they do in fact overlap. I think this is actually a Duke3D bug - since I can't seem to jump sectors at that place in the Build editor. Probably, Todd is calling updatesector without using the current sector as a hint. Keep in mind that if you use updatesectorz, you won't be raised or lowered to a valid sector when you're running through walls in noclip mode.
Ken, I'm assuming the same is true about the linked lists for statnums?
Yes.
Kyoufu Kawa at
One last post for me, here's some screenshots of the game so far.