Magicockerel Posted April 16, 2017 Share Posted April 16, 2017 I am wanting to create a workbench alias so that I can attach a script to each of the workbenches that you find throughout the game world. Attaching a script to each of the workbenches allows me to make use of the OnWorkshop... event variants at each of the settlements. I have attached a previous incarnation of the script directly to the workbench forms, and the script's worked fine. However, I'd rather not edit vanilla forms, so I thought creating an alias would be the go. My issue is that I can't see the script running at all (which I can tell from notifications that are displayed at certain events), so I'm assuming that I haven't set the alias up correctly. I have only done quite limited experimenting with aliases in the past, so that's very likely the case. As shown below, I have attempted to alias the various workbenches that I've put in a couple form lists. I'll note that I am using the same form lists to add an activator to the workshop workbenches (which is working fine), so there's nothing wrong with the form lists themselves (to my knowledge). I've only added the base game workbenches to the form lists to ensure that there are no DLC requirements. However, I've added any DLC workbenches to those form lists via script if those .esm files are loaded, so there shouldn't be any issues there. To put things simply, I need help creating an alias so that I can attach scripts to the various workshop workbenches in the game. http://i.imgur.com/yZs27Uy.png The mod in its current state can be found in the following dropbox link. It's in a relatively complete state, as there's really only bug testing left to do (this being just one of them). For some context, it's version 2 of my Workbench Control Panel mod. Any help would be appreciated. Link to comment Share on other sites More sharing options...
vkz89q Posted April 17, 2017 Share Posted April 17, 2017 When are you starting your quest? That's when the alias is filled. If it's start game enabled and workbench isn't in loaded area, it will be none. You can do ref collection alias with only one condition: GetIsID WorkShopWorkBench. Then do SQV your quest in console and you see all workbenches in your alias(should be 28 in vanilla game?). If something is missing, you might need additional aliases/conditions for some workbenches. Or you can just use those form lists you made. You can put max initial count high as you want, it will fill up to that point. You can put 50 and the game finds 28, it will not fail because of that. Just don't do Allow Reuse in quest or you can get same workbench several times. I actually just tested it, and with only GetIsID WorkSHopWorkBench, max initial count 50, nothing ticked in settings, and it lists 28 ref aliases in the collection. Link to comment Share on other sites More sharing options...
Magicockerel Posted April 17, 2017 Author Share Posted April 17, 2017 Hey, thanks for the response. The save-game did actually start right next to the Sanctuary workbench, so the In Loaded Area flag didn't cause any issues. I originally didn't have that box ticked, but I ended up messing around with a few things because I was running out of ideas. The quest itself starts enabled with the game. I have only ever messed around with reference aliases, and never with reference collection aliases. Am I correct in assuming that the only real advantage to creating a reference collection alias over a reference alias is that you don't need to create a new reference alias for each reference that you want to keep track of? That is, I don't need to create 28 reference aliases for each of the WorkshopWorkbenches in the vanilla game (Workbench0, Workbench1, ..., Workbench27)? Using the SQV 07000F9C console command (0x000F9C being the quest FormID) reveals that both the reference alias and the reference collection alias have correctly registered each of the workshop references (that are linked to the WorkshopWorkbench containers). That is, it returns the FormID's of SanctuaryWorkshopREF (010250FE), RedRocketWorkshopREF (01054BAE), etc. However, I've had no luck whatsoever getting any feedback from the script that I've attached to either the reference alias or the reference collection aliases. I've added Debug.Notifications to each of the various OnWorkshop... events that I'm using, and I even added the OnActivate() event to the script, to see if I could trigger anything by activating the workbench. I haven't been able to trigger any of the notifications that I've embedded in the script, so there's still something wrong somewhere. The OnWorkshop... events are apparently sent to the workshop reference. Considering the reference collection alias is keeping track of each of the workshop references, the events should be triggered, but aren't. Another issue I'm having with the reference collection alias is the use of the Self.GetReference() function. I can't see any equivalent function on this page. I'm sure that there's some way that I can achieve the same functionality in the script that I've attached to the reference collection alias, but I haven't been able to find it so far. At the moment I've just got that section of the script commented out, because the script functions fine without it. However, I will need to resolve this issue before I release the mod. Link to comment Share on other sites More sharing options...
vkz89q Posted April 17, 2017 Share Posted April 17, 2017 (edited) Hmmh, I have only used ref collection with actors. I have a script where I need to do something when actor from collection dies.. and this is how I "identify" which one is it: Event OnDying(ObjectReference AkSenderRef, Actor akKiller) int index = Self.Find(akSenderRef) Actor tempActor = Self.GetAt(index) as Actor ;do stuff to tempActor endEvent Self <- means the whole alias collection in this case so it finds the akSenderRef from the collection. So yes, you are correct that the only reason to use ref collection is to make it easier if you have lot of aliases. But maybe it's not good in this case.. but reading https://www.creationkit.com/fallout4/index.php?title=RefCollectionAlias_Script , I can see it should work same way with OnActivate. I guess there might be something wrong with your script? Maybe you could post just the script in code tag? I don't have experience with workshops, so I can't propably help more than this.. but maybe someone else can. Edited April 17, 2017 by vkz89q Link to comment Share on other sites More sharing options...
Magicockerel Posted April 17, 2017 Author Share Posted April 17, 2017 (edited) Oh, I wasn't aware that the reference collection alias functioned as an array. Thanks, that solves that issue. Here's what the script currently looks like. It compiles fine, but I don't get any notifications when I trigger those events in-game. I'll have a look at making those edits to the Self.GetReference() sections of the script shortly. I haven't made them prior to making this post as solving this issue won't fix whatever's wrong with how I've created these aliases. I've provided the mod as a whole in a dropbox link in the first post, as it was when I first made this thread. [code=auto:0]ScriptName WCP_QUST_Workbench_RefCollAlias Extends RefCollectionAlias ; ========== ; Properties ; ========== ; -------------------- ; Auto Const Mandatory ; -------------------- Actor Property PlayerRef Auto Const Mandatory ActorValue Property Food Auto Const Mandatory ActorValue Property Safety Auto Const Mandatory ActorValue Property Water Auto Const Mandatory GlobalVariable Property WCP_GLOB_DisplayNotifications Auto Const Mandatory Keyword Property WorkshopLinkCenter Auto Const Mandatory Keyword Property WorkshopLinkContainer Auto Const Mandatory Keyword Property WorkshopLinkSandbox Auto Const Mandatory Keyword Property WorkshopLinkSpawn Auto Const Mandatory WCP_QUST_Housekeeping_Script Property WCP_QUST_Housekeeping Auto Const Mandatory WorkshopParentScript Property WorkshopParent Auto Const Mandatory ; ====== ; Events ; ====== Event OnActivate(ObjectReference akSenderRef, ObjectReference akActionRef) If (akActionRef == PlayerRef) Debug.Notification(asNotificationText = "Hello World!") EndIf Debug.Notification(asNotificationText = "Derp") EndEvent Auto State Disabled ; Do nothing EndState State Busy ; Do nothing EndState State Enabled ; Build Mode Entered or Exited Event OnWorkshopMode(ObjectReference akSenderRef, Bool aStart) ; --------- ; Variables ; --------- Bool BuildMode Bool Repaired ; ---------- ; Operations ; ---------- Debug.Notification(asNotificationText = "OnWorkshopMode") GoToState("Busy") BuildMode = True Repaired = False ConditionalSettlementAttacks(BuildMode, Repaired, None) GoToState("Enabled") EndEvent ; Workshop Object Scrapped or Stored Event OnWorkshopObjectDestroyed(ObjectReference akSenderRef, ObjectReference akActionRef) ; --------- ; Variables ; --------- Bool BuildMode Bool Repaired ; ---------- ; Operations ; ---------- Debug.Notification(asNotificationText = "OnWorkshopObjectDestroyed") GoToState("Busy") BuildMode = False Repaired = False ConditionalSettlementAttacks(BuildMode, Repaired, akActionRef) GoToState("Enabled") EndEvent ; Workshop Object Constructed Event OnWorkshopObjectPlaced(ObjectReference akSenderRef, ObjectReference akReference) ; --------- ; Variables ; --------- Bool BuildMode Bool Repaired ; ---------- ; Operations ; ---------- Debug.Notification(asNotificationText = "OnWorkshopObjectPlaced") GoToState("Busy") BuildMode = False Repaired = False ConditionalSettlementAttacks(BuildMode, Repaired, akReference) GoToState("Enabled") EndEvent ; Workshop Object Repaired Event OnWorkshopObjectRepaired(ObjectReference akSenderRef, ObjectReference akReference) ; --------- ; Variables ; --------- Bool BuildMode Bool Repaired ; ---------- ; Operations ; ---------- Debug.Notification(asNotificationText = "OnWorkshopObjectRepaired") GoToState("Busy") BuildMode = False Repaired = True ConditionalSettlementAttacks(BuildMode, Repaired, akReference) GoToState("Enabled") EndEvent EndState ; ========= ; Functions ; ========= Bool Function IsWorkshopSafe(Bool BuildMode, Bool DisplayNotifications, Bool Repaired, Int Index, ObjectReference ConstructableObject) ; --------- ; Variables ; --------- Int FoodCount Int RequiredSafetyCount Int SafetyCount Int WaterCount ; ---------- ; Operations ; ---------- FoodCount = WorkshopParent.Workshops[Index].GetValue(akAV = Food) As Int SafetyCount = WorkshopParent.Workshops[Index].GetValue(akAV = Safety) As Int WaterCount = WorkshopParent.Workshops[Index].GetValue(akAV = Water) As Int ; As the repaired event does not include the attributes of the repaired constructable object in the sum If (Repaired == True) FoodCount += ConstructableObject.GetValue(akAV = Food) As Int WaterCount += ConstructableObject.GetValue(akAV = Water) As Int SafetyCount += ConstructableObject.GetValue(akAV = Safety) As Int EndIf RequiredSafetyCount = WCP_QUST_Housekeeping.FoodMultiplier*FoodCount+WCP_QUST_Housekeeping.WaterMultiplier*WaterCount If (SafetyCount >= RequiredSafetyCount) ; The workshop has sufficient defense to scare off raiders If (WorkshopParent.Workshops[Index].AllowAttacks == True) WorkshopParent.Workshops[Index].AllowAttacks = False Return True EndIf ElseIf (SafetyCount < RequiredSafetyCount) ; The workshop has insufficient defense to scare off raiders If (DisplayNotifications == True) If (BuildMode == False) If (ConstructableObject.GetValue(akAV = Food) > 0 || ConstructableObject.GetValue(akAV = Safety) > 0 || ConstructableObject.GetValue(akAV = Water) > 0) Debug.Notification(asNotificationText = "Required Defense = " + RequiredSafetyCount + "\nDefense Deficit = " + (RequiredSafetyCount-SafetyCount)) EndIf EndIf EndIf If (WorkshopParent.Workshops[Index].AllowAttacks == False) WorkshopParent.Workshops[Index].AllowAttacks = True Return True EndIf EndIf EndFunction Function ConditionalSettlementAttacks(Bool BuildMode, Bool Repaired, ObjectReference ConstructableObject) ; --------- ; Variables ; --------- Bool StateChanged Bool DisplayNotifications Int Index ; ---------- ; Operations ; ---------- Index = GetCurrentWorkshopIndex() DisplayNotifications = WCP_GLOB_DisplayNotifications.GetValue() As Bool If (WCP_QUST_Housekeeping.DefaultConditionalSettlementAttacksState[Index] == True) StateChanged = IsWorkshopSafe(BuildMode, DisplayNotifications, Repaired, Index, ConstructableObject) ElseIf (WCP_QUST_Housekeeping.DefaultConditionalSettlementAttacksState[Index] == False) If (WorkshopParent.Workshops[Index].AllowAttacks == True) WCP_QUST_Housekeeping.DefaultConditionalSettlementAttacksState[Index] = True StateChanged = IsWorkshopSafe(BuildMode, DisplayNotifications, Repaired, Index, ConstructableObject) EndIf EndIf If (DisplayNotifications == True) If (BuildMode == False) If (StateChanged == True) If (WorkshopParent.Workshops[Index].AllowAttacks == True) Debug.Notification(asNotificationText = "WCP: This settlement is now prone to attack") ElseIf (WorkshopParent.Workshops[Index].AllowAttacks == False) Debug.Notification(asNotificationText = "WCP: This settlement is no longer under attack") EndIf EndIf EndIf EndIf EndFunction Int Function GetCurrentWorkshopIndex() ; --------- ; Variables ; --------- Int CenterIndex Int ContainerIndex Int PlayerIndex Int SandboxIndex Int SpawnIndex Int WorkbenchIndex ; ---------- ; Operations ; ---------- PlayerIndex = WorkshopParent.WorkshopLocations.Find(akElement = PlayerRef.GetCurrentLocation(), aiStartIndex = 0) If (PlayerIndex >= 0) Return PlayerIndex EndIf ; WorkbenchIndex = WorkshopParent.WorkshopLocations.Find(akElement = Self.GetReference().GetCurrentLocation(), aiStartIndex = 0) ; ; If (WorkbenchIndex >= 0) ; Return WorkbenchIndex ; EndIf ; ; SandboxIndex = WorkshopParent.WorkshopLocations.Find(akElement = Self.GetReference().GetLinkedRef(apKeyword = WorkshopLinkSandbox).GetCurrentLocation(), aiStartIndex = 0) ; ; If (SandboxIndex >= 0) ; Return SandboxIndex ; EndIf ; ; ContainerIndex = WorkshopParent.WorkshopLocations.Find(akElement = Self.GetReference().GetLinkedRef(apKeyword = WorkshopLinkContainer).GetCurrentLocation(), aiStartIndex = 0) ; ; If (ContainerIndex >= 0) ; Return ContainerIndex ; EndIf ; ; CenterIndex = WorkshopParent.WorkshopLocations.Find(akElement = Self.GetReference().GetLinkedRef(apKeyword = WorkshopLinkCenter).GetCurrentLocation(), aiStartIndex = 0) ; ; If (CenterIndex >= 0) ; Return CenterIndex ; EndIf ; ; SpawnIndex = WorkshopParent.WorkshopLocations.Find(akElement = Self.GetReference().GetLinkedRef(apKeyword = WorkshopLinkSpawn).GetCurrentLocation(), aiStartIndex = 0) ; ; If (SpawnIndex >= 0) ; Return SpawnIndex ; EndIf ; ; If (PlayerIndex < 0 && WorkbenchIndex < 0 && SandboxIndex < 0 && ContainerIndex < 0 && CenterIndex < 0 && SpawnIndex < 0) ; WCP_QUST_Housekeeping.ErrorWarning(301) ; ; ; Stop the script running ; EndIf EndFunction [/code] Edit: I just noticed that the Enabled state wasn't set to Auto, so that could explain those issues (I'll have a look at fixing it now). However, that doesn't explain why the OnActivate event wasn't giving me any feedback. Edit 2: Or rather, I forgot to change the state of this script from Disabled to Enabled in the perk script when this feature is enabled. Edit 3: Yeah... after remotely changing the state of the script in the spoiler to Enabled, the script appears to function as intended. I guess I'm an idiot. Still, you've helped me understand reference collection aliases, so this hasn't been a waste. Thanks for your help mate. Edited April 17, 2017 by KernalsEgg Link to comment Share on other sites More sharing options...
vkz89q Posted April 17, 2017 Share Posted April 17, 2017 Funny, I just tested your file and added your script to ref alias collection, did same state change you did and all works perfectly :D Glad it worked out! Link to comment Share on other sites More sharing options...
Magicockerel Posted April 17, 2017 Author Share Posted April 17, 2017 I've been slowly working on these scripts over the last couple of months. I lost what I had originally been working on when I reformatted my computer (again, I'm an idiot), which I did after being out of country for over a month. What ended up happening was me trying to work myself back to where I was purely in Notepad++ (that is, just the scripts themselves), as I only recently attempted to compile the scripts in the CK and create the .esp itself. Given that I hadn't worked on the mod for over a month, though, it took a while to re-familiarise myself with my previous work. These sort of bugs that result from discontinuities in design choices are a result of this. Luckily I had the source files that I have uploaded on the file page to work with. However, if you care to contrast what I've released on the mod page and what I uploaded to dropbox this morning, you'll see that I pretty much rebuilt the mod from scratch. Again, thanks for the help mate :) Link to comment Share on other sites More sharing options...
Recommended Posts