Hitscan

From EDukeWiki
Jump to navigation Jump to search

hitscan <x1> <y1> <z1> <sect1> <cos of ang> <sin of ang> <zvel> <hit sector return var> <hit wall return var> <hit sprite return var> <hit x return var> <hit y return var> <hit z return var> <clip mask>

Hitscan returns the values of what would be hit if one travelled in a straight line from a set of coordinates in a specified direction.

All parameters are gamevars. The first three are the coordinates from which the hitscan occurs, followed by the scanning sector. The cos, then the sin of an angle (typically the ang of the actor performing the scan) come next, followed by the z angle, which must be calculated before the hitscan. The six return gamevars hold the values of what the hitscan hits. The value of clipmask tells hitscan which sorts of things it can hit. A clipmask of 4294901808 is useful for most purposes.

HITWALL and HITSPRITE's default value is -1. They will be filled up with the wall id or sprite id that is hit. In other words, if running hitscan against an actor and HITWALL's value is not -1, that means the target actor is not hit. If it is hit, HITSPRITE will be set to the id of the actor.

Example of hitscan originating from the player:

//  This state will return the sector, wall, and sprite(id, x ,y, and z data)currently under the crosshair.
 
state checkhitscan
	getplayer[THISACTOR].posx MY_X
	getplayer[THISACTOR].posy MY_Y
	getplayer[THISACTOR].posz MY_Z
	getplayer[THISACTOR].cursectnum MY_SECTOR
	getplayer[THISACTOR].ang MY_ANGLE
	getplayer[THISACTOR].horiz MY_ZDIST
	subvar MY_ZDIST 100
	mulvar MY_ZDIST -2048
	cos MY_COS MY_ANGLE
	sin MY_SIN MY_ANGLE

	hitscan MY_X MY_Y MY_Z MY_SECTOR MY_COS MY_SIN MY_ZDIST HITSECTOR HITWALL HITSPRITE HITX HITY HITZ 4294901808
ends

If the hitscan does not originate from the player but from another actor, the code is a bit different:

  • Ensure the hitscan cstat bit is set on the target actor
  • The angle needs to be calculated
  • The zdist calculation is different
  • If appropriate, the "my_z" coordinate needs to be shifted up to the "eye level" of the actor. You should be able to get away with using a constant value around 4096-8192 for most cases, but it depends on the exact height of the actor.
state checkhitscan
	geta[].x MY_X
	geta[].y MY_Y
	geta[].z MY_Z
	geta[].sectnum MY_SECTOR

        geta[otheractor].x OTHER_X
	geta[otheractor].y OTHER_Y
	geta[otheractor].y OTHER_Z
	geta[otheractor].cstat CSTAT_BACKUP
	seta[otheractor].cstat 256 // enable hitscan bit is set or the sprite will not be detected
	
	// Calculate angle
	sub OTHER_X MY_X
	sub OTHER_Y MY_Y
	getangle MY_ANGLE OTHER_X OTHER_Y
	cos MY_COS MY_ANGLE
	sin MY_SIN MY_ANGLE
	
	// Calculate zdist
	set MY_ZDIST OTHER_Z
	sub MY_ZDIST MY_Z
	shiftvarl MY_ZDIST 14
	ldist xydist THISACTOR otheractor
	ife xydist 0 set xydist 1
	divvarvar MY_ZDIST xydist
	
	// Bring Z position to "eye level", exact value needed here depends on height of the sprite
	// This could maybe also be calculated using ysize
	sub MY_Z 8192
	
	hitscan MY_X MY_Y MY_Z MY_SECTOR MY_COS MY_SIN MY_ZDIST HITSECTOR HITWALL HITSPRITE HITX HITY HITZ 4294901808
	
	// reinstate original cstat (useful in case the sprite you're checking against is a non-blocking effect sprite for instance)
	seta[otheractor].cstat CSTAT_BACKUP
ends