unknownhero2827 Posted October 1, 2015 Share Posted October 1, 2015 (edited) I'm trying to give my followers group orders through a menu, activated by a spell. So far, I can only get to the menu part. Honestly I barely have any idea how to do this. Begin ScriptEffectStart MessageBox "Group Orders." "Follow" "Stay" "Nevermind" End Begin Gamemode if GetButtonPressed > -1if GetButtonPressed == 0 ;Followset IFQuest.IFGroupOrders to 1elseif GetButtonPressed == 1 ;Stayset IFQuest.IFGroupOrders to 2elseif GetButtonPressed == 2 ;Nevermindset IFQuest.IFGroupOrders to 0endifendif End This is my spell script, of course. I don't know if it's laid out right. You can see that I'm trying to make it change a short in a quest script. From the quest script, I'm using that as what my followers' object script refers to when given a group order. if IFQuest.IFGroupOrders == 1RemoveScriptPackageAddScriptPackage IFFollowPackageelseif IFQuest.IFGroupOrders == 2RemoveScriptPackageAddScriptPackage IFStayPackageendif That's the object script. Another problem is I don't know if my spell script is constantly setting the IFGroupOrders short. Oh and I have the different lines indented and stuff (idk if it actually makes a difference other than it's easier to navigate). If there's a better way to try and do this, like bypassing the quest script altogether, that'd be nice. Thanks for any help in advance. EDIT: I apologize for my lack of... terminology. Edited October 1, 2015 by unknownhero2827 Link to comment Share on other sites More sharing options...
unknownhero2827 Posted October 1, 2015 Author Share Posted October 1, 2015 http://cs.elderscrolls.com/index.php?title=MessageBox_Tutorial I found this on the construction set wiki. I'll probably have to take some time to review it. Link to comment Share on other sites More sharing options...
Surilindur Posted October 1, 2015 Share Posted October 1, 2015 (edited) Script effects use something like Begin ScriptEffectUpdate ... EndAnd not GameMode. I have managed to do messageboxes with spells, so it should theoretically work.Edit: Also, the GetButtonPressed returns the correct button only once. Grab it once, and then use it. Like this: short iButton ... Begin ScriptEffectUpdate set iButton to GetButtonPressed If ( iButton < 0 ) Return EndIf ... Your scripts here with iButton as the button pressed ... set iButton to -1 End Also, you could try learning how arrays work. OBSE adds them. In my follower management mod, there is an array that stores information about the followers. When issuing a command, you could then cycle through the array and access each follower that way instead of using a quest script and actor scripts. Just an idea, might take a little learning. Edited October 1, 2015 by PhilippePetain Link to comment Share on other sites More sharing options...
unknownhero2827 Posted October 1, 2015 Author Share Posted October 1, 2015 I've successfully gotten the menu to work. But, the orders are only working with 1 actor at a time, unless i have it like this: Actor's Object Script if IFQuest.MenuResult == 1RemoveScriptPackageMoveTo PlayerAddScriptPackage IFFollowPackage elseif IFQuest.MenuResult == 2RemoveScriptPackageAddScriptPackage IFFollowPackageelseif IFQuest.MenuResult == 3RemoveScriptPackageAddScriptPackage IFStayPackageelseif IFQuest.MenuResult == 4RemoveScriptPackageAddScriptPackage IFRelaxPackageelseif IFQuest.MenuResult == 10RemoveScriptPackageAddScriptPackage IFTravelAnvilPackageelseif IFQuest.MenuResult == 11RemoveScriptPackageAddScriptPackage IFTravelBravilPackageelseif IFQuest.MenuResult == 12RemoveScriptPackageAddScriptPackage IFTravelBrumaPackageelseif IFQuest.MenuResult == 13RemoveScriptPackageAddScriptPackage IFTravelCheydinhalPackageelseif IFQuest.MenuResult == 14RemoveScriptPackageAddScriptPackage IFTravelChorrolPackageelseif IFQuest.MenuResult == 15RemoveScriptPackageAddScriptPackage IFTravelImperialCityPackageelseif IFQuest.MenuResult == 16RemoveScriptPackageAddScriptPackage IFTravelLeyawiinPackageelseif IFQuest.MenuResult == 17RemoveScriptPackageAddScriptPackage IFTravelSkingradPackageelseif IFQuest.MenuResult == 20ForceAV Aggression 50ForceAV Confidence 50elseif IFQuest.MenuResult == 21ForceAV Aggression 5ForceAV Confidence 50elseif IFQuest.MenuResult == 22ForceAV Confidence 0endif Quest Script: if GroupMenu == 1MessageBox "Group Orders" "Regroup" "Follow" "Stay" "Relax" "Travel" "Behavior" "Nevermind"set Choosing to 1set GroupMenu to 0elseif (Choosing == 1) set Choice to GetButtonPressed if (Choice == -1)elseif (Choice == 0)set MenuResult to 1 elseif (Choice == 1) set MenuResult to 2 elseif (Choice == 2) set MenuResult to 3 elseif (Choice == 3) set MenuResult to 4elseif (Choice == 4) ;Travelset Choosing to -10 elseif (Choice == 5) ;Behaviorset Choosing to -11 elseif (Choice == 6)endifelseif (Choosing == -10)MessageBox "Group Orders: Travel" "Anvil" "Bravil" "Bruma" "Cheydinhal" "Chorrol" "Imperial City" "Leyawiin" "Skingrad" "Nevermind"set Choosing to 10elseif Choosing == 10set Choice to GetButtonPressed if (Choice == -1)elseif (Choice == 0)set MenuResult to 10elseif (Choice == 1)set MenuResult to 11elseif (Choice == 2)set MenuResult to 12elseif (Choice == 3)set MenuResult to 13elseif (Choice == 4)set MenuResult to 14elseif (Choice == 5)set MenuResult to 15elseif (Choice == 6)set MenuResult to 16elseif (Choice == 7)set MenuResult to 17elseif (Choice == 8) endif elseif (Choosing == -11)MessageBox "Group Orders: Behavior" "Aggressive" "Defensive" "Evasive" "Nevermind"set Choosing to 11elseif (Choosing == 11)set Choice to GetButtonPressedif (Choice == -1)elseif (Choice == 0)set MenuResult to 20elseif (Choice == 1)set MenuResult to 21elseif (Choice == 2)set MenuResult to 22elseif (Choice == 3) endif endif This means that the actors continuously get reassigned the command over and over again. It does make them all "obey", but the script is still rubbish right now. I'll try looking into arrays, though I'm sure it'll take me a lot longer than I'd like to figure out what I'm looking at. Link to comment Share on other sites More sharing options...
Surilindur Posted October 1, 2015 Share Posted October 1, 2015 (edited) But it will make writing easier. Write it once, then use it for one follower, two followers, twenty followers, a hundred followers, whatever! As long as the game can handle it, though. Definitely recommended. I would call it the lazy one's choice were it not for the learning if one is completely new to arrays. And I also asked for help on the forums. Or at least I received help, so I must have asked. :smile: I dare not comment on the quest script implementation. If it works for you, that is fantastic. I assume you know how to stop the quest when not necessary? So as to spare game resources? Also, the actor script could do with some improvement maybe. Or maybe not. In high level processing, an actor's script is run every frame and it happens for each individual actor. You could use a variable to restrict the amount of processing when not relevant. But I am not sure how it would work with that thingy. Using an array could solve everything, and you could just have one quest script with an array (quest script update interval irrelevant) with a spell that handles commands. A simple version could maybe work a bit like the following (not your script, but the idea) if using OBSE and arrays? Quest script ScriptName SomeQuestScript float fQuestDelayTime int iTemp Array_var aFollowers Begin GameMode If ( GetGameLoaded == 0 ) ; Only run the rest of the script when a save has been loaded Return EndIf let iTemp := ar_Size aFollowers ; Check if array has been initialised If ( iTemp < 0 ) ; If not, initialise it let aFollowers := ar_Construct Array EndIf EndSpell script effect for control spell ScriptName SomeControlSpellScript int iButton ref rTemp Array_var aTemp Begin ScriptEffectStart MessageBox "Option A" "Option B" "Option C" End Begin ScriptEffectUpdate let iButton := GetButtonPressed ; Get the pressed button If ( iButton < 0 ) ; If not relevant, skip the rest of the script Return EndIf let aTemp := ar_Construct Array ; Initialise temp array ; This following could also be done with indexes, which is what I do. ; Indexes work better if you have added several StringMap type arrays to ; aFollowers and therfore cannot directly access followers the following way. ForEach aTemp <- SomeQuest.aFollowers ; For every element thingy in aFollowers let rTemp := *aTemp ; Get the actor reference from the element If ( iButton == 0 ) ; Choice A, for example: rTemp.MoveTo Player rTemp.RemoveScriptPackage ElseIf ( iButton == 1 ) ; Choice B ElseIf ( iButton == 2 ) ; Choice C EndIf Loop let iButton := -1 ; Prevent running this again let aTemp := ar_Null ; Just emptying the temp array, probably not necessary EndAnd how to add a follower to the array of followers (just place it somewhere): int iTemp ref rTarget ... let rTarget := TargetToRecruit let iTemp := ar_Find rTarget SomeQuest.aFollowers If ( iTemp < 0 ) ; Only if the actor is not already in the array ar_Append SomeQuest.aFollowers rTarget rTarget.AddScriptPackage SomePackage EndIfAnd for dismissing the actor int iTemp ref rTarget ... let rTarget := TargetToDismiss let iTemp := ar_Find rTarget SomeQuest.aFollowers If ( iTemp >= 0 ) ar_Erase SomeQuest.aFollowers iTemp EndIf rTarget.RemoveScriptPackageSo it would work completely without touching actors' scripts, making it universally compatible. :smile: Those examples are guaranteed to be 100% made-up-on-the-fly and fully untested! But just to give you an idea of how it could work. The OBSE command documentation has a pretty good explanation of how arrays work. :tongue: Edited October 1, 2015 by PhilippePetain Link to comment Share on other sites More sharing options...
unknownhero2827 Posted October 2, 2015 Author Share Posted October 2, 2015 I've decided to just go with group orders through dialogue for now. Thanks for your help on my multiple posts. I'll have to take some time to review your example, and read up on more tutorials. There's so much to learn. Have to ask though, is the knowledge going to be largely applicable to future/other games? Link to comment Share on other sites More sharing options...
Surilindur Posted October 2, 2015 Share Posted October 2, 2015 (edited) Well... I have not tried any scripting for Morrowind, but it seems to be a bit different if the tuorials I have read are correct. But I cannot comment on it. Even with MWSE, it would seem more limited to me. Or at least one would need to use more workarounds for things that are present in Oblivion with OBSE as normal commands. For Skyrim... umm... it uses the new Papyrus thing. Basic Oblivion scripting will not be of much help. It will be of some, but knowing how Oblivion scripting works will not make you a master of Papyrus. If you get far enough in Oblivion scripting so that you end up using OBSE event handlers and user-created functions, they are most likely the best thing OBSE has to offer on your way to Papyrus. But both Oblivion scripting and Papyrus are pretty simple, maybe. At least the basics. Papyrus just changes the syntax a bit and overhauls how scripts interact with the rest of the game, as they sort of just ripped the old scripting system out and pasted Papyrus on top of the game. Or that is how I view it. It does allow for more modularity or such, reusing scripts and whatnot, but it is a bit different. :tongue: For example if you can reference an actor in Oblivion the following way: MyActorRef.AddItem WeapIronLongsword 10But Papyrus cannot directly reference anything in the game. :sad: So in Papyrus, you would need to make a property for the actor ref and the sword, fill them with the actor and the sword (possible in the CK menu, is pretty easy) and then use the properties in your script. Actor Property MyActor Auto Weapon Property MyWeapon Auto ... MyActor.AddItem(MyWeapon, 10, false)So... well... it is not that difficult. The basics of arrays (indexes and such) are not too different, though. Once you get the basic principles, you will have very little to learn about the... well... principles. :tongue: Syntax can change, but the ideas remain. The thing with Papyrus and OBSE event handlers and user-created functions is that once you get the idea of how to call a user-created function, and know how event handlers work, you will know the basic principles of working with Papyrus. If you had a script like this as on OBSE user-created function: ScriptName MyOBSEFunction float fNumber float fMultiplier float fOutput Begin Function { fNumber fMultiplier } let fOutput := ( fNumber * fMultiplier ) SetFunctionValue fOutput EndAnd you would want to use it, to get the value of, for example 2.0 x 1.5, you would call it like (in Oblivion script): float fNumber ... let fNumber := Call MyOBSEFunction 2.0 1.5And it would return to you the value. For Papyrus, you could have them both in the same script. But the idea of calling a function and possibly supplying some arguments, also probably getting something back from it, are the same. Like (if it were an activator that returns the result as a messagebox): ScriptName MyPapyrusScript Extends ObjectReference Function FnMyPapyrusFunction(Float fNumber, Float fMultiplier) Float fOutput = (fNumber * fMultiplier) Return fOutput EndFunction Event OnActivate(ObjectReference akActionRef) If(akActionRef == Game.GetPlayer()) Float fNumber = FnMyPapyrusFunction(2.0, 1.5) Debug.MessageBox("Result is " + fNumber) EndIf EndEventAnd you can already see the Event OnActivate in there. Which works like an OBSE event handler, but is a script block that is executed upon the relevant event by the game. If you had an OBSE event handler, your event handler could look something like this (as an example, not a working one): ScriptName MyOBSEEventHandler ref rArgumentA ref rArgumentB Begin Function { rArgumentA rArgumentB } ; Code here EndAnd the event handler could receive the arguments from Oblivion when the event it is registered for is fired. In Papyrus, there is no need to place separate event handlers (except for maybe SKSE mod events, but you will not need to know about them now). Every event in Papyrus scripts will be called when appropriate and the game will supply it the necessary arguments. To put it simply. I hope that does not make you too confused. I only know Papyrus and the Oblivion scripting thingy (plus a little Python). And I am pretty bad at explaining things. :tongue: About future games, I have no idea. Also I have no idea about other games. I like to make mods for the Elder Scrolls series only, because it is still simple enough for me. But I know Fallout 3 and Fallout New Vegas work in a similar way, although both are from the same publisher. Also, unless Bethesda goes completely nutters, I suspect Fallout 4 will use something similar to Papyrus. So if you learn scripting for Oblivion, it canHelp you learn the very basic ideas behind arrays, strings and different variable types and how to manipulate themHelp you learn about variable operators and comparison operatorsHelp you understand the idea behind If-ElseIf-Else-EndIf and loops (While, ForEach, Label-GoTo)Help you learn how the game (scripts and such) works under the hood (handy for anyone using mods)Make it easier to move on to Fallout 3 or New Vegas, I thinkMake it easier to learn Papyrus, but only if you get far enough with Oblivion + OBSE, and you will still need to do some reading and such (still not a piece of cake)The Oblivion scripting is not the game code, it is code that the game runs. It is not a real programming language, and is pretty specific to those few games listed. Future titles from Bethesda will probably use different language thingy, hopefully a new version of their Papyrus language used for Skyrim, which is still not a real scripting language as it is, though. Hopefully that helps a little. I might be wrong, so anyone is free to correct. :smile: Edited October 2, 2015 by PhilippePetain Link to comment Share on other sites More sharing options...
Recommended Posts