SMB92 Posted May 28, 2017 Author Share Posted May 28, 2017 I use Notepad++ with the Papyrus highlights plugin :) I'm quite familiar with all those things in CK, pretty much Notepad++ and CK back and forth, back and forth. I have not tried bothering with the compiler plugin for Notepad++ though, I don't see any need for it (yet). I like this idea you mentioned, I did try sticking the struct along with the array inside a blank script and importing it, I did not think to do what you suggested (struct in blank script, array in quest) but I will do that right now. I was also looking at changing out using an XmarkerHeading for a DefaultActivator (because you can tie the script to the base object) but I am not sure yet if there are any limitations or implications of using an Activator placed in the world ( and using OnCellAtach events etc, will read into it). This was just a backup plan so to speak. I thought about having the Spawn() function on the Quest and having that pass the parameters/values to the marker script for the SpawnEnemyActors() function, but I do not know how to write that up properly just yet, I am aware I would have to code some security measure so that multiple instances of the Marker script couldn't run that function all at one time. Link to comment Share on other sites More sharing options...
kitcat81 Posted May 28, 2017 Share Posted May 28, 2017 I see, but I`m still not sure that I understand , sorry. I mean...This is from wiki : The "Import" keyword lets you use global functions in a script without prefixing them with the name of the script they are in. Simply use "Import" followed by the name of the script to import. If a function with the same name exists in both then you will still have to prefix it with the name of the script which contains the version you want. But there are no functions and no global functions in the quest script. So it looks like there is nothing to import. Link to comment Share on other sites More sharing options...
SMB92 Posted May 28, 2017 Author Share Posted May 28, 2017 I see, butÃÂ I`mÃÂ still not sure that IÃÂ understand , sorry.ÃÂ ÃÂ I mean...This is from wiki : The "Import" keyword lets you use global functions in a script without prefixing them with the name of the script they are in. Simply use "Import" followed by the name of the script to import. If a function with the same name exists in both then you will still have to prefix it with the name of the script which contains the version you want.ÃÂ ButÃÂ there are noÃÂ functions and no globalÃÂ functionsÃÂ in the quest script. SoÃÂ it looks like there is nothing to import.I understand only structs and functions can be imported, thats fine. What I want to do is look at the array in the quest script, have the functions in the local script see and use it, that is all. I don't need to change values in it from the local script. So yeah basically a remote storage so I don't have to define potentially tens of thousands of properties on each marker (imagine updating them omg) Link to comment Share on other sites More sharing options...
JonathanOstrus Posted May 28, 2017 Share Posted May 28, 2017 (edited) I use Notepad++ with the Papyrus highlights plugin :smile: I'm quite familiar with all those things in CK, pretty much Notepad++ and CK back and forth, back and forth. I have not tried bothering with the compiler plugin for Notepad++ though, I don't see any need for it (yet). I like this idea you mentioned, I did try sticking the struct along with the array inside a blank script and importing it, I did not think to do what you suggested (struct in blank script, array in quest) but I will do that right now. I was also looking at changing out using an XmarkerHeading for a DefaultActivator (because you can tie the script to the base object) but I am not sure yet if there are any limitations or implications of using an Activator placed in the world ( and using OnCellAtach events etc, will read into it). This was just a backup plan so to speak. I thought about having the Spawn() function on the Quest and having that pass the parameters/values to the marker script for the SpawnEnemyActors() function, but I do not know how to write that up properly just yet, I am aware I would have to code some security measure so that multiple instances of the Marker script couldn't run that function all at one time. I believe an activator will work so-long as it's a permanent and not temporary one. I'd have to go look again but moving the SpawnEnemyActors to the quest should be ok. Most of it can be moved around. Edited May 28, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
SMB92 Posted May 28, 2017 Author Share Posted May 28, 2017 type mismatch while assigning to a asc_random#actortypestruct (cast missing or types unrelated) No output generated for ASC_Random, compilation failed. BTW this is the error that I see in the compiler, seems a bit strange to me. Link to comment Share on other sites More sharing options...
JonathanOstrus Posted May 28, 2017 Share Posted May 28, 2017 type mismatch while assigning to a asc_random#actortypestruct (cast missing or types unrelated)No output generated for ASC_Random, compilation failed. BTW this is the error that I see in the compiler, seems a bit strange to me. I'd need to see the whole script and the whole compiler output verbatim. It will include the line #'s and stuff. Link to comment Share on other sites More sharing options...
JonathanOstrus Posted May 28, 2017 Share Posted May 28, 2017 Ah nvm I see the problem line. In the Spawn() function. The line ActorTypestruct spawnDetails = ... Not sure what your current version looks like but should be something like: ActorTypestruct spawnDetails = (ASC_MasterRandomQuest as ASC_MasterRandomQuestScript).ActorTypes[iWhoToSpawn] I think your last version had ActorTypes.Length instead of iWhoToSpawn. Link to comment Share on other sites More sharing options...
SMB92 Posted May 28, 2017 Author Share Posted May 28, 2017 Done everything like you mentioned and finally, it compiles (Ship It™) Scriptname ASC_Random extends ObjectReference import ASC_MainStruct ASC_MasterRandomQuestScript Property ASC_MasterRandomQuest Auto GlobalVariable Property ASC_Main_ModEnabled Auto Const GlobalVariable Property ASC_Main_RandomEnabled_R1 Auto Const GlobalVariable Property ASC_Main_Random_Chance_R1 Auto Const GlobalVariable Property ASC_Main_Random_DisableOnBlock_R1 Auto Const FormList Property ASC_ResetList_R1 Auto Const Actor Property PlayerRef Auto Const ObjectReference Property PatrolMarker Auto Const GlobalVariable Property ASC_Main_Difficulty_R1 Auto Const GlobalVariable Property ASC_Reroll_Main_Chance_R1 Auto Const GlobalVariable Property ASC_Reroll_Main_R1 Auto Const GlobalVariable Property ASC_DeleteTimer_R1 Auto Const bool Rerolled = false Actor[] GroupList Function Spawn() int iNumSpawnTypes = (ASC_MasterRandomQuest as ASC_MasterRandomQuestScript).ActorTypes.Length ; how many types of spawning actors can we support int iWhoToSpawn = Utility.RandomInt(1,iNumSpawnTypes) ; changed to use the size of our array of actor types ActorTypeStruct spawnDetails = (ASC_MasterRandomQuest as ASC_MasterRandomQuestScript).ActorTypes[iWhoToSpawn] if (spawnDetails.ASC_Allowed.GetValueInt() == 1) SpawnEnemyActors(spawnDetails.ASC_Max_Allowed.GetValueInt(), spawnDetails.ASC_Chance.GetValueInt(), spawnDetails.LvlActorBase, spawnDetails.ASC_Allowed_Boss.GetValue() as Bool, spawnDetails.ASC_Max_Allowed_Boss.GetValueInt(), spawnDetails.ASC_Chance_Boss.GetValueInt(), spawnDetails.LvlActorBossBase) elseif (spawnDetails.ASC_Allowed.GetValueInt() == 0) && (spawnDetails.ASC_Reroll_Allowed.GetValueInt() == 1) RerollCheck(spawnDetails.ASC_Reroll_Chance.GetValueInt()) ;else ; should there be something to handle a case where we're not allowed and have no reroll allowance? the way this is right now, if both were 0 then nothing would get spawned and the script stalls until the cell unloads and the spawn is called again on the new cell load. endif EndFunction Function SpawnEnemyActors(int iMaxSpawnCount, int iChance, ActorBase varBaseActor, bool bBossAllowed, int iMaxBossCount, int iBossChance, ActorBase varBossActor) int Difficulty = ASC_Main_Difficulty_R1.GetValueInt() int iSpawnCounter = iMaxSpawnCount int iPosition = 0 bool bSpawnSuccess = false GroupList = new Actor[0] ; since we don't have 100% chance of spawning actors, we need this to be an accumulating array Debug.Notification("Spawning enemies") ; unless we add a function parameter for text this had to be changed to be something generic while (iSpawnCounter < iMaxSpawnCount) if (Utility.RandomInt(1,100) <= iChance) GroupList.Add(Self.PlaceActorAtMe(varBaseActor, Utility.RandomInt(1,Difficulty), None)) iPosition = GroupList.Length - 1 GroupList[iPosition].SetLinkedRef(PatrolMarker) Debug.Notification("Array Add Success. Actor count now: " + iPosition) bSpawnSuccess = True endif iSpawnCounter += 1 endwhile if bBossAllowed == 1 iSpawnCounter = 0 ; reuse var. memory efficient while (iSpawnCounter < iMaxBossCount) if (Utility.RandomInt(1,100) <= iBossChance) GroupList.Add(Self.PlaceActorAtMe(varBossActor, Utility.RandomInt(1,Difficulty), None)) iPosition = GroupList.Length - 1 GroupList[iPosition].SetLinkedRef(PatrolMarker) Debug.Notification("Array Add Success. Actor count now: " + iPosition) bSpawnSuccess = True endif iSpawnCounter += 1 endwhile endif EndFunction Function RerollCheck(int iRerollChance) if (Rerolled == false) && (Utility.RandomInt(1,100) <= iRerollChance) Spawn() Rerolled = true Debug.Notification("Rerolling after block") else Debug.Notification("Reroll on block denied") endif EndFunction EDIT: Confirming that the array is no longer a property on the marker script! Link to comment Share on other sites More sharing options...
kitcat81 Posted May 28, 2017 Share Posted May 28, 2017 I see, butÃÂ I`mÃÂ still not sure that IÃÂ understand , sorry.ÃÂ ÃÂ I mean...This is from wiki : The "Import" keyword lets you use global functions in a script without prefixing them with the name of the script they are in. Simply use "Import" followed by the name of the script to import. If a function with the same name exists in both then you will still have to prefix it with the name of the script which contains the version you want.ÃÂ ButÃÂ there are noÃÂ functions and no globalÃÂ functionsÃÂ in the quest script. SoÃÂ it looks like there is nothing to import.I understand only structs and functions can be imported, thats fine. What I want to do is look at the array in the quest script, have the functions in the local script see and use it, that is all. I don't need to change values in it from the local script. So yeah basically a remote storage so I don't have to define potentially tens of thousands of properties on each marker (imagine updating them omg) Interesting. Unfortunately, I can`t find any info about this. The wiki only mentions global functions. Though I know it can miss some things, but I have not seen any examples of such usage in a vanilla script. You can move the spawining function with all the other properties to the quest script and then yoy can run it from the marker script. So the markers oncellatach RegisterForDistanceLessThan ( the distance should be at least twice shorter than the distance between markers so there is no chance they will try to spawn something in the same time. When the event fires the active marker calls the quest function that spawns a actor. OnCellDetach they unregister for all events so there will be no persistence. You`ll only need to think how to make it so that the actor spaws on the current marker. Or do you want all markers in a cell to spawn something in the moment when the player enters the cell? Link to comment Share on other sites More sharing options...
JonathanOstrus Posted May 28, 2017 Share Posted May 28, 2017 Done everything like you mentioned and finally, it compiles (Ship It™) Scriptname ASC_Random extends ObjectReference import ASC_MainStruct ASC_MasterRandomQuestScript Property ASC_MasterRandomQuest Auto GlobalVariable Property ASC_Main_ModEnabled Auto Const GlobalVariable Property ASC_Main_RandomEnabled_R1 Auto Const GlobalVariable Property ASC_Main_Random_Chance_R1 Auto Const GlobalVariable Property ASC_Main_Random_DisableOnBlock_R1 Auto Const FormList Property ASC_ResetList_R1 Auto Const Actor Property PlayerRef Auto Const ObjectReference Property PatrolMarker Auto Const GlobalVariable Property ASC_Main_Difficulty_R1 Auto Const GlobalVariable Property ASC_Reroll_Main_Chance_R1 Auto Const GlobalVariable Property ASC_Reroll_Main_R1 Auto Const GlobalVariable Property ASC_DeleteTimer_R1 Auto Const bool Rerolled = false Actor[] GroupList Function Spawn() int iNumSpawnTypes = (ASC_MasterRandomQuest as ASC_MasterRandomQuestScript).ActorTypes.Length ; how many types of spawning actors can we support int iWhoToSpawn = Utility.RandomInt(1,iNumSpawnTypes) ; changed to use the size of our array of actor types ActorTypeStruct spawnDetails = (ASC_MasterRandomQuest as ASC_MasterRandomQuestScript).ActorTypes[iWhoToSpawn] if (spawnDetails.ASC_Allowed.GetValueInt() == 1) SpawnEnemyActors(spawnDetails.ASC_Max_Allowed.GetValueInt(), spawnDetails.ASC_Chance.GetValueInt(), spawnDetails.LvlActorBase, spawnDetails.ASC_Allowed_Boss.GetValue() as Bool, spawnDetails.ASC_Max_Allowed_Boss.GetValueInt(), spawnDetails.ASC_Chance_Boss.GetValueInt(), spawnDetails.LvlActorBossBase) elseif (spawnDetails.ASC_Allowed.GetValueInt() == 0) && (spawnDetails.ASC_Reroll_Allowed.GetValueInt() == 1) RerollCheck(spawnDetails.ASC_Reroll_Chance.GetValueInt()) ;else ; should there be something to handle a case where we're not allowed and have no reroll allowance? the way this is right now, if both were 0 then nothing would get spawned and the script stalls until the cell unloads and the spawn is called again on the new cell load. endif EndFunction Function SpawnEnemyActors(int iMaxSpawnCount, int iChance, ActorBase varBaseActor, bool bBossAllowed, int iMaxBossCount, int iBossChance, ActorBase varBossActor) int Difficulty = ASC_Main_Difficulty_R1.GetValueInt() int iSpawnCounter = iMaxSpawnCount int iPosition = 0 bool bSpawnSuccess = false GroupList = new Actor[0] ; since we don't have 100% chance of spawning actors, we need this to be an accumulating array Debug.Notification("Spawning enemies") ; unless we add a function parameter for text this had to be changed to be something generic while (iSpawnCounter < iMaxSpawnCount) if (Utility.RandomInt(1,100) <= iChance) GroupList.Add(Self.PlaceActorAtMe(varBaseActor, Utility.RandomInt(1,Difficulty), None)) iPosition = GroupList.Length - 1 GroupList[iPosition].SetLinkedRef(PatrolMarker) Debug.Notification("Array Add Success. Actor count now: " + iPosition) bSpawnSuccess = True endif iSpawnCounter += 1 endwhile if bBossAllowed == 1 iSpawnCounter = 0 ; reuse var. memory efficient while (iSpawnCounter < iMaxBossCount) if (Utility.RandomInt(1,100) <= iBossChance) GroupList.Add(Self.PlaceActorAtMe(varBossActor, Utility.RandomInt(1,Difficulty), None)) iPosition = GroupList.Length - 1 GroupList[iPosition].SetLinkedRef(PatrolMarker) Debug.Notification("Array Add Success. Actor count now: " + iPosition) bSpawnSuccess = True endif iSpawnCounter += 1 endwhile endif EndFunction Function RerollCheck(int iRerollChance) if (Rerolled == false) && (Utility.RandomInt(1,100) <= iRerollChance) Spawn() Rerolled = true Debug.Notification("Rerolling after block") else Debug.Notification("Reroll on block denied") endif EndFunction EDIT: Confirming that the array is no longer a property on the marker script! Just thought about your mention to move SpawnEnemyActors to the quest script. While you can do that, as it is it doesn't really matter either way. You'd need to make sure to add an argument to the function so you can pass the marker ObjectReference. Then in the SpawnEnemyActors function change the self in the uses of self.PlaceActorAtMe to the argument variable. Link to comment Share on other sites More sharing options...
Recommended Posts