Some doing indeed. UNTESTED PATCH ready. I have only verified that zdoom still starts. I have not stuck fully with the suggestion from NeuralStunner -I tried for a bit more flexibility.
One readily uncertain thing: Does floorclipping and other position-adjustments mess with this? I simply don't know. There turned out to be a few points of uncertainty, but either I found out most of it, or I forgot something... (dun dun dun!)
Also, for the time being this relies on the untested assumption that you can hitscan for the next object by temporarily unlinking the object you encountered last. There may be better solutions.
Even if some implementations are wrong, or bad, the function is established with code/flow, so bugfixes might be a piece of cake by comparison. (Ooooh, optimism! Bliiiind optimism.)
A_CheckRay (state jump, int flags = CRF_AIM_VERT|CRF_AIM_HOR, double range = 0, angle angle = 0, angle pitch = 0, double offsetheight = 32, double offsetwidth = 0, int ptr_target = AAPTR_DEFAULT);
jump: standard state parameter
flags: long list follows
range: 0 = infinite (represented by 0x7FFFFFFF as fixed_t, I don't know if that's gonna be fine or not)
angle: offset your aim by this angle (based either on your facing, or direction towards target)
pitch: offset your aim by this pitch (based either on your facing, or direction towards target) <-- high risk of miscalculation (such as needing - where + was used)
offsetheight: change the height from which ray is cast; aim is adjusted to correct for this offset (if pitch is determined by a target)
offsetwidth: cast the ray from the side; aim is not adjusted to correct for this offset
ptr_target: pick an actor to aim for, AAPTR_DEFAULT picks TARGET (to ensure no actor is targeted, use AAPTR_NULL)
EXAMPLE >> Minimalist call: A_CheckRay("shoot")
Jumps to state if the default line of sight (as provided by me, might not correspond well to various hitscan functions) is clear.
Flags (aim)
CRF_AIM_VERT: Aim for target actor if there is one (angle)
CRF_AIM_HOR: Aim for target actor if there is one (pitch)
Flags (jump on intercept)
CRF_JUMPENEMY: Jump if an enemy breaks the ray
CRF_JUMPFRIEND: Jump if a friend breaks the ray
CRF_JUMPOBJECT: Jump if a non-monster breaks the ray
CRF_JUMPNONHOSTILE: Jump if a non-enemy breaks the ray (I
think "wild" monsters may see eachother as non-enemies unless they're set to fight over everything all the time)
Flags (skip on intercept) (jump has precedence over skip)
CRF_SKIPENEMY: Ignore enemies breaking the ray
CRF_SKIPFRIEND: Ignore friends breaking the ray
CRF_SKIPOBJECT: Ignore non-monsters breaking the ray
CRF_SKIPNONHOSTILE: Ignore non-hostiles breaking the ray
Flags (filter on intercept) (has precedence over jump)
CRF_MUSTBESHOOTABLE: Ignore actors that are not shootable (checks SHOOTABLE and NONSHOOTABLE)
CRF_MUSTBEGHOST: Ignore actors that are not ghosts
CRF_IGNOREGHOST: Ignore actors that are ghosts
CRF_MUSTBESOLID: Ignore actors that are not solid
Flags (misc)
CRF_SKIPTARGET: Ignore the target actor breaking the ray
-- The ray has to reach the target actor for the target actor to be returned
-- None of the other filters apply to the target actor, they only apply to intercepting actors
CRF_BEYONDTARGET: Trace past the targeted actor (requires SKIPTARGET)
CRF_ALLOWNULL: Cast the ray even if target is NULL. When there is no target, caller aim (pitch, angle) is used regardless of aim-flags.
CRF_CHECKPARTIAL: Perform the check even if the target itself is actually out of range. Useful if you're still interested in closer intercepting actors.
Flag combos
CRF_SKIPOBSTACLES = CRF_SKIPENEMY|CRF_SKIPFRIEND|CRF_SKIPOBJECT|CRF_SKIPNONHOSTILE
(You can override some of these with jump-flags, such as CRF_SKIPOBSTACLES|CRF_JUMPFRIEND)
EXAMPLE >> Don't shoot if there's a friend somewhere on the way: A_CheckRay("dontshoot", CRF_SKIPTARGET|CRF_JUMPFRIEND|CRF_SKIPOBSTACLES|CRF_MUSTBESHOOTABLE)
EXAMPLE >> Don't shoot if a friend will catch it: A_CheckRay("dontshoot", CRF_SKIPTARGET|CRF_JUMPFRIEND|CRF_MUSTBESHOOTABLE)
-- The first one skips obstacles, assuming that the shot will/may go through them; the shooter simply does not wish to shoot in the direction of a friend
-- The second one hits anything, and jumps (aborting fire) if it is a friend; if the first obstacle is not a friend, the jump will not happen
It is a distinct possiblity that this will, for any odd reason, not work.
It is a distinct possibility that a sane cap must be introduced on search range. (0x7fffffff represents "unlimited" in a Doom map)EXAMPLE >> Just don't shoot in the direction of a friend: A_CheckRay("dontshoot", CRF_SKIPTARGET|CRF_BEYONDTARGET|CRF_JUMPFRIEND|CRF_SKIPOBSTACLES|CRF_MUSTBESHOOTABLE)
For attacks that risk going through the target and hitting your good friend
behind the target.
None of these examples do anything to limit range. And with the offsets and angles it is fully possible to miss the target entirely. That may be what you want. While it may change, for now I'm trying to allow "infinite" range when it is unspecified.
I hope you find my version understandable and useful, and I hope it works. Changes, additions, questions, regrets; bring them forth. (Objections?)
Corrections, advice, fixes... Anything you have.
Successful tests:
Player weapon that will only shoot if "a_checkray(1)" jumps. (Only if player is looking directly at something. Not much more effective than A_JumpIfTargetInLOS when used so plainly by a player. Players will relly only need it for strange and advanced stuff I think.)
Untested stuff: Most of it
non-0 offsets (width, height)
non-0 angle/pitch settings
traces that don't actually encounter the target, running with nigh unlimited range
traces that run into intercepting actors
the many flag combinations
monster actions
EDIT: NEW FILE
download/file.php?id=13750; NEW DETAILS
viewtopic.php?f=15&t=29014&p=637925#p637925