Headshot script not working

Post » Sun Jun 24, 2012 6:26 am

I have a start game enabled quest. I set up a reference alias in this quest. It places an FXemptyactivator at the player when the quest loads up. Attached to it is the following script:

Scriptname ESG_DetermineHeadshot extends ReferenceAlias Import MathFloat HeadPosXFloat HeadPosYFloat HeadPosZFloat HitPosXFloat HitPosYFloat HitPosZActor TargetBool HitLocReportedBool HeadLocReportedFunction HeadNode(Float PosX, Float PosY, Float PosZ, Actor Victim)HeadPosX = PosXHeadPosY = PosYHeadPosZ = PosZTarget = VictimHeadLocReported = trueIf HitLocReported  HeadLocReported = false  CalcResult()EndIfEndFunctionFunction HitLocation(Float PosX, Float PosY, Float PosZ)HitPosX = PosXHitPosY = PosYHitPosZ = PosZHitLocReported = trueIf HeadLocReported  HitLocReported = false  CalcResult()EndIfEndFunctionFunction CalcResult()Float Distance = sqrt(pow((HeadPosX - HitPosX), 2.0) + pow((HeadPosY - HitPosY), 2.0) + pow((HeadPosZ - HitPosZ), 2.0))If Distance < 100  Debug.Notification("Headshot!")Else  Debug.Notification("Not a Headshot...")EndIfEndFunction

I also have a spell. This spell has a magic effect with the following script:

Scriptname ESG_HeadNodeFinder extends ActiveMagicEffect ReferenceAlias Property HeadshotLocator AutoEvent OnInit()Actor Target = GetTargetActor()HeadshotLocator.GetRef().MoveToNode(Target, "NPC Head [Head]")(HeadShotLocator as ESG_DetermineHeadshot).HeadNode(HeadShotLocator.GetRef().GetPositionX(), HeadShotLocator.GetRef().GetPositionY(), HeadShotLocator.GetRef().GetPositionZ(), Target)Dispel()EndEvent

The spell uses a custom projectile, that closely mimics Ice Spike, only it has an explosion. This explosion only exists to place another activator, this one is also custom. It has the attached script:

Scriptname ESG_HitPosScript extends ObjectReference ReferenceAlias Property HeadshotMarker AutoEvent OnInit()(HeadshotMarker as ESG_DetermineHeadshot).HitLocation(GetPositionX(), GetpositionY(), GetpositionZ())DisableNoWait()Delete()EndEvent



My problem is as follows: When a target is perfectly still, standing upright, and I shoot them in the head, I get a notification that it was not a headshot.

This tells me that both the magic effect and the projectile are reporting the location of the head node and the location of where the projectile hit, and the script is calculating something. But apparently, it isn't calculating it correctly. Either MoveToNode isn't working on my activator referencealias, or my equation is wrong.

Any help?
User avatar
Deon Knight
 
Posts: 3363
Joined: Thu Sep 13, 2007 1:44 am

Post » Sun Jun 24, 2012 10:14 am

  • Does your script log report any errors?
  • What if you try using OnEffectStart instead of OnInit for the spell script?
  • Try using Debug.Notification and Debug.Trace to report the positions so you can check them.
  • For your reference alias script's functions, change parts of it to this instead:
If HeadLocReported    HeadLocReported = false    CalcResult()Else    HitLocReported = trueEndIf
User avatar
Vahpie
 
Posts: 3447
Joined: Sat Aug 26, 2006 5:07 pm

Post » Sun Jun 24, 2012 4:39 pm

Moving that bit into OnEffectStart() did the trick. Works beautifully now, and relatively well on moving targets too!
User avatar
Samantha Mitchell
 
Posts: 3459
Joined: Mon Nov 13, 2006 8:33 pm

Post » Sun Jun 24, 2012 3:49 pm

http://www.youtube.com/watch?v=GkzRtx3gWJA

And there it is, working beautifully! This will make for some awesome perks. Again, thanks for your help!
User avatar
Blessed DIVA
 
Posts: 3408
Joined: Thu Jul 13, 2006 12:09 am

Post » Sun Jun 24, 2012 10:56 am

