en_hawk Posted June 10, 2013 Posted June 10, 2013 I've been working on a custom race project and I've started running into problems with RC. I'm using custom modifications of the generic race controller, as my races are setup differently than what is typical; the races are completely separated from the vanilla head part formlists. So I made a stripped down version of the generic race controller, NoHDPTRaceController, that only adds the race to the necessary formlists for RC to work properly, as their head part formlists have the races added directly to them. That part is all well and good, next I wanted to add additional races as separate plugins, so I needed to make a new race controller that added the races to my custom head part formlists(along with the RC ones) as opposed to the vanilla ones. This is the part that isn't behaving correctly. For reference, I'm using this version of racial compatibility http://skyrim.nexusmods.com/mods/24168/.it seemed to be working correctly with the first race I made, however when I added a second one the head part formlist adding started randomly failing when I started a new game, so one(or both) of the extra races would not have hair/head parts available. So I edited the generic race controller and threw some debug lines in the proxyraces function to see if I could figure out what was up; that posed even more questions without answering any. Based on the code, it should call the proxy function once per race, keep looping until a spot opens up in the dispatcher, then finally run the actual proxy code. It appears to be trying to start the proxy routine multiple times, jumping all over the place, and then inexplicably giving up half the time. I have very little to no experience with papyrus(though I am an experienced programmer), so I'm really drawing a blank here.Because I don't feel like uploading 300mb of assets or so just for diagnosing a script issue(nor could I imagine most people would be interesting in downloading that either), I made a new set of plugins in about 10 minutes specifically for demonstrating the issue. I have the base plugin with its custom set of head part records along with the first race, they're all just copies of the vanilla nord, its added to the head part formlists statically. Next I've got two addon plugins that are pretty much identical; they each contain a single race and utilize a custom race controller that adds the races to the head part formlists in the base plugin. On their own they work correctly, however if I run both of them at the same time one or both of them will fail to add itself to the formlists and end up with no headparts or hair.I'll post the script source here, in addition to including it with the rest of the files.Here's how I modified the proxyraces function in the generic race controller for debugging: Function proxyRaces() RaceDispatcherScript dispatch = Game.GetFormFromFile(0x00009F27, "RaceCompatibility.esm") As RaceDispatcherScriptDebug.Trace("proxy: " + Self as String) While !dispatch.doProxyRace(Self)Debug.Trace(Self as String + " is waiting to proxy") Utility.Wait(1.0) EndWhileDebug.Trace("proxy completed: " + Self as String)EndFunction Here's the NoHDPTRaceController: Scriptname NoHDPTRaceController extends GenericRaceController bool Function internalProxyRaces() FormList[] RaceList = new FormList[10] RaceList[0] = NewArgonian RaceList[1] = NewBreton RaceList[2] = NewDarkElf RaceList[3] = NewHighElf RaceList[4] = NewImperial RaceList[5] = NewKhajiit RaceList[6] = NewNord RaceList[7] = NewOrc RaceList[8] = NewRedguard RaceList[9] = NewWoodElf FormList[] RaceListVampire = new FormList[10] RaceListVampire[0] = NewArgonianVampire RaceListVampire[1] = NewBretonVampire RaceListVampire[2] = NewDarkElfVampire RaceListVampire[3] = NewHighElfVampire RaceListVampire[4] = NewImperialVampire RaceListVampire[5] = NewKhajiitVampire RaceListVampire[6] = NewNordVampire RaceListVampire[7] = NewOrcVampire RaceListVampire[8] = NewRedguardVampire RaceListVampire[9] = NewWoodElfVampire int element = 0 While(element < RaceList.Length) If(RaceList[element] != None && RaceList[element].GetSize() > 0) ; Ensure we actually have a replacement int index = 0 While(index < RaceList[element].GetSize()) ; Cycle each race in our replacement list ; Regular Listing Race standardRace = RaceList[element].GetAt(index) AS Race if(standardRace != None) ; Make sure we actually have a race to replace with if(PlayableRaceList != None && !PlayableRaceList.HasForm(standardRace)) ; Check for None so we can skip transform script without crashing PlayableRaceList.AddForm(standardRace) endIf if(!isHuman(element)) if(!RacesBeast.HasForm(standardRace)) RacesBeast.AddForm(standardRace) endIf endIf If(isHuman(element)) if(!RacesHuman.HasForm(standardRace)) RacesHuman.AddForm(standardRace) endIf endIf If(isElf(element)) if(!RacesElf.HasForm(standardRace)) RacesElf.AddForm(standardRace) endIf endIf ; Vampire Listing If(RaceListVampire[element] != None && RaceListVampire[element].GetSize() > 0) Race vampireRace = RaceListVampire[element].GetAt(index) AS Race if(vampireRace != None) if(PlayableVampireList != None && !PlayableVampireList.HasForm(vampireRace)) ; Check for None so we can skip transform script without crashing PlayableVampireList.AddForm(vampireRace) endIf endIf endIf endIf index += 1 endWhile endIf element += 1 EndWhile Return TrueEndFunction Here's the controller I made for the example plugin races: Scriptname testracecontroller extends GenericRaceController ; Multi-Race PartsFormList Property validracesnordtest Auto bool Function internalProxyRaces() FormList[] RaceList = new FormList[10] RaceList[0] = NewArgonian RaceList[1] = NewBreton RaceList[2] = NewDarkElf RaceList[3] = NewHighElf RaceList[4] = NewImperial RaceList[5] = NewKhajiit RaceList[6] = NewNord RaceList[7] = NewOrc RaceList[8] = NewRedguard RaceList[9] = NewWoodElf FormList[] RaceListVampire = new FormList[10] RaceListVampire[0] = NewArgonianVampire RaceListVampire[1] = NewBretonVampire RaceListVampire[2] = NewDarkElfVampire RaceListVampire[3] = NewHighElfVampire RaceListVampire[4] = NewImperialVampire RaceListVampire[5] = NewKhajiitVampire RaceListVampire[6] = NewNordVampire RaceListVampire[7] = NewOrcVampire RaceListVampire[8] = NewRedguardVampire RaceListVampire[9] = NewWoodElfVampire int element = 0 While(element < RaceList.Length) If(RaceList[element] != None && RaceList[element].GetSize() > 0) ; Ensure we actually have a replacement int index = 0 While(index < RaceList[element].GetSize()) ; Cycle each race in our replacement list ; Regular Listing Race standardRace = RaceList[element].GetAt(index) AS Race if(standardRace != None) ; Make sure we actually have a race to replace with if(PlayableRaceList != None && !PlayableRaceList.HasForm(standardRace)) ; Check for None so we can skip transform script without crashing PlayableRaceList.AddForm(standardRace) endIf if(!isHuman(element)) if(!RacesBeast.HasForm(standardRace)) RacesBeast.AddForm(standardRace) endIf endIf ; Conditioned Listings If(isHuman(element) || isOrc(element) || isElf(element)) if(!validracesnordtest.HasForm(standardRace)) validracesnordtest.AddForm(standardRace) endIf endIf If(isHuman(element)) if(!RacesHuman.HasForm(standardRace)) RacesHuman.AddForm(standardRace) endIf endIf If(isElf(element)) if(!RacesElf.HasForm(standardRace)) RacesElf.AddForm(standardRace) endIf endIf ; Vampire Listing If(RaceListVampire[element] != None && RaceListVampire[element].GetSize() > 0) Race vampireRace = RaceListVampire[element].GetAt(index) AS Race if(vampireRace != None) if(PlayableVampireList != None && !PlayableVampireList.HasForm(vampireRace)) ; Check for None so we can skip transform script without crashing PlayableVampireList.AddForm(vampireRace) endIf endIf endIf endIf index += 1 endWhile endIf element += 1 EndWhile Return TrueEndFunction Here are the relevant excerpts from my papyrus log: [06/10/2013 - 03:08:19AM] proxy: [testracecontroller <nordtest3controller (17002F9F)>][06/10/2013 - 03:08:19AM] handling target:[testracecontroller <nordtest3controller (17002F9F)>][06/10/2013 - 03:08:19AM] proxy: [testracecontroller <nordtest2controller (16002F9F)>][06/10/2013 - 03:08:19AM] waiting for Slot:[testracecontroller <nordtest2controller (16002F9F)>][06/10/2013 - 03:08:19AM] proxy: [NoHDPTRaceController <nordtestcontroller (15002FB2)>][06/10/2013 - 03:08:19AM] waiting for Slot:[NoHDPTRaceController <nordtestcontroller (15002FB2)>] [06/10/2013 - 03:08:24AM] proxy: [NoHDPTRaceController <nordtestcontroller (15002FB2)>][06/10/2013 - 03:08:24AM] handling target:[NoHDPTRaceController <nordtestcontroller (15002FB2)>][06/10/2013 - 03:08:24AM] proxy: [testracecontroller <nordtest2controller (16002F9F)>][06/10/2013 - 03:08:24AM] waiting for Slot:[testracecontroller <nordtest2controller (16002F9F)>][06/10/2013 - 03:08:24AM] proxy: [testracecontroller <nordtest3controller (17002F9F)>][06/10/2013 - 03:08:24AM] waiting for Slot:[testracecontroller <nordtest3controller (17002F9F)>][06/10/2013 - 03:08:24AM] proxy completed: [NoHDPTRaceController <nordtestcontroller (15002FB2)>][06/10/2013 - 03:08:24AM] proxy completed: [testracecontroller <nordtest3controller (17002F9F)>] Based on this it appears that each race is running the proxy routine twice for some reason, and it does not appear to be looping at all; if it doesn't get a slot in the dispatcher on the first call it just aborts for some reason. As you can see, the base race and plugin number 2(nordtest3) successfully proxied and work properly, whereas plugin number 1(nordtest2) did not and none of its head parts work(sliders move but nothing happens, it just keeps the model of whatever you had selected on the previous race before swapping). Just a note, the only head parts I added multiple options for is the hair(for males only), and there's only the two of them so please keep that in mind. Any insight into this would be much appreciated, I'm out of ideas.
en_hawk Posted June 20, 2013 Author Posted June 20, 2013 I've still not figured out a solution to this problem, could really use some help.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.