I just saw this thread and thought I should write something in here. First of all, I didn't understand everything you were talking about, lol. But I find it far too complex. Gravity affecting the arrow is so small it isn't really noticable. Aside from that I think you didn't include some important factors like the height difference, the height of the actors itself and so on. I created a new detection system for version 2.2 of my Locational Damage mod and everythings works nearly perfectly (one thing is still subject to change) from any angle, position etc. You find it below, I'll release it anyway when I release v2.2. I'm going to share my thoughts with you that I had while creating this system: First, I'm saving the player's position, X angle and if he's sneaking or not when he shoots. I'm not using OnPlayerBowShot for that though as it doesn't trigger when using a crossbow. Instead, I'm just using the "arrowRelease"-animation event for that and the OnPlayerBowShot to get the power of the shot. Then I save everything in my quest script. Event OnAnimationEvent(ObjectReference Source, string asEventName)
if(source == playerRef)
if(asEventName == "arrowRelease")
script.shotAngle = playerRef.getangleX()
script.xPos = playerRef.getpositionX()
script.yPos = playerRef.getpositionY()
script.zPos = playerRef.getpositionZ()
script.shotIsSneaking = playerRef.isSneaking()
endif
endif
EndEvent
Event OnPlayerBowShot(Weapon akWeapon, Ammo akAmmo, float afPower, bool abSunGazing)
script.shotPower = afPower
EndEvent When the player then hits someone with the arrow I can use these values for the calculation. First I'm going to determine the distance between the shot position and the target's postion: ; xyzPos = player position
; xyzPosMe = target position
dist = sqrt(pow((xPos - xPosMe), 2.0) + pow((yPos - yPosMe), 2.0) + pow((zPos - zPosMe), 2.0)) When no crossbow was used I also use the gravity and the power of the shot: ; xA = X angle on shot
; dist = distance given by getdistance()
float power = script.shotPower
xA /= power
dist += (dist*getgamesettingfloat("fArrowGravityMult")) This makes sure the correct hit location is found by the calculation. Now to the actual detection. Intially I calculate the height of the attacker and target taking into account if they're sneaking or not as well as their scale. Next I'm going to detect if the attacker is aiming to the arms/legs and if yes which arm or leg, using somewhat predefined values (this is actually still subject to change because it's from my old system and I cannot save the headingAngle to a target on shot). After that I calculate the "real" distance between the target and the attacker using a triangle consisting of the distance given by the getdistance()-function as the hypotenuse and the height difference as the opposite. Now I can calculate the adjacent by using the Pythagoras' theorem. After that I calculate the height difference between the attacker's head (where his "camera" is set) and different heights of the target representing the different body zones. This helps me getting "angle ranges" for the body zones by using the arctangent. Then I compare these angle ranges with the X angle and check in which range the attacker is and then know which bodyzone was hit. Pretty simple if you think about it. But it works amazingly well. ; 1 = head
; 2 = neck
; 3 = nape
; 5 = Rshoulder
; 6 = Lshoulder
; 7 = Rarm
; 8 = LArm
; 9 = chest
; 10 = back
; 11 = groin
; 12 = legs
; 13 = feet
; headingAngle = attacker.getheadingAngle(target)
; facing = target.getheadingAngle(attacker)
int function hitDetection(Bool UsedPowerattack)
scale = attacker.getscale()
scaleMe = me.getscale()
height = attacker.getheight()*scale
heightMe = me.getheight()*scaleMe
if(bIsSneaking)
height *= 0.75
endif
if(bIsSneakingMe)
heightMe *= 0.75
endif
rangedScale = 1 + (scaleMe - scale)
shoulderDisp = 3.5*rangedScale
armDisp = 12.1*rangedScale
disposition = dist * sin(headingAngle)
float dispHeight = zPos - zPosMe
dist = sqrt(pow(dist, 2.0) - pow(dispheight, 2.0))
Float pos = (zPos + height)
heightDist = pos - (zPosMe + (heightMe*0.9))
headZone = atan(heightDist/dist)
heightDist = pos - (zPosMe + (heightMe*0.85))
neckZone = atan(heightDist/dist)
heightDist = pos - (zPosMe + (heightMe*0.75))
shoulderZone = atan(heightDist/dist)
heightDist = pos - (zPosMe + (heightMe*0.5))
chestZone = atan(heightDist/dist)
heightDist = pos - (zPosMe + (heightMe*0.4))
groinZone = atan(heightDist/dist)
heightDist = pos - (zPosMe + (heightMe*0.2))
legZone = atan(heightDist/dist)
if(xA < headZone)
return 1
elseif(xA < neckZone)
if(facing <= -135 || facing >= 135)
return 3
else
return 2
endif
elseif(xA < shoulderZone)
return shoulderhitCalc(UsedPowerattack)
elseif(xA < chestZone)
return armHitcalc()
elseif(xA < groinZone)
if(abs(facing) < 45)
return 11
else
return 12
endif
elseif(xA < legZone)
return 12
else
return 13
endif
endfunction
int function armHitCalc()
if(abs(facing) < 45)
if(disposition > armDisp)
return 7
elseif(disposition < -armDisp)
return 8
else
return 9
endif
elseif(facing < -45 && facing > -135)
return 8
elseif(facing > 45 && facing < 135)
return 7
elseif(abs(facing) >= 135)
if(disposition > armDisp)
return 8
elseif(disposition < -armDisp)
return 7
else
return 10
endif
endif
endfunction
int function shoulderHitCalc(bool UsedPowerattack)
if(abs(facing) < 45)
if(disposition > shoulderDisp)
return 5
elseif(disposition < -shoulderDisp)
return 6
elseif(type != 7)
if(UsedPowerattack)
return 4
else
return 9
endif
else
return 4
endif
elseif(facing < -45 && facing > -135)
return 6
elseif(facing > 45 && facing < 135)
return 5
elseif(abs(facing) >= 135)
if(disposition > shoulderDisp)
return 6
elseif(disposition < -shoulderDisp)
return 5
else
return 10
endif
endif
endfunction I hope it's readable because the forum seems to add extra blank lines after every command. If you have any questions just ask. :-) Kahmul