So are you going to tie a double damage/stagger effect script when you get a head shot on people/critters? That would be pretty cool.

You should move the message into the upper left corner without the dialog box. Something like "Headshot! Damage x2"
User avatar
Fam Mughal
 
Posts: 3468
Joined: Sat May 26, 2007 3:18 am

Post » Sun Jun 24, 2012 11:57 am

Explosion Property BloodDecalPlaceExplosion AutoExplosion Property SomeOtherExplosion AutoArmor Property NonPlayableInvisibleHelmet AutoFunction CalcResult()Float Distance = sqrt(pow((HeadPosX - HitPosX), 2.0) + pow((HeadPosY - HitPosY), 2.0) + pow((HeadPosZ - HitPosZ), 2.0))If Distance < 100    ;Display "HEADSHOT" using quest objective    GetOwningQuest().SetObjectiveDisplayed(10, True)    GetReference().PlaceAtMe(BloodDecalPlaceExplosion)    GetReference().PlaceAtMe(SomeOtherExplosion)    Actor MyTarget = Game.FindClosestActorFromRef(GetReference())    MyTarget.EquipItem(NonPlayableInvisibleHelmet)    MyTarget.Kill()Else    Debug.Notification("Not a Headshot...")EndIfEndFunction
User avatar
Stephanie Nieves
 
Posts: 3407
Joined: Mon Apr 02, 2007 10:52 pm

Post » Sun Jun 24, 2012 3:49 pm

What I have here is for testing purposes. The effects and whatnot will come later. I was just using this to build a reliable headshot detection system.


I plan on working this into 3 perks in the destruction tree, and later extending it to bows in the archery tree (though that will likely require a new system because this relies on both a magic effect landing on the target and an explosion created by the projectile.) Archery will be more difficult to do.

Anyways, the three perks in the destruction tree will be Nueral Shock, Mind Fire, and Brain Freeze. They will give your single target destruction spells a bonus when hitting enemies in the head. Mind Fire might enrage or fear the target, Brain Freeze might calm them or paralyze them, Nueral Shock might disarm them or destroy a large portion of their magicka. I have not decided on the effects yet, but I wanted them to do something other than just bonus damage.

I have updated the scripts a bit to give variable amounts of "leniency" when hitting moving targets. If the target is perfectly still, you must hit them exactly in the head, if they are walking, you get a slightly larger hit box, if they are running, it is even larger. I have tweaked it so that it feels accurate, though on running targets, you may inspect them and find your ice spike is embedded in their shoulder and not their head, but the whole process seems good enough.


Obviously there wont be wonky notification boxes popping up interrupting gameplay, this is merely a framework for the aforementioned effects.

I did see a locational damage mod where a guy managed to determine with a good deal of accuracy whether arrows are hitting individual body parts. I would love to know how he accomplished this, as this is the only method I have been able to think up thus far and I doubt it could be expanded on to accurately report hits to body parts other than the head.
User avatar
Janeth Valenzuela Castelo
 
Posts: 3411
Joined: Wed Jun 21, 2006 3:03 am

Post » Sun Jun 24, 2012 4:08 pm

Here is the updated script, working beautifully. Finally got the numbers fine-tuned so it works pretty solid.

For the ReferenceAlias that is created, FXemptyactivator, at the player, I have a script that sets up the various functions required to calculate the headshot. This is the script:

Spoiler

Scriptname ESG_DetermineHeadshot extends ReferenceAliasImport MathFloat HeadPosXFloat HeadPosYFloat HeadPosZFloat HitPosXFloat HitPosYFloat HitPosZActor TargetBool HitLocReportedBool HeadLocReportedInt MaxFloat OffsetBool HeadshotSuccess = falseFunction HeadNode(Float PosX, Float PosY, Float PosZ, Float Mobility, String SourceType)HeadPosX = PosXHeadPosY = PosYHeadPosZ = PosZOffset = Mobility * 0.35If HitLocReported  HeadLocReported = false  CalcResult()Else  HeadLocReported = trueEndIfEndFunctionFunction HitLocation(Float PosX, Float PosY, Float PosZ)HitPosX = PosXHitPosY = PosYHitPosZ = PosZIf HeadLocReported  HitLocReported = false  CalcResult()Else  HitLocReported = trueEndIfEndFunctionFunction CalcResult()Float Distance = sqrt(pow((HeadPosX - HitPosX), 2.0) + pow((HeadPosY - HitPosY), 2.0) + pow((HeadPosZ - HitPosZ), 2.0))If Distance < (13 + Offset)  HeadshotSuccess = trueEndIfEndFunctionBool Function RetrieveHeadshot()If HeadshotSuccess  Return True  HeadshotSuccess = FalseElse  Return FalseEndIfEndFunction


