trashgarbage666 Posted December 27, 2017 Share Posted December 27, 2017 (edited) Like the title says, I'm working on a headshot script, and need some help working out a very persistent bug. I have no coding knowledge whatsoever, so the code you're seeing now is based purely on examples and lots and lots of testing. What the script does: The script is attached to Ammo as an "Impact Script". When the ammo hits a target, it checks if the target's human, checks if the target's been hit in either the head or neck, checks if the target isn't wearing a helmet, and checks if the target isn't dead already. If all four conditions are good, it sets the target's health to 0. (I omitted the part that checks for helmets from the example script below, because I actually use three different versions of this script that I apply to ammo of varying caliber. The only difference between the three versions being which helmets prevent headshots from insta-killing the target. It's just a GetEquipped Form List check. It isn't causing the error.) ScriptName HeadshotAmmoSCRIPT BEGIN GameMode Ref rTarget Set rTarget to GetOwnerLastTarget If (GetHitLocation == 1 || GetHitLocation == 2) && (rTarget.GetDead != 1) && (rTarget.GetIsCreature != 1) ForceActorValue Health 0 Else EndIf ENDHere's my problem: Currently, the code says headshots are only lethal if the target IS NOT a creature. However, if I load up the game with the code looking like this, headshots are lethal to everything. Creatures and NPCs. If I reverse the condition so headshots are ONLY lethal to creatures, then headshots behave like a bodyshot on all creatures and NPCs. The GetIsCreature command is behaving like it can't tell the difference between humans and animals. It's really important that I get this script to ignore creatures, because I'd much rather handle headshot lethality on a creature to creature basis through Body Part Data damage mults. The player shouldn't be able to 1-shot deathclaws with a 9mm. Hopefully all my script needs is a fresh set of eyes on it. Thanks for hearing me out! Edited December 27, 2017 by punchbattle Link to comment Share on other sites More sharing options...
dubiousintent Posted December 27, 2017 Share Posted December 27, 2017 (edited) Here's a programming tip for when a compound conditional (multiple tests on the same line) is not working as expected: split it up into nested conditions. An "ElseIf" is equivalent to an "OR (||)" compound, and each nested "IF" statement is equivalent to an "AND (&&)" compound. So, change: "If (GetHitLocation == 1 || GetHitLocation == 2) && (rTarget.GetDead != 1) && (rTarget.GetIsCreature != 1)" into: If (GetHitLocation == 1 || GetHitLocation == 2) ; NVSE required: PrintD (string:expression), DBPrint (formatted string) DBPrintC "Script [HeadshotAmmoSCRIPT], GetHitLocation = [%g].", GetHitLocation If (rTarget.GetDead != 1) ; NVSE required: PrintD (string:expression), DBPrint (formatted string) PrintD "Script [HeadshotAmmoSCRIPT], rTarget.GetDead = [" + $(rTarget.GetDead) + "]." If (rTarget.GetIsCreature != 1) ; NVSE required: PrintD (string:expression), DBPrint (formatted string) PrintD "Script [HeadshotAmmoSCRIPT], rTarget.GetIsCreature = [" + $(rTarget.GetIsCreature) + "]." ForceActorValue Health 0 Else ; (Can be dropped if you just want it to totally fail.) Endif Else; (Can be dropped if you just want it to totally fail.) Endif Else EndIf Insert "debug messages" (examples given) as required to pin down what values your conditions are actually testing. That should quickly isolate what is not as expected. (I just repeat the '; NVSE required' comment line to remind myself of the required syntax differences with each line. Not required otherwise.) Use the game console "bat <filename.bat>" command to run a "batch file" similar to this to trigger the debug print statements when testing. Without that they won't actually do anything normally: con_SCOF "_MyDebug.log" ; Output console messages to file DBMode 1 65 ; "Enable Debug mode" command ; NVSE required: PrintD (string:expression), DBPrint (formatted string) DBPrintC "Starting log for mod index 65(0x41) (<ModPluginName>) ..." ; descriptive initialization message (e.g. "<ModPluginName>" = "New Vegas Bounties III") Place your "batch file" in the game root folder (where the "FalloutNV.exe" file is found). The filename begins with an "underscore" (_) so it will be sorted to the top of the file list.Edit: Replaced "<MainQuestName>" with "<ModPluginName>" without any file extension. Just used to coordinate mod index with plugin file for reference. Sorry about any confusion. While it would require some additional lines of code, consider using "GetCreatureType" instead if you can't get "GetIsCreature" to do the job. -Dubious- Edited December 27, 2017 by dubiousintent Link to comment Share on other sites More sharing options...
trashgarbage666 Posted December 27, 2017 Author Share Posted December 27, 2017 (edited) I think the problem is GetIsCreature and GetIsCreatureType doesn't like playing nice with the GameMode script block. Here's what I mean: ScriptName HeadshotAmmoSCRIPT BEGIN GameMode Ref rTarget Set rTarget to GetOwnerLastTarget If rTarget.GetIsCreature != 1 ForceActorValue Health 0 Else EndIf END ScriptName HeadshotAmmoSCRIPT BEGIN GameMode Ref rTarget Set rTarget to GetOwnerLastTarget If rTarget.GetIsCreatureType 6 != 1 ForceActorValue Health 0 Else EndIf END Neither of these scripts work. The first script should make my ammo 1-hit kill anything that isn't a creature, and the second script should 1-hit kill anything that isn't a robot, and yet the bullets indiscriminately kill everything they hit. Check out the Boxing Glove script from the vanilla game: scn BoxingGlovesFatigueOnHitScript ; Inflicts Fatigue damage on the target to temporarily knock it out. ; JES Begin OnHit Ref BoxingGloveTarget Set BoxingGloveTarget to GetOwnerLastTarget If (BoxingGloveTarget != PlayerRef) && (BoxingGloveTarget.GetIsCreatureType 6 != 1) BoxingGloveTarget.damageav Fatigue 16 Else BoxingGloveTarget.damageav Health 10 EndIf End This code is able to successfully differentiate between creatures, NPCs, and the player, and yet it does so within the OnHit script block. I'd gladly use OnHit for my code, but I read somewhere on the GECK wiki that the GetHitLocation command doesn't work inside OnHit. Is it possible to use multiple script blocks within the same script? If so, I could probably use OnHit to determine if the target's a creature, and GameMode to determine if the target got hit in the head. That could work... right? EDIT: Couldn't get it to work. So I had another Idea. I tried giving a super mutant a dummy "helmet" item and told the script to not insta-kill anything that has that item in its inventory. It didn't work either, which completely blows me away because I had no problem telling the script not to insta-kill someone wearing a helmet. I'm at a complete loss for what to do. Edited December 27, 2017 by punchbattle Link to comment Share on other sites More sharing options...
dubiousintent Posted December 28, 2017 Share Posted December 28, 2017 I think the key is in those notes you are recalling from the wiki about "GetHitLocation":This information is not available in the OnHit and OnHitWith script blocks, unlike GetLastHitCritical.This information is available in a UDF event handler script for OnHit and OnHitWithThis information is available in a UDF script for SetOnCriticalHitEventHandlerGetHitLocation won't work if used in a weapon's Object Effect, but will work if used in the weapon's Crit Effect.GetHitLocation will only return the correct value in a GameMode block in the frame that the reference is killed.The "BoxingGlove" script is not in a "GameMode" Block. Without looking, my guess would be it is called by an "EventHandler" (second bullet point). So you need to create a OnHit EventHandler "User Defined Function" (UDF) to call your script. -Dubious- Link to comment Share on other sites More sharing options...
trashgarbage666 Posted December 28, 2017 Author Share Posted December 28, 2017 Unfortunately, I think you might be right. It's unfortunate because I'm reading the UDF and Event Handling pages on the GECK wiki, and it's just ...completely out of my league. I don't even know where to begin. If you know how to set something like this up, could you walk me through it? Making this mod has been helping me de-stress, and and this point, I feel like my project has hit a wall. Link to comment Share on other sites More sharing options...
dubiousintent Posted December 28, 2017 Share Posted December 28, 2017 (edited) As for "walking you through it", suggest you read the series of NVSE+ tutorials by DoctaSax under the "Scripting" section of wiki "Getting started creating mods using GECK" article. Read the entire series as they build upon each other. While that will be useful, you are now getting fairly deep into "programming" for a non-programmer. The GECK wiki is primarily a list of functions and their syntax with some basic tutorials that just cover how to build game "assets". Not really anything about how to "write proper code" for scripts. You can teach yourself from online resources these days, but you may need to look up some "basic programming" guides elsewhere. (The earliest "command line" forms of the "Basic" programming language (not "Visual Basic") have all you need to understand scripting. Command prompt "batch files" or "shell scripts" as well.) NVSE just adds functionality (i.e. technical features such as new functions) that are missing from the game engine. Use of them presumes knowledge of basic programming (how to have code logic flow as desired). Mostly that is through the use of "If ... Else ... EndIf" blocks, but other features like "arrays" are less obvious. You could learn all you need to know for scripting in a single semester of a formal "introductory programming" language class. These are often available as "adult continuing education classes" or as part of community center programs. -Dubious- Edited December 28, 2017 by dubiousintent Link to comment Share on other sites More sharing options...
Mktavish Posted December 28, 2017 Share Posted December 28, 2017 (edited) So I had another Idea. I tried giving a super mutant a dummy "helmet" item and told the script to not insta-kill anything that has that item in its inventory. It didn't work either, which completely blows me away because I had no problem telling the script not to insta-kill someone wearing a helmet. I'm at a complete loss for what to do. I'm guessing for some reason the impact script execution / or the GetOwnerLastTarget , won't return subcategories of actor type or inventory.But you say it works for checking equipped slots.So since all humans will have something equipped in the upper body slot , and no creature ever will. How about adding " If GetEquippedObject 2 != 0 " ? But I was also thinking having another script that could use "ObjectUnderReticle" setting a variable ... in an actor or object effect.Then in your impact script use "GetScriptVariable"But that one might be kind of processor intensive ? Edited December 28, 2017 by Mktavish Link to comment Share on other sites More sharing options...
trashgarbage666 Posted December 28, 2017 Author Share Posted December 28, 2017 (edited) I'm guessing for some reason the impact script execution / or the GetOwnerLastTarget , won't return subcategories of actor type or inventory.But you say it works for checking equipped slots.So since all humans will have something equipped in the upper body slot , and no creature ever will. How about adding " If GetEquippedObject 2 != 0 " ? So after reading this, I thought "oh my god, that's a great idea! I finally get to move forward with my mod! I'm so excited!" and added it to my script right away... only to be stopped dead in the water immediately. The script won't save. It's acting like there's a typo or syntax error. There isn't. Honestly, I think it's not working just to spite me. I hate this. I hate it. I see no reason why your idea shouldn't work, and yet here we are. EDIT: Well, I know "GetEquipped (Form List) == 0" works because I've been using it to tell the script to ignore anyone wearing a helmet! So! I put together an armor / clothing Form List and told the script to only kill things wearing clothes or armor. It didn't work at first, so I changed how the script found its target from "GetOwnerLastTarget" to "Player.GetCombatTarget" and it started working just fine. So it's pretty much mission accomplished at this point? Kind of? I was sorta hoping the player could be killed by headshots as well, but Player.GetCombatTarget dictates that only NPCs shot by the player will be killed. I've been experimenting with stuff like (OwnerOfThis).GetCombatTarget, but haven't had any luck. Anyone have any ideas? Edited December 28, 2017 by punchbattle Link to comment Share on other sites More sharing options...
Mktavish Posted December 28, 2017 Share Posted December 28, 2017 Dang I thought it would at least save ... but it seems it doesn't like the ref instance of what "GetOwnerLastTarget" is returning. So I dug a little deeper with what you could pass besides "GetIsCreature" And "GetIsFormType" is at least saving ... although not sure it will give you the same problems as trying to exclude creatures. But here is what I was able to save. ~~~~~~~~~~~~~SCN ZZZMyBulletScript BEGIN GameMode Ref rTarget Set rTarget to GetOwnerLastTarget If rTarget.GetIsFormType 42 == 1 || rTarget.GetIsFormType 44 == 1 If (GetHitLocation == 1 || GetHitLocation == 2) && (rTarget.GetDead != 1) ForceActorValue Health 0 Else EndIf EndIf END~~~~~~~~~~~~~~ And here is the Int code list for form types http://geck.bethsoft.com/index.php?title=Form_Type_IDs Link to comment Share on other sites More sharing options...
trashgarbage666 Posted December 28, 2017 Author Share Posted December 28, 2017 (edited) I was actually able to get your previous suggestion to work perfectly! You might not have seen it, because I just kind of stealth edited my previous post to say so. However, I thought I'd give your new idea a try just to see if it had any notable pros or cons over the other method, and while it did manage to save, it wasn't able to differentiate between creatures and NPCs. But still! I wasn't even aware of Form Types, so it was helpful all the same! I just wanted to say thanks for all your help. Like I mentioned in a previous post, making mods has sort of become how I de-stress, and now that I'm past this problem I can continue doing that! Edited December 28, 2017 by punchbattle Link to comment Share on other sites More sharing options...
Recommended Posts