zax Posted August 28, 2013 Posted August 28, 2013 Honestly, I have no idea. Although, why do you want to use a furniture object with 2 markers, instead of 2 different objects? I wouldn't know how to make an NPC access one out of many markers. With a sit target package you only can use the object, without any parameters. Maybe it'S possible to make a new sittarget procedure. But I have no idea. And I don't see a reson to do so. Use 2 markers. Then you automatically have 2 animations. Well, actually there are furnitures with multiple markers, but they are mostly triggering same idle. Was doing some research today and all I found is that its done via "marker keywords" attached to each marker (in furniture window). Then "keyword" check is set in each related animation on list. The thing I'm not 100% sure yet is if "marker keyword" option adds keyword to affected actor or its just requirement for specific marker activation? The only vanilla furniture using multiple idles that I found so far is "ExecutionerChoppingBlock" and its animations hidden in Action Activate -> Chair -> "Executionee® Is there any particular reason that I don't see? Was thinking of using this function http://www.creationkit.com/IsFurnitureMarkerInUse_-_ObjectReference to check if other markers are "in use" to trigger some effects on one of them. It could be kind of useful, since sex animatins could use method like that (two markers, then triggering animation when both are inUse) or something like interactive ZAZ devices where one actor sits inside when other is doing something else.
oli3d Posted August 29, 2013 Posted August 29, 2013 So I thinkk I ill skip this release, and start working on that missing piece which is the reason why 4.0 is still Beta: extend furniture animations. I now going to extend furnitures to the Sequenced Animations functionality (so you can define furnitures with as many animations and anima Objects as you like; simply say "fu" or "FU" instead of "sa" or "SA"). As soon as I have it ready I'll make a "restricted" Beta, to allow modders to switch to the new syntax before I release to final. that means a chair/furniture can have more different sit animations... for example nomalSit, relaxedSit , upsetsit etc.. as root animations? like: sitonchair----idleenterinstant ----idleenter ----idle1 +>keywordExtraCondition1 ----idle2 +>keywordExtraCondition2 ----idle3 +>keywordExtraCondition3 ----idle4 +>keywordExtraCondition4 ----idle5 +>keywordExtraCondition5 .. .. ----idleN +>keywordExtraConditionN ----idleExit or mor like: sitonchair----idleenterinstant ----idleenter ----idle +> plays sequenced Animations defined in behaviour file ----idleExit ? Moin Oli
fore Posted August 29, 2013 Author Posted August 29, 2013 Honestly, I have no idea. Although, why do you want to use a furniture object with 2 markers, instead of 2 different objects? I wouldn't know how to make an NPC access one out of many markers. With a sit target package you only can use the object, without any parameters. Maybe it'S possible to make a new sittarget procedure. But I have no idea. And I don't see a reson to do so. Use 2 markers. Then you automatically have 2 animations. Well, actually there are furnitures with multiple markers, but they are mostly triggering same idle. Was doing some research today and all I found is that its done via "marker keywords" attached to each marker (in furniture window). Then "keyword" check is set in each related animation on list. The thing I'm not 100% sure yet is if "marker keyword" option adds keyword to affected actor or its just requirement for specific marker activation? The only vanilla furniture using multiple idles that I found so far is "ExecutionerChoppingBlock" and its animations hidden in Action Activate -> Chair -> "Executionee® Is there any particular reason that I don't see? Was thinking of using this function http://www.creationkit.com/IsFurnitureMarkerInUse_-_ObjectReference to check if other markers are "in use" to trigger some effects on one of them. It could be kind of useful, since sex animatins could use method like that (two markers, then triggering animation when both are inUse) or something like interactive ZAZ devices where one actor sits inside when other is doing something else. These are very interesting findings, and lead us closer to the understanding how furniture REALLY work. The keywords are very convenient to distinguish which furniture is used by a character, but I don't think they are unavoidable. Any query which determines the required animation will help. Important are "Getsitting = <n>" conditions. When "Getsitting = 2", then the Enter animation is played, and from there Getsitting returns 3, and then we can use different Idles in the furniture. The "EnterInstant" AnimEvent sem to be raised when the char already is in a sitting position, so this does nothing but avoid the enter animation. One thing I don't know is, when a furniture has 2 or more markers (like the head chop). What marker will be selected as entry by a char? Certainly one which is not used yet. But others than that I haven't found any parameter to support that. I assume it's simply the (open) entry that is closest to a char. But's that's just an assumption. But from here, the animations which are selected are exclusively determined by the conditions used in the CK idle animations. They are not triggered by the furniture or it's markers. So I think, with the next FNIS version with more than one sit animation you will have 2 choices how to define conditions: either in the CK like today, or with SAE() in scripts. Shoulkd be the same result. Except when using SAE() you don't need to define any CK idles except Enter/EnterInstant/Exit. And even these 3 I'm not sure if we really need them all. Let's see what the tests will unveil. So remains the question how we can have 2 or more enter animations for one furniture. I don't think we need that. Just use a 0.1 sec idle, and from there jump in the fu sequence to the animation intended for the appropriate char. But if we really should need 2 different enter anims, I think I can add that at a later time. or mor like: sitonchair----idleenterinstant ----idleenter ----idle +> plays sequenced Animations defined in behaviour file ----idleExit I think with the above I have answered your question as well. Yes it will work like in your second list, except that EnterInstant is not an idle, but an AnimEvent, and comes AFTER idleenter (the char can enter instantly, because enter was already played). EDIT: And I wanted to mention that sittarget packages are not the only way to use furnitures. Minin works through a combination of activator and furniture. In one of their scripts, mining animations are started by an Activate().
zax Posted August 29, 2013 Posted August 29, 2013 Well not sure if I understand its mechanism but I think that conditions are checked from top of the list to the bottom (not for sub idles inside block only, but between other "idles groups" as well). Thats why if we set 3 different idle groups with the same keyword as "entry" (like they did with ChoppBlock) its conditions are checked from the first one then if it fits, it plays proper sub-idle and uses appropriate marker. Need confirmation of all of an above^ The keywords I was talking about are marker specific keywords that are supposed to segregate appropriate Actors between specific markers. But after doing some tests: removing keywords "isExecutioner" etc. from ChoppingBlock ("marker keywords" in furniture window) I couldnt get any other result but always 'sitting' on marker 1 (of 0, 1, 2) - tried activation from different directions. As you can observe on "bench" type of furnitures - ie. WRTempleBench01 (Whiterun) it does for sure support and recognize directional activation of markers (you can decide where to sit). Maybe ChoppingBlock is too small object and its collision mesh of marker 1 is covering whole object? No idea. One thing I don't know is, when a furniture has 2 or more markers (like the head chop). What marker will be selected as entry by a char? Certainly one which is not used yet. But others than that I haven't found any parameter to support that. I assume it's simply the (open) entry that is closest to a char. But's that's just an assumption. The way they do it (at least how it was suposed to work) is that they check "isExecutioner" keyword for 1st marker, then "isExecutionerGuard" for other, and if an Actor doesnt have any of these keywords he will be using the last remaining marker. Markers with "isExecutioner" and "isExecutionerGuard" are basically restricted for two specific NPC's. It is how I THINK it works or should work. Because as mentioned above removing these restricting keywords didnt seem to do anything, and is probably being overwritten by ChoppingBlockscript the same way as mining... Also tried (using vanilla only anim events): sitonchair----idleenterinstant ----idleenter ----idleCustom (random idle, IdleKneeling for example) ----idleExit Enter/Exit working as intended, but idleCustom (it had no conditions declared at all) couldnt be called by console (.playidle idleCustom), but idleExit could - why? Is it how furniture SAs are supposed to work? Why vanilla events (like IdleKeeling, IdleSitCrossLegged etc) couldnt be called, but they use some other vanilla idles in ChoppingBlockscript (and why they do it in furniture?)
zax Posted August 29, 2013 Posted August 29, 2013 sitonchair----idleenterinstant ----idleenter ----idleCustom (random idle, IdleKneeling for example) ----idleExit Enter/Exit working as intended, but idleCustom (it had no conditions declared at all) couldnt be called by console (.playidle idleCustom), but idleExit could - why? Is it how furniture SAs are supposed to work? Why vanilla events (like IdleKeeling, IdleSitCrossLegged etc) couldnt be called, but they use some other vanilla idles in ChoppingBlockscript (and why they do it in furniture?) Ok, my mistake - used IdleKneelingEnter AnimEvent (as AnimEvent of idleCustom from an above example) instead of IdleKneeling. - idleCustom (with IdleKneelingEnter event) couldnt be called after already called "idleenter" (with another x-Enter event) - idleCustom (with IdleKneeling event) can be called, but its then sending "OnGetUp" papyrus event, so it practically isnt "sitting" anymore. IdleKneeling event should be considered as furniture type event, why its sending "OnGetUp" event? An above doesnt change the fact that they play idles manually in ChoppingBlockScript instead of triggering them by furniture? (it means that some events can be called in furniture without sending OnGetUp?) I dont know how vanilla Enter EnterInstant Exit events are structured (it looks like FURNITURE1_Enter.hkx FURNITURE1_Loop.hkx are merged in one event? vanilla kneeling behaves exactly like that, it plays enter then loop), + theres probably some animation variables and params, that I dont understand, controlling all of that.
fore Posted August 29, 2013 Author Posted August 29, 2013 Oh yes. I totally missed those keywords for the markers. That's of course a very good reason. I also have a possible explanation why you see no difference after changing the keywords. Maybe it's the same reason why you cannot switch back the "Opposite Gender Anims" options on some female actors once you have met them. The ExecutionerChoppingBlock furniture has a script. So at least for that reason data has to be stored for this object. Which means the data for this might be stored in your save file. But again, just an assumption. Your console playidle tests will not give you any usable results. Because you can consider it as treat IF something LOOKS LIKE it's working. At least there is no connection to any furniture if you do it via console. Furniture idles have a relatively extensive setup (modifiers, variables setting and testing, ...), and calling something in between will certainly miss all of that. IF you are able to do so. Because most of the times the Loop animation isn't called by a specific AnimEvent, but by a generic "00NextClip". IdleKneeling is special, because there are 2 3some animations. One furniture anim activated by "IdleKneelingEnter", and a non-furniture animation activated by "IdleKneeling". So both animations have (almost) nothing in commen. However, the non-furniture version belongs to a tree called "IdleStopIdles", which apparently can stop other furniture animations, and therefore send a 00ResetClip which may cause some side effects you have seen. If you are interested understanding what's happening when AnimEvents are called, I really recommend that you download and use CondenseBehavior. It can save you a lot of unnecessary testing. And with all that you know from your tests I have no doubt that you can easily understand it's information. And if not, you can still ask me.
zax Posted August 29, 2013 Posted August 29, 2013 From what I understood so far: - IdleEnterInstant AE is used by some kind of "wildcardTransitions" which are usually NULLed - wtf is that I dont even? - IdleEnter AE is basically enter + loop animations in one - IdleExit AE is separate exit animation One question, why do you say that Exit is never used? Its never triggered or its translated from IdleChairExit call to proper event inside behavior file (my guess)? ... "#1834" "hkbStateMachineStateInfo" "enterNotifyEvents" #1833 "exitNotifyEvents" #1832 "generator" #1831 "name" ChairDrinkingIdleVar "stateId" 1 "#1833" "hkbStateMachineEventPropertyArray" "id" 20 <!-- HeadTrackingOff --> "#1832" "hkbStateMachineEventPropertyArray" "id" 18 <!-- HeadTrackingOn --> "#1831" "hkbClipGenerator" "name" ChairDrinkingIdleVar "animationName" Animations\male\AnimObjectChairDrinkingIdleVar1.hkx "triggers" #1830 "#1830" "hkbClipTriggerArray" "localTime" -0.200000 "id" 91 <!-- ChairNextClip --> "localTime" 1.842000 "id" 20 <!-- HeadTrackingOff --> "localTime" 4.821000 "id" 18 <!-- HeadTrackingOn --> Could you explain me what triggers what in this example? Is "generator" a trigger or enter/exit NotifyEvents are enabling this state that is then calling "generator" to switch to the next clip via <!-- ChairNextClip --> ? Need help with understanding the structure, this code is so fucked up...
fore Posted August 30, 2013 Author Posted August 30, 2013 Once you are used to read the most common elements I think you will see that this format is not hard to read, at least from it's basic structure. First of all you really need to straighten out you terminology. AEs are not one or two animations. They are events that are sent at one place, and received at another one of the behavior graph's state machine. They can have 2 different purposes: move the behavior graph from one state to another, or inform the engine about certain things (e.g to equip certain AnimObjects) Interesting is purpose (1), because a state change will cause a new animation to play. This is done by a "generator" which directly or indirectly will lead to a "clipgenerator" which denominates the animation. So ONE state-changing AE (1) will always cause ONE animation to play. To be sent, AEs are either "triggered" or "notified". "triggers" are events relative to the begin or end of a clip. "notifies" are raised when a state is started or ended. This differentiation is necessary to know, because notified AEs will not show up in OnAnimationEvent(). To be received, AEs have to be part of a TransitionInfoArray. This TransitionInfoArray either describes specific "transition", which means it describes which AEs will cause a transition from the current state to another specific state. Mostly used in a sequence of animation files to play the next animation. Or it can be a "wildcardtransition" which describes which AE will cause a transition to one of the current sub-trees states, independent of the current state. Mostly used to start a new sequence of animation files. I think this overview answers most of your questions. And when I said that "Exit is never used" I only referred to the Exit event generated by FNIS by this specific furniture animation. Because you should use "IdleChairExitStart" like most vanilla furniture animations. Edit: Maybe the tree structure is important to understand. It starts with a StateMachine (StM). Each StM can have an ARBITRARY number of StateMachineInfos (StMI). Each StMI has a state. States only have to be unique, but only for all direct StMIs of one StM (sub-trees can and will use the same state number). StMIs define "generators", which are either ONE StM (defining a sub-tree), or a ClipGenerator (as leaves). So basically it's StM (root) StMI (state 0) StM (level 2) StMI (state 0) ClipGenerator StMI (state 1) ClipGenerator ....... StMI (state 1) StM (level 2) StMI (state 0) StM (level 3) ........ StMI (state 2) .....
zax Posted August 30, 2013 Posted August 30, 2013 Well, thanks for explaination im in process of understanding it. (read my PM first please) In meanwhile, an offtopic question: what do you know about paired animations? Curious if the reason of everyone not using paired anims is behavior limitation or something else? Are they that much harder to make (2 skeletons in one scene) or what? I found they could be easily called via http://www.creationkit.com/PlayIdleWithTarget_-_Actor I found they are in 0_master.hkx (unfortunately) "#0763" "hkbStateMachineStateInfo" "generator" #0764 "name" Player_HugA "stateId" 59 "#0764" "hkbStateMachine" "variableBindingSet" #0772 "name" Player_HugA_Behavior "startStateId" 0 #0765 "wildcardTransitions" null "#0772" "hkbVariableBindingSet" "variableIndex" 51 <!-- bIsSynced --> "#0765" "hkbStateMachineStateInfo" "generator" #0766 "name" Player_HugA_DisablePitch "stateId" 0 "#0766" "hkbStateMachine" "variableBindingSet" #0771 "name" Player_HugA_H2HSlamA_Behavior "startStateId" 0 #0767 "wildcardTransitions" null "#0771" "hkbVariableBindingSet" "variableIndex" 58 <!-- DisablePitch --> "#0767" "hkbStateMachineStateInfo" "generator" #0768 "name" pa_HugA "stateId" 0 "#0768" "BSSynchronizedClipGenerator" "name" pa_HugA "pClipGenerator" #0769 "SyncAnimPrefix" & #9216; "bSyncClipIgnoreMarkPlacement" false "bApplyMotionFromRoot" false "#0769" "hkbClipGenerator" "name" Paired_HugA "animationName" Animations\Paired_HugA.hkx "triggers" #0770 "#0770" "hkbClipTriggerArray" "localTime" 0.000000 "id" 615 <!-- NPCKillMoveStart --> "localTime" 3.466667 "id" 156 <!-- NPCpairedStop --> "localTime" 3.466667 "id" 616 <!-- NPCKillMoveEnd --> "localTime" 3.466667 "id" 159 <!-- PairEnd -->
fore Posted August 30, 2013 Author Posted August 30, 2013 Yes I know paired animation. I invested a lot of time a year ago. And failed at that time like I did with furnitures. Interestingly they have things in common, like one actor walking to the other before the actual animation plays. And I had the same type of failure as with furnitures. But since I founde the furniture problem, I have good hopes I can make the paired as well. BUT... I have never heard that any modder has made a paired animation. The famous Saidenstorm at the Beth forum had claimed he knew, and has given a sketchy breakdown about what to do, but that's it. So I think, before any animator shows me a working replacer paired animation, I don't think I will invest any more into that. But paired animations would really be the hit. I consider furniture animation only a work-around for paired animations in most (sex mod) cases.
fore Posted September 11, 2013 Author Posted September 11, 2013 To everyone interested in the FNIS 4.0 progress: I know I have been very quiet recently, but I can assure you I have spent as much time I could afford.This "full blown" furniture stuff was/is really a tough thing. So many issues, a complicated behavior structure, and many areas in the generator I had to change and even redesign. I also did some optimizations to ease the mt_behavior size limit a little bit. And not to forget creture stuff that needed some better integration into the whole procedure. But now I can tell that I have the first "full blown" furniture animations created by the generator running. Arbitrary number of single animations per fu, and arbitrary AOs. Of course I need to do a lot of testing now after all those changes, and a few minor things still to fix. But I think I can release a finale beta within 1-2 weeks. Ok, don't panic. I understand that FNIS' beta status has become more and more of an annoyance. So this final beta will only last about 1 more week. To allow modders to switch to the new fu syntax, and give me some time to update documentation (including a better modders' doc), and update the language files with the translators. And fix bugs that modders can find during this time. 1 week only. And then I hope things get REALLY started.
jbezorg Posted September 14, 2013 Posted September 14, 2013 One suggestion I would make is by default always have 2 anim vars on every actor. 0.0 = Not Installed AnimVar FNISversion REAL 4.0 AnimVar FNISCreature REAL 0.0 With this in mind, is it possible to be able to create read only AnimVar's that can only be changed when the behavior file is recreated? Something like. AnimVarReadOnly MaxNodeScale REAL 3.0 AnimVarReadOnly MinNodeScale REAL 0.1 AnimVarReadOnly FNISversion REAL 4.0 AnimVarReadOnly FNISCreature REAL 0.0
jbezorg Posted September 14, 2013 Posted September 14, 2013 if you want to work through anim vars and not update scripts. Pros Compile it once and if the Anim Vars don't change you're done Version defined in one location. FNIS_FNISBase_List.txt ( or FNIS_FNIS_List.txt? ) Cons Slower Scriptname FNIS Hidden float function GetVersion(bool abCreature = false) global if abCreature return Game.GetPlayer().GetAnimationVariableFloat("FNISCreature") else return Game.GetPlayer().GetAnimationVariableFloat("FNISversion") endIf endFunction If you want to avoid using anim vars. Maybe to reduce behavior file bloat?Pros FasterCons FNIS & FNIS Creature would have to have their own copies of the same script though with the chance of a partial reinstall of FNIS leaving the wrong version in the script folder. You'll have to compile new versions with each update to FNIS. Scriptname FNIS Hidden float fnisBase = 4.0 float fnisCreature = 0.0 float function GetVersion(bool abCreature = false) global if abCreature return fnisCreature else return fnisBase endIf endFunction
fore Posted September 14, 2013 Author Posted September 14, 2013 One suggestion I would make is by default always have 2 anim vars on every actor. 0.0 = Not Installed AnimVar FNISversion REAL 4.0 AnimVar FNISCreature REAL 0.0 With this in mind, is it possible to be able to create read only AnimVar's that can only be changed when the behavior file is recreated? Something like. AnimVarReadOnly MaxNodeScale REAL 3.0 AnimVarReadOnly MinNodeScale REAL 0.1 AnimVarReadOnly FNISversion REAL 4.0 AnimVarReadOnly FNISCreature REAL 0.0 I liked the idea. But I can only realize one part, and it's not as easy to use as it looks like. Keep in mind that Animvars are no FNIS "invention", they are simply translated into Behavior variables. So I have to use what they provide. What I can do is define "AnimVar FNISversion REAL 4.0" right away as part of FNISBase\FNIS_FNISBase_List.txt. This will add this variable to behaviors\FNISBase\FNIS_FNIS_Base_Behavior.hkx and define FNISversion for every character, PC and all NPCs. But to do the same for every creature, I would have to add a mod every creature. 49 mods just to define the version? I don't know if you or your users really want that. Or make a third default mod (FNISCreature) just for characters? Might confuse many. There is also no possible attribute ReadOnly. HBT or the behavior data simply doesn't provide that. A comparison with a REAL version number will work at the most for versions like 4.0, 4.5. You cannot exactly represent 4.1 with a real number. So it's unpredictable if the comparison of 2 real 4.1 numbers, one defined as Animvar in behaviors, and one as papyrus script variable will match. Needs to be tested. But what about 4.1.1? In other products I have seen solutions with several integers, like VersionMajor, VersionMinor1, VersionMinor2. But is this what you want?
jbezorg Posted September 14, 2013 Posted September 14, 2013 I liked the idea. But I can only realize one part, and it's not as easy to use as it looks like. Keep in mind that Animvars are no FNIS "invention", they are simply translated into Behavior variables. So I have to use what they provide. What I can do is define "AnimVar FNISversion REAL 4.0" right away as part of FNISBase\FNIS_FNISBase_List.txt. This will add this variable to behaviors\FNISBase\FNIS_FNIS_Base_Behavior.hkx and define FNISversion for every character, PC and all NPCs. But to do the same for every creature, I would have to add a mod every creature. 49 mods just to define the version? I don't know if you or your users really want that. Or make a third default mod (FNISCreature) just for characters? Might confuse many. There is also no possible attribute ReadOnly. HBT or the behavior data simply doesn't provide that. A comparison with a REAL version number will work at the most for versions like 4.0, 4.5. You cannot exactly represent 4.1 with a real number. So it's unpredictable if the comparison of 2 real 4.1 numbers, one defined as Animvar in behaviors, and one as papyrus script variable will match. Needs to be tested. But what about 4.1.1? In other products I have seen solutions with several integers, like VersionMajor, VersionMinor1, VersionMinor2. But is this what you want? If it's available from the player actor that's sufficient I think. Last option would also work. A fourth parameter can be used for bit flags for any yes/no questions about the current build you want to pass on to the modder. AnimVar FNISmajor INT32 4 AnimVar FNISminor INT32 0 AnimVar FNISbuild INT32 3 AnimVar FNISflags INT32 2 Then this for scripting Scriptname FNIS Hidden ; e.g. ;AnimVar FNISmajor INT32 4 ;AnimVar FNISminor INT32 0 ;AnimVar FNISbuild INT32 3 ;AnimVar FNISflags INT32 2 int property ISALPHA = 1 autoreadonly int property ISBETA = 2 autoreadonly ; call FNIS.GetVersion() string function GetVersion() global actor kPlayer = Game.GetPlayer() return kPlayer.GetAnimationVariableInt("FNISmajor") as String \ + "." + kPlayer.GetAnimationVariableInt("FNISminor") as String \ + "." + kPlayer.GetAnimationVariableInt("FNISbuild") as String endFunction ; call FNIS.GetMajor() int function GetMajor() global return Game.GetPlayer().GetAnimationVariableInt("FNISmajor") endFunction ; call FNIS.GetMinor() int function GetMinor() global return Game.GetPlayer().GetAnimationVariableInt("FNISminor") endFunction ; call FNIS.GetBuild() int function GetBuild() global return Game.GetPlayer().GetAnimationVariableInt("FNISbuild") endFunction ; call FNIS.GetFlag(FNIS.ISBETA) Bool function GetFlag( int aiFlag ) global return Math.LogicalAnd(Game.GetPlayer().GetAnimationVariableInt("FNISflags"), aiFlag) as Bool endFunction FNIS.7z
jbezorg Posted September 15, 2013 Posted September 15, 2013 Crap... Do anim vars persist with the save? If so, the all of the above won't work.
fore Posted September 15, 2013 Author Posted September 15, 2013 Crap... Do anim vars persist with the save? If so, the all of the above won't work. You don't change those animvars, so they stay as they are as part of the behavior files. That's not a problem. One problem could be that providing scripts requires an esp/esm. And I don't really want to do that just for versioning.
Ashal Posted September 15, 2013 Posted September 15, 2013 Global functions like that don't require an esp/esm, since they aren't attached to anything.
jbezorg Posted September 15, 2013 Posted September 15, 2013 Silent version. Tested in FNIS 4.0 Beta 3. This will not pollute the Papyrus Log file with errors when the anim var is not found. Scriptname FNIS Hidden ; silence the Papyrus log ===================================================== bool[] function getPapyrusDebugState() global bool[] bDebugState = new bool[3] bDebugState[0] = Utility.GetINIBool("bLoadDebugInformation:Papyrus") bDebugState[1] = Utility.GetINIBool("bEnableTrace:Papyrus") bDebugState[2] = Utility.GetINIBool("bEnableLogging:Papyrus") return bDebugState endFunction bool[] function getPapyrusDebugSilent() global bool[] bDebugState = new bool[3] bDebugState[0] = false bDebugState[1] = false bDebugState[2] = false return bDebugState endFunction function setPapyrusDebugState( bool[] bDebugState ) global Utility.SetINIBool("bLoadDebugInformation:Papyrus", bDebugState[0]) Utility.SetINIBool("bEnableTrace:Papyrus", bDebugState[1]) Utility.SetINIBool("bEnableLogging:Papyrus", bDebugState[2]) endFunction ; FNIS Versioning ============================================================= ; call FNIS.GetVersion() string function GetVersion( bool abFailSilent = true ) global actor kPlayer = Game.GetPlayer() bool[] bDebugOff = FNIS.getPapyrusDebugSilent() bool[] bDebugState = FNIS.getPapyrusDebugState() if abFailSilent FNIS.setPapyrusDebugState( bDebugOff ) endIf string ret = kPlayer.GetAnimationVariableInt("FNISmajor") as String \ + "." + kPlayer.GetAnimationVariableInt("FNISminor") as String \ + "." + kPlayer.GetAnimationVariableInt("FNISbuild") as String if abFailSilent FNIS.setPapyrusDebugState( bDebugState ) endIf return ret endFunction ; call FNIS.GetMajor() int function GetMajor( bool abFailSilent = true ) global bool[] bDebugOff = FNIS.getPapyrusDebugSilent() bool[] bDebugState = FNIS.getPapyrusDebugState() if abFailSilent FNIS.setPapyrusDebugState( bDebugOff ) endIf int ret = Game.GetPlayer().GetAnimationVariableInt("FNISmajor") if abFailSilent FNIS.setPapyrusDebugState( bDebugState ) endIf return ret endFunction ; call FNIS.GetMinor() int function GetMinor( bool abFailSilent = true ) global bool[] bDebugOff = FNIS.getPapyrusDebugSilent() bool[] bDebugState = FNIS.getPapyrusDebugState() if abFailSilent FNIS.setPapyrusDebugState( bDebugOff ) endIf int ret = Game.GetPlayer().GetAnimationVariableInt("FNISminor") if abFailSilent FNIS.setPapyrusDebugState( bDebugState ) endIf return ret endFunction ; call FNIS.GetBuild() int function GetBuild( bool abFailSilent = true ) global bool[] bDebugOff = FNIS.getPapyrusDebugSilent() bool[] bDebugState = FNIS.getPapyrusDebugState() if abFailSilent FNIS.setPapyrusDebugState( bDebugOff ) endIf int ret = Game.GetPlayer().GetAnimationVariableInt("FNISbuild") if abFailSilent FNIS.setPapyrusDebugState( bDebugState ) endIf return ret endFunction ; FNIS Version Flags ========================================================== int property ISALPHA = 1 autoreadonly int property ISBETA = 2 autoreadonly ; call FNIS.GetFlag( ([mymod] as FNIS ).ISBETA ) Bool function GetFlag( int aiFlag, bool abFailSilent = true ) global bool[] bDebugOff = FNIS.getPapyrusDebugSilent() bool[] bDebugState = FNIS.getPapyrusDebugState() if abFailSilent FNIS.setPapyrusDebugState( bDebugOff ) endIf bool ret = Math.LogicalAnd(Game.GetPlayer().GetAnimationVariableInt("FNISflags"), aiFlag) as Bool if abFailSilent FNIS.setPapyrusDebugState( bDebugState ) endIf return ret endFunction BSA in attached 7z FNIS.7z
jbezorg Posted September 15, 2013 Posted September 15, 2013 Separated Papyrus functions from FNIS. ; call FNIS.GetMajor() int function GetMajor( bool abFailSilent = true ) global bool[] bDebugOff = Papyrus.getDebugLogSilent() bool[] bDebugState = Papyrus.getDebugLogState() if abFailSilent Papyrus.setDebugLogState( bDebugOff ) endIf int ret = Game.GetPlayer().GetAnimationVariableInt("FNISmajor") if abFailSilent Papyrus.setDebugLogState( bDebugState ) endIf return ret endFunction FNIS.7z Papyrus.7z
jbezorg Posted September 15, 2013 Posted September 15, 2013 http://www.loverslab.com/files/file/350-papyrus-utilities/
fore Posted September 15, 2013 Author Posted September 15, 2013 Excellent. So let's do it. Now do you want me to pack that with FNIS, or do you want to keep it at LoversLab? Both is ok with me. And both proceedings have advantages. Especially here you can update much faster. I try to reduce the number of FNIS releases as much as I can. But in any case I ask you for a few lines of documententation. Including authorship and link (if you want me to pack that with FNIS, please do a fuzzy link, like "Lovers-Lab" with explanation to remove the "-". A well-know fellow-modder at Nexus was just banned for one month for distributing an "illegal" link). If you keep the scripts here I would use this for the modder's doc, which I will distribute as pdf in the future.
shane4244 Posted September 16, 2013 Posted September 16, 2013 I just wanted to take a moment to thank you for making animations in skyrim possible. I don't like to single people out because its impossible to thank everyone for thier contributions, but I'll make an exception in this case. You manged to come up with a way to add animations to skyrim that works and works well so that others can create frameworks and mods around said system. It's one of those background apps like skse that no one really thinks about when there playing there game but without it what there playing would not be possible. In the interest of keeping it short I'll just say thanks and creature support has been a long requested feature thank you for bringing it to lovers lab. I'll let you get back on topic.
fore Posted September 16, 2013 Author Posted September 16, 2013 I'll keep it short too, shane. Thanks for the nice words.
jbezorg Posted September 16, 2013 Posted September 16, 2013 Excellent. So let's do it. Now do you want me to pack that with FNIS, or do you want to keep it at LoversLab? Both is ok with me. And both proceedings have advantages. Especially here you can update much faster. I try to reduce the number of FNIS releases as much as I can. But in any case I ask you for a few lines of documententation. Including authorship and link (if you want me to pack that with FNIS, please do a fuzzy link, like "Lovers-Lab" with explanation to remove the "-". A well-know fellow-modder at Nexus was just banned for one month for distributing an "illegal" link). If you keep the scripts here I would use this for the modder's doc, which I will distribute as pdf in the future. I'll supply a copy without the Papyrus utilities. It's possible that multiple calls to a function that use those utilities in a threaded environment can turn off the papyrus log.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.