Auberginuspl Posted November 27, 2020 Author Share Posted November 27, 2020 So, I created the .esp using the above scripts. Spawned myself the debug pistol on a new character and went around the world killing animals that should have been affected by the perk. Surprisingly enough, it sort of worked. Sort of, because it affected only roughly a quarter of animals that I found. So.. despite the fact that I added pretty much every Creature from the AnimalFriendFaction to my Form List, only some of them are affected by the script, for whatever reason. For example, while domesticated Bighorners are affected (and do give the player the debuff upon killing them), wild Bighorners are not. Not a single coyote or gecko (except for a few Golden Geckos) I found was affected, but every Night Stalker was, including the Legendary variant. Every Brahmin I found was affected, including the hostile variant. Wild Molerats weren't affected, but Snuffles was. Giant rats weren't affected, except for two "Unnaturally Large Sized Rodents" found in the sewers. Viscious dogs weren't affected, but NCR and Legion dogs were. As you can see, it's very inconsistent and I'm trying to figure out why. I studied the case of coyotes that spawn around Goodsprings. Killing them doesn't give me the debuff. In G.E.C.K it seems that coyote spawners were objects VSpawnTier1CoyoteMed75, VSpawnTier1CoyoteMed50, and others that were NOT in the Animal Friend Faction, so I hadn't added them to my form list at first. Therefore, I went ahead and added those, as well as pretty much every relevant creature from the Actors>Creatures tab, so that every Actor entry that, for example, contains "Coyote" or "Bighorner" has been added into my form list. This, however, did nothing, and I am at a loss. How come some creatures are affected but others aren't? What might be causing this? I'd appreciate any suggestions because I don't know what to do... Thanks in advance. Link to comment Share on other sites More sharing options...
Auberginuspl Posted November 27, 2020 Author Share Posted November 27, 2020 Well, I suppose I found a workaround, but it involves manually adding scripts to a huge bulk of Actors that were unaffected by my original script, like GamerRick originally sugested. The original script still covers a lot of animals, including Legion Mongrels which already had a script attached to them so I wouldn't be able to add mine manually, so I guess it sort of works. I attached this script to every Coyote object I found: scn 111AnimalCrueltySCRIPT Begin OnDeath if player.hasperk AnimalFriend player.castimmediateonself AnimalFriendDebuff showmessage AnimalCrueltyMessage endif end And bam, it works as intended. I'm gonna try this with the rest of unaffected animals and see how it works. Thank you so much for your suggestions, GamerRick, you were extremely helpful! I might just accomplish what I wanted with my mod. But if you, or anybody else has any answers as to why my original script with the SetJohnnyOnDyingEventHandler function with the Form List with every animal in it didn't work for all animals, but only some of them, I'd like to hear em. Thanks all! Link to comment Share on other sites More sharing options...
Auberginuspl Posted November 27, 2020 Author Share Posted November 27, 2020 Sorry for being spammy. While I was manually attaching scripts to animals, I realized I want to also penalize the player for eating the meat of affected animals. I could do that by manually editing the Ingestibles themselves but since I'm using a mod that makes changes to these items (JSawyer), I figured to try and see if there's a way to implement this via scripting. I did a little test on Bighorner Meat: scn AnimalFoodDebuffQuest begin gamemode if Player.hasperk AnimalFriend if Player.IsSpellTargetAlt BighornerMeat player.castimmediateonself AnimalFriendDebuff showmessage AnimalCrueltyMessage endif endif end And it works, however, the message, as well as the debuff is being applied CONTINUOUSLY for as long as the base effect of the ingested meat is active. Is there a way to make it only fire ONCE upon consumption? I tried the OnMagicEffectHit but I don't think it works with consumables, only base effects. Any ideas? Thanks in advance... Link to comment Share on other sites More sharing options...
dubiousintent Posted November 27, 2020 Share Posted November 27, 2020 You need a "flag" variable to indicate you have already applied the debuff, and a condition for when the debuff is over. For ex: scn AnimalFoodDebuffQuest int iDoOnce begin gamemode if Player.hasperk AnimalFriend if Player.IsSpellTargetAlt BighornerMeat If iDoOnce == 0 player.castimmediateonself AnimalFriendDebuff Let iDoOnce := 1 showmessage AnimalCrueltyMessage EndIf Elseif iDoOnce <> 0 Let iDoOnce := 0 Else print "Player is not target of BigHornerMeat" endif endif end-Dubious- Link to comment Share on other sites More sharing options...
Auberginuspl Posted November 27, 2020 Author Share Posted November 27, 2020 Hey, that's fantastic Dubious, thank you very much for your help, it works perfectly. Well, almost, rarely it just won't apply the effect for no reason but the next time I eat the meat, it does, probably engine limitations or something. Either way, it's what I was looking for, fantastic! BTW: initially the script only fired once and that's it, I had to change Elseif iDoOnce <> 0 to Elseif iDoOnce == 1 and now it works. I started adding other meat items to your script, like so: if Player.IsSpellTargetAlt BighornerMeat > 0 || Player.IsSpellTargetAlt BigHornerSteak > 0 || Player.IsSpellTargetAlt CoyoteMeat > 0 || Player.IsSpellTargetAlt BrahminMeat > 0 || Player.IsSpellTargetAlt BrahminSteak > 0 Etcetera, but upon adding about a dozen of items, I get an error: Max Script line length (512 characters) exceeded. How I can add more items to the same script? I tried fiddling with elseif and else functions but I only end up breaking the script... Link to comment Share on other sites More sharing options...
dubiousintent Posted November 28, 2020 Share Posted November 28, 2020 (edited) Glad you figured out how to fix something I threw together off the top of my head without any testing. As for why the code isn't firing off in some instances, afraid that is something you have to determine by testing. Most likely some value you are expecting when the code in question starts is not "initialized" as you expect. Use debug print statements before conditional tests to see exactly what values are being passed at the moment. As you have found, there is a limit (i.e. 512 characters to include spaces) to how long a single line of code can extend before the engine chokes on it. In part this is because the engine evaluates the entire line of code before it then breaks down it down to testing the result of individual "test conditions". In the specific case of "compound conditionals" (all your " || (OR)" tests, these can also become a horror story when trying to determine which is causing a logic bomb. Note that when you are putting together a series of "compound conditions", it becomes essential to help the engine parse the line correctly, by grouping each "conditional" in it's own set of the appropriate "encapsulation" marks as described in 'TIP Best Practice Encapsulation Parens Brackets and Braces". Please see "TIP Basic conditional test syntax" and the other linked "Tips" in that one for a more extensive break down of the subject. However, for your situation consider this. You are only going to have one "SpellTarget" in effect at the moment in that script. So you just need to determine which target 'meat' is "in play". So rather than all those "OR" compound conditions you merely need to convert them into a series of "ElseIf" statements (the logic equivalent to the OR), so only one result for the specific "target meat" fires off. Ex: If Player.IsSpellTargetAlt BighornerMeat > 0 ; do something 1 ElseIf Player.IsSpellTargetAlt BigHornerSteak > 0 ; do something 2 ElseIf Player.IsSpellTargetAlt CoyoteMeat > 0 ; do something 3 ElseIf ; repeat condition logic as often as required ; do something as needed Else ; failsafe action to take when the target is not valid, which can include a "do nothing" comment EndIfWhile this seems like many lines of code, it is extremely efficient for the engine to process and usually is quicker than parsing out the equivalent compound conditional line as the engine skips everything remaining as soon as it finds the first "true" condition line. If you should hit upon a limit to the number of "elseif" statements you can have, that should not be a problem. Just start another "If ... ElseIf" series picking up from the next "target". You have already logically eliminated all the previously tested targets from consideration, and you are only going to hit upon a single "match" either way. You can improve efficiency even further by prioritizing your "target" conditions so the most likely are encountered first in the test chain. There are other ways to accomplish a similar process (walking through an array of "targets" using a "While" loop for instance), but they are just applying the same principle. -Dubious- Edited November 28, 2020 by dubiousintent Link to comment Share on other sites More sharing options...
GamerRick Posted November 28, 2020 Share Posted November 28, 2020 (edited) For the meat eating, you could add your new effect to their effect list, and it is contingent on the player having the perk and not already affected by that hidden spell you created.. Or you can add something to the creatures you want to cover to make them unique to the others, like adding a hammer or an unplayable weapon you create to their inventory. Then you have a single if condition to check in your script. In your case, checking for the faction should suffice though. I would like to know why the JohnnyGuitar function doesn't work. Maybe the author would like to know as well, so they can fix it if it's broken. Edited November 28, 2020 by GamerRick Link to comment Share on other sites More sharing options...
Auberginuspl Posted November 28, 2020 Author Share Posted November 28, 2020 Hey Dubious, once again thanks for helping me with my mod! I reworked my script like you showed me and it works as intended, though with a slight delay, which I'm assuming because the game processes scripts in ticks? Example: scn AnimalFoodDebuffQuestUncooked int iDoOnce begin gamemode if Player.hasperk AnimalFriend if Player.IsSpellTargetAlt NVGeckoMeat > 0 If iDoOnce == 0 player.castimmediateonself AnimalFriendDebuff Let iDoOnce := 1 showmessage AnimalCrueltyMessage Endif Elseif Player.IsSpellTargetAlt CoyoteMeat > 0 If iDoOnce == 0 player.castimmediateonself AnimalFriendDebuff Let iDoOnce := 1 showmessage AnimalCrueltyMessage Endif Elseif Player.IsSpellTargetAlt BighornerMeat > 0 If iDoOnce == 0 player.castimmediateonself AnimalFriendDebuff Let iDoOnce := 1 showmessage AnimalCrueltyMessage Endif [etc...] Elseif iDoOnce == 1 Let iDoOnce := 0 Else print "Player is not under effects of uncooked meat" endif endif end I don't know if it matters, but I decided to split it into three scripts, 1st handling uncooked meat, 2nd cooked meat, and 3rd more uncommon items containing meat and attached them to three separate quests. I think I noticed it kicking a little faster that way, but I might be wrong. Either way I'm really happy with this and very thankful for your assistance, I learned a lot thanks to you. The only minor problem I noticed is that the script takes about 2-5 seconds to recognize that the meat effects have worn out, so if the player consumes another meat item right after the previous' effect ended, the negative debuff won't be applied. But it's not an issue in my case because I extended the debuff's duration to be longer than any food item's. Great stuff. To GamerRick: yeah I wanted to add an effect directly to food items, but I decided against it because it would interfere with JSawyer mod's changes to these food items. As for the JohnnyGuitar thing, maybe it works well for single actors but has trouble processing large form lists? Mine had almost 300 entries in it, so maybe that was the problem, I'm not sure. Link to comment Share on other sites More sharing options...
GamerRick Posted November 28, 2020 Share Posted November 28, 2020 (edited) You want to make sure the player doesn't already have your spell, and I don't see the purpose of the DoOnce variable. How about this: scn AnimalFoodDebuffQuestUncooked begin gamemode if Player.hasperk AnimalFriend && player.IsSpellTargetAlt AnimalFriendDebuff == 0 if Player.IsSpellTargetAlt NVGeckoMeat > 0 player.castimmediateonself AnimalFriendDebuff showmessage AnimalCrueltyMessage Elseif Player.IsSpellTargetAlt CoyoteMeat > 0 player.castimmediateonself AnimalFriendDebuff showmessage AnimalCrueltyMessage [etc...] Else print "Player is not under effects of uncooked meat" endif endif end Edited November 28, 2020 by GamerRick Link to comment Share on other sites More sharing options...
GamerRick Posted November 29, 2020 Share Posted November 29, 2020 (edited) Even better: scn AnimalFoodDebuffQuestUncooked ref effect int num begin gamemode if Player.hasperk AnimalFriend && player.IsSpellTargetAlt AnimalFriendDebuff == 0 set num to player.GetNumActorEffects if num < 1 return endif while num > 0 let num -= 1 set effect to player.GetNthActorEffect num if effect IsInList MyFormListOfMeatEffects player.castimmediateonself AnimalFriendDebuff showmessage AnimalCrueltyMessage Set num to 9999 break endif loop if num != 9999 print "Player is not under effects of uncooked meat" endif endif end Edited November 29, 2020 by GamerRick Link to comment Share on other sites More sharing options...
Recommended Posts