Jump to content
⚠ Known Issue: Media on User Profiles ×

timtimman

Members
  • Posts

    32
  • Joined

  • Last visited

Everything posted by timtimman

  1. Yes, 1.10.40 came with large enough changes that it broke even though he tried to make it version independent. He is aware and we'll just patiently wait. Since this isn't an "official" mod of his, it doesn't get the same priority :)
  2. Yep, minor code screw-up. "Install" is a function, not an event. Just changing it will make it work. Changed the original.
  3. ; Save the script as "##########.psc" in /Data/Scripts/Source/User/ ; In the CK compile the script: Gameplay>Papyrus Script Manager. Find script, rightclick compile ; Create a new quest. Go to Scripts Tab and add script, find it and add the keyword/formlist you chose to make ScriptName ########## extends Quest ; Replace this with the name of what you name your script FormList Property WorkshopMenuMain Auto Const ;;; Want to use a single menu, create a recipe filter keyword ;;; Keyword Property %%%%%%%%%%%%%% Auto Const ; Replace with the name of the keyword you created ;;; Want to use a menu with submenues, create a formlist ;;; Formlist Property %%%%%%%%%%%%%% Auto Const ; Replace with the name of the formlist you created Event OnQuestInit() RegisterForRemoteEvent(Game.GetPlayer(), "OnPlayerLoadGame") Install() EndEvent Event Actor.OnPlayerLoadGame(Actor akActorRef) Install() EndEvent Function Install() WorkshopMenuMain.AddForm(%%%%%%%%%%%%%) ; Name of the created Keyword or Formlist you chose to make above EndFunction Function Uninstall() {Call this uninstall function using your uninstall chem, holotape etc} WorkshopMenuMain.RemoveAddedForm(%%%%%%%%%%%%%) ; Name of the created Keyword or Formlist you chose to make above Stop() EndFunction Edit: A the Install function was wrongly written as an event. Fixed!
  4. I didn't think about packing it in a ba2 archive as I assumed it would do the same, which was basing my arguments on faulty knowledge. But as you stated, deactivating the mod makes it unable to access the script, thereby cleaning up. I may have used some terminology the wrong way, and I do apologize my ignorance on the matter. I do appreciate you taking the time to write what you have, just wish you would write it in a slightly kinder way. Anyway, a big thank you!
  5. Please, before moving to personal attacks you should: Actually read what the person not agreeing with you is saying, and understand it (or at least try to, I can be unclear sometimes) Maybe do another test (there's always a possibility you overlooked something).So first things first, the case I mainly made was that if the mod user were to disable/remove the mod without uninstalling (which most will do, unless we're disagreeing here too) your code will fail and produce errors. Also, with your current uninstall function, your code will fail and produce errors because you're not stopping the quest (when the game's loaded again). You are correct in that a stopped quest automatically unregistered from all registered events, I'm not arguing with your here. However, the issue that arises has nothing to do with how the threading system works, but all to do with how the saving of scripts works. This is mentioned here if I recall correctly: Save File Notes (Papyrus) (the current site is down now however, and it isn't cached). An active script is saved in the save file when a save is requested at the current position in the file so that it can continue exactly where it was (even mid line) when the game's loaded. And since registering for an event causes the script to be latent, it will be saved. However, if the mod is disabled, the reference to the Quest holding the script is None, and thereby it'll have NO WAY to exit itself. persist and continually reload itself every time (since that's what you've resisted for). So, do this very simple test script attached to a quest: ScriptName DerpTest extends Quest Event OnQuestInit() RegisterForRemoteEvent(Game.GetPlayer(), "OnPlayerLoadGame") EndEvent ; This will be called every time the game loads, even if the it's loaded without the mod Event Actor.OnPlayerLoadGame(Actor akSender) If (Game.IsPluginInstalled("DerpTest.esp")) ; <-- Name it to whatever the .esp it named Debug.Trace("Game Loaded with the mod active, no worries") Else Debug.Trace("Loaded WITHOUT mod enabled. Maybe try to stop Quest?") ;; Uncommment below if you want... ; Stop() ; Debug.Trace("Can't call Stop() on None; failed") EndIf EndEvent Make the quest Start Game Enabled and Read Once (which is default) and do the following. Start the game with the mod enabled. Save the game and reload it See that the "Game Loaded with the mod active, no worries" message shows up in the log Save again Close the game and disable the mod (just disable for now, this matters) Open up the game and see that the "Loaded WITHOUT mod enabled. Maybe try to stop Quest?" message shows up, optionally an error relating to Stop() should you uncomment that Save again (cus why not?) Close and open and load it again (same message repeats, because the Papyrus script state is saved) Close again and delete the .pex file (this is used to recreate the saved Papyrus script state, so no, the script isn't truly saved in the saved game; just instructions on how to create it) Open and load the game again, (see that it spits out a bunch of errors about not being able to recreate the Papyrus object because of missing class whatever) Save here and reload (NOW, finally the error messages will go away, but I don't know what damage it might have done in the process. Maybe all script saved stuff has been messed up)Here is the packed mod with script for the above test: http://s000.tinyupload.com/index.php?file_id=00688330215583553733 Edit: Just saw your edit now, and you should really read through the Save File Notes (Papyrus) I linked above. The results of your test situations are mentioned there. And gah! It was just up and now it's down again. You can look at the Skyrim page for it here, which basically say the same thing.
  6. You are correct in the Revert() case, and I mentioned this under my post. Though your code will work, it's not a good way to do due to leaving the script in the save game and not giving it a way to exit. And if the mod user ever deactivates the mod (even if they use the uninstall) the code will be there and continue to fail each time the player loads the game (and enabling the mod again won't remedy this). Just adding Stop() at the end of the uninstall() function should remedy this if the user were to use the function (and that's a big if). The proper way to do it would be to make a Magic effect and attach a script with the event and have it call your function. To deliver it, you have to create a Magic Effect (the one with the script), a Spell (in the form of an ability) and a Perk (to add to the player) in the CK. The perk adds the ability spell, which applies the magic effect, upon which the script and thereby function is run. The script should check to see if your mod is installed first (using IsPluginInstalled) and if it's not, Dispel itself and RemovePerk; otherwise just run your code (which I find is easiest done by starting another quest will all your scripts etc.) The Init quest should just add the perk to the actor and start the "DoerQuest" and then stop itself (as should the "DoerQuest"). With that method you don't have any saved stuff in-game even if the mod user decides to disable/remove the mod without running the Uninstall (which most users will).
  7. I think we are all self taught when it comes to Papyrus. Don't let that hold you back and give up! You shouldn't use the 'native' flag as we cannot make anything native. The native flag on a script tells the compiler that you've added new events (which you won't be able to use). And native scripts won't let you use properties or variables (not storing information) as they are intended to be extended (and never actually attached to an object). You have to extend the script which events you want to use (or one with inheritance of the script with the event). As for the function you wish to achieve. Just make a check on your effect to see if one of the armor pieces was unequipped (attached magiceffects receives events from the actor it's attached to), in which case Dispel the effect. If your not leaving it as is, try to implement that. If you don't succeed, return for more help! Happy modding!
  8. To let everyone searching here know what fixed this particular issue: The BSLightingShaderProperty of the TriShape he'd added to the model was faulty. The following was done to fix it: The Skyrim Shader Type was changed form "Default" to "Environment Map".The Unknown Float 1 to "<float_max>"The bottom values, wetness and such to -1.0 (basically mimicked the working BSLigh.. nodes).A texture set was added and linked it (this is NOT necessary, you can use only materials if you wish). Changed the number to 10 (from six): you have to do "Spells>Sanitize>Reorder Link Arrays" for this to take.The blocks were reordered (Spells>Sanitize>Reorder blocks) and the .nif was saved saved.
  9. Basically, you have 2 approaches. Making a single tier menu (no sub-menus) which requires only a recipe-filter keyword.Making a multiple tier menu (and custom menu icon). This requires a FormList, and at least 2 recipe-filter keywords. (more keywords and formlists for sub-menus) For a single menu you make a new keyword and set the type to 'recipe-filter', and write your mod menu name. To add object to it you just put the keyword in the Recipe-Filter keywords in you Constructable Objects for your objects. For a menu with submenus/custom icon. You make a Formlist and add the first recipe-filter keyword to it at the top with it's name (to this you also link any art-object icon). Then you add the second keyword (or a new formlist) which will become the sub-menu. Just link the constructable objects with these recipe-filter keywords instead for them to appear in their respective menus. To add it to the game you'll have to make a Quest to run when the game is first loaded (default values: Start-Game enabled, and Run Once). To it you add the following script, and pass in your keyword/formlist, and the main-menu formlist. Scriptname <ModName>_Init extends Quest FormList Property WorkshopMenuMain Auto Const ; Single menu keyword Keyword Property <ModName_MenuRecipeFilterKeyword> Auto Const ; Menu with sub-menus/custom icon formlist Formlist Property <ModName_MenuFormlist> Auto Const Event OnQuestInit() WorkshopMenuMain.AddForm(Keyword or Formlist) ; which ever you wish to use Stop() ; No use having the quest running anymore EndEvent I hope that's sufficient with information to get you going with it. You should really add a Magic Effect on the actor with the event OnPlayerLoadGame() and check if your mod is still enabled, if not: call Revert(Your keyword or Formlist) to remove it from the menu. Or just implement a "uninstall" holotape or chem. But that's a different story for another time.
  10. There are quite a few things to look out for with .nif's. First is to always re-order blocks before a save (Spells>Sanitize>Re-order blocks). That is the major one. But there are a bunch of subtle things that will make the CK crash. I can't really help you from just an image if it isn't the blocks. But if you sent the .nif I could probably fix it for you and let you know what did it (played a lot with them).
  11. Well, in the case of Magic Effects and Quests (maybe some other once I can't think of now) then the last OnEffectFinish is unnecessary then. But in all other cases, my approach is the "correct" one, and should be included for good measure (even if not necessary in this case). As for 'const', I've apparently got that ass backwards. I'll redact that part in my comment to avoid further confusion. And thanks for pointing it out so nicely with references!
  12. This is not a very good practice, even if it does work. When the effect finishes you just remove the layer you created and not just change the settings. Also, making the properties 'const' will make them stick the way they are the first time the mod loaded, and not change even if you were to update the mod with new values (if a user made a save with the current mod version). Got it ass backwards on that part, corrected by steve40. 'const' cannot be modified by scripts, only in the CK (editor), See wiki Const. I suggest your script be like this: ("fixed" your first check) Scriptname ARMA_DisableSprintEffectScript extends ActiveMagicEffect Group Settings bool Property DisableSprinting auto bool Property DisableRunning auto EndGroup InputEnableLayer inputLayer Event OnEffectStart(Actor akTarget, Actor akCaster) inputLayer = InputEnableLayer.Create() if DisableRunning inputLayer.EnableRunning(false) inputLayer.EnableSprinting(false) ; If we disable running, we have to disable sprinting as well elseIf DisableSprinting inputLayer.EnableSprinting(false) endIf EndEvent Event OnEffectFinish(Actor akTarget, Actor akCaster) inputLayer.Delete() inputLayer = None EndEvent Edit: corrected my wrongful remark on how 'const' properties work.
  13. Modular Settlement Machinery aims to do just this. It just released as proof-of-concept: http://www.nexusmods.com/fallout4/mods/18968
  14. You are correct, couldn't care to fix it yourself? My post above is now correct.
  15. Good that the explanation sufficed (I felt it was a bit lacking). And please do let me know if it works, as I haven't bothered testing it myself. If you have any other questions, feel free to ask!
  16. If you actually break it down it's not very complicated. The var[]'s are just to allow sending parameters with the custom events. And now that I think about it, I derped a bit on the Classification events, as they're sent every time one is changed. It would be better to only send if it was the previous one. I'll fix that in an hour or so, don't quite have the time now. But it should work as is anyway, it's just that say WeatherRainy will be sent with akArgs[0] == false even if weather just transitioned from pleasant to cloudy. It doesn't break anything but is a bit confusing. Edit: This is the neatest I can get it at the moment, am pretty tired. Still not tested in-game but compiles and should work. ; Script by timtimman, http://www.nexusmods.com/games/users/34480070/ ; Use however you'd like but be kind and give some sort of credit Scriptname WeatherEventScript extends Quest { A quest script which sends the Custom Event WeatherChange } Float Property UpdateTime = 5.0 Auto ; Time between updates, 5 seconds should be enough Weather LastWeather ; Always sent on weather change with two arguments: akArgs[0] == Weather newWeather, akArgs[1] == Weather oldWeather. ; May need to explicitly cast them as Weather on the recieving end to use their properties and methods CustomEvent WeatherChange ; Sent if a weather classification has changed, sent with one argument akArgs[0] == bool isCurrent CustomEvent WeatherUnclassified ; Classification == -1 CustomEvent WeatherPlesant ; Classification == 0 CustomEvent WeatherRainy ; Classification == 1 CustomEvent WeatherCloudy ; Classification == 2 CustomEvent WeatherSnow ; Classification == 3 Event OnQuestInit() LastWeather = Weather.GetCurrentWeather() StartTimer(UpdateTime, 0) EndEvent Event OnTimer(Int aiTimerID) If (aiTimerID == 0) Weather currentWeather = Weather.GetCurrentWeather() If (currentWeather != LastWeather) SendWeatherEvents(currentWeather, lastWeather) EndIf LastWeather = currentWeather StartTimer(UpdateTime, 0) EndIf EndEvent Function SendWeatherEvents(Weather newWeather, Weather oldWeather) Int[] classification = new Int[2] classification[0] = oldWeather.GetClassification() classification[1] = newWeather.GetClassification() If (classification[0] != classification[1]) Var[] akArgs = new Var[1] int i = 0 While (i < 2) akArgs[0] = i as Bool If (classification[i] == -1) SendCustomEvent("WeatherUnclassified", akArgs) ElseIf (classification[i] == 0) SendCustomEvent("WeatherPlesant", akArgs) ElseIf (classification[i] == 1) SendCustomEvent("WeatherRainy", akArgs) ElseIf (classification[i] == 2) SendCustomEvent("WeatherCloudy", akArgs) ElseIf (classification[i] == 3) SendCustomEvent("WeatherSnow", akArgs) EndIf i += 1 EndWhile EndIf Var[] akArgs = new Var[2] akArgs[0] = newWeather akArgs[1] = oldWeather SendCustomEvent("WeatherChange", akArgs) EndFunction Edit 2: made a big dummy and forgot the repeated call StartTimer(UpdateTime, 0) in the OnTimer which actually makes the script continually check. The above version is correct but not the first I posted. Edit 3: did first now see that you wanted to understand how it works, with is good! I'll try to keep it simple (should be easy enough as it is). I wrote the script mostly because I usually learn best by seeing a working example. Anyway; This script uses a timer (StartTimer function & OnTimer event), and when it finishes (the event is called) it checks to see if the current weather is any different form last time it checked (stored in variable LastWeather). If there is a difference, it proceeds to the SendWeatherEvents function which sends out the custom events. A custom event is sent just as is, or with arguments (this is where the Vars come in). The function SendCustomEvent takes the name of the CustomEvent as a raw string (not through a variable) and an optional arguments array in the form of a Var[]. This array need to have it's size declared and be filled manually. The Var can take any type (not structs or arrays) and will remember the type. But in order to use Script functions you need to cast it manually on the receiving end, or the compiler will complain and fail. I hope that clears some stuff up. Love to know in what context you'll put it to use. Edit 4: made a rookie mistake pointed out by cadpnq, infinite loop! Just forgot to add 'i += 1' in the While loop. Fixed!
  17. Here's a script that should work if you want to use custom events. It compiles but I haven't tested it in-game; it should work however. ; Script by timtimman, http://www.nexusmods.com/games/users/34480070/ ; Use however you'd like but be kind and give some sort of credit Scriptname WeatherEventScript extends Quest { A quest script which sends the Custom Event WeatherChange } Float Property UpdateTime = 5.0 Auto ; Time between updates, 5 seconds should be enough Weather LastWeather ; Always sent on weather change with two arguments: akArgs[0] == Weather newWeather, akArgs[1] == Weather oldWeather. ; May need to explicitly cast them as Weather on the recieving end to use their properties and methods CustomEvent WeatherChange ; Sent if a weather classification has changed, sent with one argument akArgs[0] == bool isCurrent CustomEvent WeatherUnclassified ; Classification == -1 CustomEvent WeatherPlesant ; Classification == 0 CustomEvent WeatherRainy ; Classification == 1 CustomEvent WeatherCloudy ; Classification == 2 CustomEvent WeatherSnow ; Classification == 3 Event OnQuestInit() LastWeather = Weather.GetCurrentWeather() StartTimer(UpdateTime, 0) EndEvent Event OnTimer(Int aiTimerID) If (aiTimerID == 0) Weather currentWeather = Weather.GetCurrentWeather() If (currentWeather != LastWeather) SendWeatherEvents(currentWeather, lastWeather) EndIf LastWeather = currentWeather EndIf EndEvent Function SendWeatherEvents(Weather newWeather, Weather oldWeather) Int classification = newWeather.GetClassification() If (classification != oldWeather.GetClassification()) Var[] unclassArgs = new Var[1] unclassArgs[0] = false Var[] pleasantArgs = new Var[1] pleasantArgs[0] = false Var[] rainyArgs = new Var[1] rainyArgs[0] = false Var[] cloudyArgs = new Var[1] cloudyArgs[0] = false Var[] snowArgs = new Var[1] snowArgs[0] = false If (classification == -1) unclassArgs[0] = true ElseIf (classification == 0) pleasantArgs[0] = true ElseIf (classification == 1) rainyArgs[0] = true ElseIf (classification == 2) cloudyArgs[0] = true ElseIf (classification == 3) snowArgs[0] = true EndIf SendCustomEvent("WeatherUnclassified", unclassArgs) SendCustomEvent("WeatherPlesant", pleasantArgs) SendCustomEvent("WeatherRainy", rainyArgs) SendCustomEvent("WeatherCloudy", cloudyArgs) SendCustomEvent("WeatherSnow", snowArgs) EndIf Var[] akArgs = new Var[2] akArgs[0] = newWeather akArgs[1] = oldWeather SendCustomEvent("WeatherChange", akArgs) EndFunction Just attach it to a quest and then pass the quest in as a property (WeatherEventScript Property WeatherEvents Auto) to whichever script you want to receive the custom events. Then just register for it using RegisterForCustomEvent(WeatherEvents, "WeatherRainy"), or which other event you'd like to receive. And somewhere write: Event WeatherEventScript.WeatherRainy(WeatherEventScript akSender, Var[] akArgs) and you should be good to go.
  18. For anyone who's interested, these are the codes the 2 upcoming tests we'll conduct. Test 1: http://pastebin.com/RT3yBDzM (based on if the MineStartThrow animation name) Test 2: http://pastebin.com/9eidHiC5 (an improved variation of the check ammo count script) <== money's on this one Some tweaking may be necessary, but they show the general concept. If test 1 works it will be shortened somewhat depending on order of execution etc. Edit: Found an error on line 61 (how remote events are received) of test 2. Due to this lines 61 and 62 are changed to: Event ObjectReference.OnItemRemoved(Actor akSender, Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) If (akSender == Game.GetPlayer() && akBaseItem == RDE_Mine.GetAmmo()) Also; Test 3: http://pastebin.com/FHLsy2Nk (a hack attempt to sort animation events)
  19. @Galvon94 That's one approach I've thought of taking, but avoided it as it would be easier to just copy and modify an already existing one. That and you apparently can't attach scripts to projectiles... But anything using Custom Events would be much better as the FindAllRef... function is very costly computational wise. @Reneer Will make sure to test those! If you've extracted all animation variables, I'd love to take a look :smile: You code example was my next thing to test. I just hope the remove ammo is completed before the animation event is sent out. Or can at least be given enough time using Wait(0.1). The issue still remains that the mines will be triggered if the player throws a grenade, while also having the detonator equipped, and this check is needed for all ammo. And, this makes it all more computationally heavy. One solution could be to not allow the detonator to be equipped with anything other than the RDE_Mines. I don't know if that can easily be set in the CK or if I also need to register a remote event on the actor to check so that this will unequip if any other throwable is equipped. Still, it's very sucky! For good measure though you should put your if statement before the FindAllRef... function since if it's false, the result of the search won't be needed, and hence saving computation. Thank's for the feedback, both of you! Will return once more testing has been performed, regardless of failure or success.
  20. Though about it some more, your line of code won't work unfortunately. The issue apparently is that even though I register for animation event on this object, what's returned as akSource is the PC. Meaning that we'll get all WeaponFire animationevents. And hence, if you throw a mine (can be equipped at the same time), which is also sends a WeaponFire event, the result is that it blows up in your face. Checking to see if the current item is equipped wouldn't be necessary as I wouldn't receive the event unless it was equipped, where I register for it. Checking to see that our mines aren't equipped would work, but that won't allow us to place mines and detonate them without unequipping the mines, which we'd like to avoid. Some of the stuff we've tried to make it work the way we want, which unfortunately doesn't work. Sorting to see if the akSource came from out object in all possible ways; failed due to animation events being passed form the player actor. Tried overwriting the Fire function on weapon; didn't work as it probably isn't triggered when actually firing weapons. Right now my though of how to make it work is to only allow one of the items detonator/mines be equipped at a time. Any more suggestions are welcome!
  21. Yeah, we figured that out. Thanks for your input, but we'd like to be able to have both objects equipped at the same time. I have a few ideas on how to solve it which we'll get working on hopefully tonight. But this will be our last resort as we'll know it'll work. Will update on how we solved it if it's different than this. Thanks!
  22. Ok. There are, unfortunately, several things which are available only to the CK and can't be set/changed using script. Layers could be one of them.
  23. Sorry, I'm phrasing was a bit off. I don't think ObjectReference would get a hold of that script. As you pointed out, that would be very weird. But you could perhaps get hold of it and use it in script, by the means of setting the object which has the CloakingScript on it: ObjectReference Property ObjectWhichHasScript Auto. And maybe using that, (since you need a reference) casting it as a CloakingScript: (ObjectWhichHasScript as CloakingScript). I assume you've check your spelling, so it isn't an annoying mistake like that.. Both name of the file and name said in the file. Cloaking and Claoking might be a simple typo to make. Right now otherwise, I'm out of ideas. Hope some of them has been helpful at least.
  24. From the looks of it (not familiar with the CK), it might be that it's defined as Const, which might not let you do that. Or you've written it in the wrong order. As far as I know it should be written as: CloakingScript Property CloakControllerLink Auto Const ? Or maybe it's just the CK failing it's inheritance. If it's just pure ScriptObject inheritance all the way, you wouldn't be able to pick an object (I think). Try an ObjectReference as property, and the item should have the CloakingScript attached to it. Then you should be able to use myRef.EndCloakEffect() or maybe (myRef as CloakingScript).EndCloakEffect(). I could be wrong, but hope it helps.
×
×
  • Create New...