For the activator that we spawn using an explosion attached to the projectile, which "reports" its location, the hit location, to the ReferenceAlias, I used this script:

Spoiler

Scriptname ESG_HitPosScript extends ObjectReferenceReferenceAlias Property HeadshotMarker AutoEvent OnInit()(HeadshotMarker as ESG_DetermineHeadshot).HitLocation(GetPositionX(), GetpositionY(), GetpositionZ())DisableNoWait()Delete()EndEvent

And finally, for the magic effect attached to the spell, I have two scripts. One of them reports the location of the targets head and calculates how fast the target is moving, and the other retrieves whether or not the spell was a headshot and then has the target remotecast a new spell which represents the "bonus" effect from getting a headshot.

Spoiler

Scriptname ESG_HeadNodeFinder extends ActiveMagicEffectReferenceAlias Property HeadshotMarker AutoActivator Property FXemptyactivator AutoString Property SourceType AutoFloat DistanceMovedInt MobilityObjectReference MobileTargetCheckerEvent OnEffectStart(Actor Target, Actor Caster)HeadshotMarker.GetRef().MoveToNode(Target, "NPC Head [Head]")MobileTargetChecker = Caster.PlaceAtMe(FXemptyactivator)MobileTargetChecker.MovetoNode(Target, "NPC Head [Head]")DistanceMoved = Math.sqrt(Math.pow((HeadShotMarker.GetRef().GetPositionX() - MobileTargetChecker.GetPositionX()), 2) + Math.pow((HeadShotMarker.GetRef().GetPositionY() - MobileTargetChecker.GetPositionY()), 2) + Math.pow((HeadShotMarker.GetRef().GetPositionZ() - MobileTargetChecker.GetPositionZ()), 2))(HeadShotMarker as ESG_DetermineHeadshot).HeadNode(HeadShotMarker.GetRef().GetPositionX(), HeadShotMarker.GetRef().GetPositionY(), HeadShotMarker.GetRef().GetPositionZ(), DistanceMoved, SourceType)Dispel()EndEvent

Scriptname ESG_HeadShotBonusSpell extends ActiveMagicEffectSpell Property HeadShotBonus AutoReferenceAlias Property HeadshotMarker AutoBool Cast = falseEvent OnEffectStart(Actor Target, Actor Caster)Utility.Wait(0.2)Cast = (HeadshotMarker as ESG_DetermineHeadshot).RetrieveHeadShot()If Cast  Debug.Notification("Headshot")  HeadShotBonus.RemoteCast(Target, Caster)EndIfEndEvent
User avatar
Trey Johnson
 
Posts: 3295
Joined: Thu Oct 11, 2007 7:00 pm

Post » Sun Jun 24, 2012 5:10 am

Encountered a problem. For some reason, if I hit a target the first time, it wont register a headshot no matter what. But I have to hit them with the spell once before it will start registering headshots.

So i shoot someone in the head, nothing. Shoot them in the head again, get a headshot notification. Turn around and shoot someone else in the head, nothing, shoot again, headshot. Then if I go back to the first target and hit them in the head, nothing, gotta do it again.
User avatar
Jamie Moysey
 
Posts: 3452
Joined: Sun May 13, 2007 6:31 am

Post » Sun Jun 24, 2012 5:22 am

If i understand this correctly, you have a magic effect which determines whether it was a head shot or not.

I suspect problem with magic effects and scripts is that the magic effect is applied and then the script runs, however your shot has already taken place and you second shot works because the magic effect is already applied
User avatar
Samantha Jane Adams
 
Posts: 3433
Joined: Mon Dec 04, 2006 4:00 pm


Return to V - Skyrim