Jump to content

testiger2

Members
  • Posts

    78
  • Joined

  • Last visited

Everything posted by testiger2

  1. what you can try (don't know if its the best solution): create a perk, add an ability to the perk and one perk entry point let the EP mod the magic cost of the spell set cost to something really high like 100000 or so and then put in the contition with GetItemCount == 0. this will make you unable to cast the spell when you dont have the gem because the spell cost is too high. also add a keyword to your spell and use the EPMagic_SpellHasKeyword condition so it only tracks you spell for the ability add a script that extends activemagiceffect and then use OnSpellCast to track when the spell is fired. you will propably want a good amount of optimizations here because this could get resource intensive otherwise. maybe there is an easier solution for this or you can dump this if you are willing to live with removing the gem only when a target is hit
  2. Hello everyone, i am wondering if Texture Sets can be used on Art Objects(ARTO). So far i was not able to make them work together. When i apply the Set in the CK it shows correcty but the changes will not apply ingame. Its been a while but i remember reading that there was a similar issue with female 1stPerson models on the ArmorAddon. Is this a similar issue or may it be something else?
  3. Well maybe i could have worded my initial question a bit better. Of course the savegame will not contain the actual scripts. The question could have been better worded this way: If you have an emtpy dummy script(meaning no vars/props whatsoever) will the script's reference still be baked into the save? If we we assume an unbugged script.
  4. So i looked into it a bit and id like to conclude a little summary in the way i understand it. -- Inside the save's papyrus sections we have to sections that are of importance: - The saved/baked strings, called stringList from here on - The saved/baked script instances, called instanceList from here on For the sake of this writeup i will from here on refer to the count of stringList as stringcount and to the count of instanceList as instancecount. We(i) already know that stringList is limitied to a reach of an uInt16 which stops at 2^16-1 meaning ~65k entries So we could assume that instanceList is also limited to about ~65k entries. Question: Yes/No ? Question2: Does breaking the limit of instanceList also break saves or is this exlusive to breaking stringList's count? Lets first examine stringList ----------------------------- One thing i immediately noticed is that stringList does not contain any duplicates. Meaning vars/props get stored in stringList as a per string and not per script basis. So if 2 or more scripts contain a variable like int iVarSomethingSomething = 1then the name of "iVarSomethingSomething" will only be added once no matter how many scripts use the same variable name. The same rule applies if the same script is instanced to multiple objects. And the same rules also apply to the script names themselves. So to answer OP's (my) initial question: when using a dummyscript like ScriptName SomethingScript extends Form you increase the stringcount by exactly 1. Doesn't matter where or how often it is attached or instanced. Another important info i gathered is that literals can also bake. In my testing i found several string literals (and even some integer literals) A little string array init like Pages = new string[3] Pages[0] = "$General" Pages[1] = "$Favorite Groups" Pages[2] = "$Advanced" can increase the stringcount up to 4. The array itself uses 1 entry but initialising every entry can quickly rile up stringcount. I guess this is what @ReDragon2013 refered to in an earlier post when he mentioned active scripts Question: Is this behaviour limited only to active scripts ? Question2: Do editor filled arrays behave the same? Time to test...later Now lets look into instanceList ------------------------------- As the name instanceList suggest this list stores the script instances in the save. This goes per script Example: If you create 2 ObjectReferences that contain the same script you will increase the instancecount by 2. If you create 2 ObjectReferences and add 2 scripts each you increase the count by 4 etc. Going by this extending ObjectReference and Actor (both which are Instances of base forms by design) should be used with care. Baseforms should increase the instancecount on a per Formid/EditorId basis. Example if you add a script that extends a baseform class you increase the count by 1 no matter how many instances of it you create. Question: Does the same script that is attached to objs with different Formids increase count further? Time to test...later -- The above summary just mirrors my findings from playing around with save editors a bit and may not be accurate. If you have more in-depth info on this topic please chime in and correct me where my observations are wrong or add into it.
  5. Hi people, i have a quick question about scripts in regard to the string count in the save game. Now as far as i know functions and properties (apart form AutoReadOnly) will bake into the savegame and increase the stringcount. What about the scripts themselves? If i say add an empty dummy script to an object will that bake and increase the count?
  6. What mechanic is used to teleport the horse to the player? If its just a follow package i'd just add a quest with a dialog option like "Stay here" or something and then just update the package through the fragment. Now you can strategically place mounts all over the world. If it is controlled by a package that is...
  7. All of those suggestions are valid and lead to the desired result. Its just a question of what you (or OP in this case) want. Direct edits are always gonna be faster than any dynamic solution but come at the cost of possible incompatibility. Onhit() on player is very expensive and is best avoided when possible. For cloaking it depends how expensive they are. They can be moderately cheap with proper management but can also be very expensive if the conditions are not waterproof or there are too many actors affected.
  8. I think the Onhit() solution might be a little costly in terms of performance. One possible other solution if you are ok with editing the vanilla diseases: Locate the disease spell of choice (for example ataxia for skeever) and then remove all magic effects and add a list of filter/placeholer magiceffects Make the magic effect's type FireAndForget and set the duration to like 10 seconds or something Then add a script to each magic effect such as Scriptname DiseaseApplyFilterScript extends ActiveMagicEffect Spell Property DiseaseToApply Auto Event OnEffectStart(Actor akTarget, Actor akCaster) akTarget.AddSpell(DiseaseToApply) EndEvent Fill the property of DiseaseToApply DiseaseToApply will link to one of the actual diseases. Then you can use conditions on these placeholder effects to your hearts content inside the spell tab or inside the magic effect tab of the filtereffect. Use GetRandomPercent, GetRace, etc. This approach is way more performant as it does't need the costly Onhit() Event and also you don't need multiple scripts or check every possible condition like race through the script. Just let the default condition system handle it for you.
  9. @ OP If you are new to nifskope setting up the animation sequence(s) can be a little tricky but there are a few tutorials out there on how to do it. I don't have any links on hand right now but you should be able to find it by googling some of the Block names like NiControllerManager, NiTransformColloer or some of those. You could also look at the meshes for the magic spells (shockhandeffects.nif for example) that give you an idea on how the nif would be set up. The Netimmerse method is definetly easer, basically copy-paste. @maxarturo You can animate the textures in a .nif to some degree, you could make a tileable texture and then animate the UV coordinates (flame atronach mesh does this for example). If you were to use only 2 frames you could achieve a texture change effect As for NetImmerse.SetNodeTextureSet() - This would also work, but i don't know if this function changes the textures only for that ObjectReference or for all instances of the mesh. I have not used this function before but i know that the Node-Transform-functions only affect the specific ObjectReference so this might also be the case for SetNodeTextureSet(). Could be that you also need to call QueueNiNodeUpdate() for the effect to appear right away. I don't think you need any of those methods though. Since you are using an Actor the mesh is essentially an armor that you can equip. Naked body meshes are also armors to the game they are just flagged as unplayable so you don't have them in the inventory. So what i would do is to create a copy of the Actors armor, then give it the new texture set in the CK and then simply use Actor.EquipItem at any point through papyrus. How you track the combat state change is up to you there are dozens of ways for it. Maybe layer in a magic effect with some shader effects for the transition an thats it.
  10. Well here is my take on it First of all i think you should use papyrus states instead of three different scripts and then You can combine the 3 mesh states into the same .nif actually. I know of 2 ways to achieve this with Nifskope (3 ways if you are ok with using only 2 states) First method do this by putting each sub-mesh up into an animation sequence using a set of NiVisControllers and NiBoolInterpolators Then you call PlayGamebryoAnimation() from your script when you change the state. Alternative to this if you are not comfortable with the animations you can fake the visibility by using NetImmerse.SetNodeScale() with a value of 0 and 1 on your object. For this you Create 3 new NiNodes, give them the names of your states and make each sub-mesh a child node of one of those three. Then when you want to change the mesh state you call SetNodeScale(self,"nameOfNodeToHide",0.0) and SetNodeScale(self,"nameOfNodeToUnhide",1.0) This method requires SKSE The third option is to use the mechanic the game uses for harvestable plants but this only allows for 2states on/off By doing this you end up with a single object that can transform into whatever and you don't need to track multiple ones etc.
  11. Well quite a lot of the armor mashups from the earlier days of skyrim modding use a workaround method instead of using 'proper' 3d editing. The method works by throwing a number of armor meshes together in nifskope and then hiding the parts you don't want by using alpha channels in the textures. This is the dirty way of doing it and has a few major drawbacks. - Because the geometry is not removed and just hidden by the alpha the game needs to process said geometry -> bigger performance hit - Seperate Alpha channel > Seperate Texures > No compatiblity for retexture mods out of the box - Shaders like blood effects etc. may conform to the hidden geometry and cause the effects to float in the air for example Well the obvious path if you want to fix this is by importing the meshes into your 3d program of choice and then start chopping away the actual geometry. In this special case i think Outfit Studio is your best tool for this. It has a feature called 'Zap Sliders' (or something like it) that lets you paint a mask onto the mesh(es) and when you export your file, the geometry hidden by the mask will be completelöy removed. This is exactly what you need for this and should be the easier way versus using blender or 3ds max
  12. Well i found out that even though OnSpellCast() fires from using scrolls it will always receive a 'none' as the argument. So you can't just use it the regular way. i created a workaround using GetItemCount(). Its an unelegant solution , dirty, i would dare to call it filthy, but it should work (not tested it though) [spoiler] Actor Property PlayerRef Auto Formlist Property usedScrollsFLST Auto ; create this and give unique name in the CK Form[] usedScrollsArr int[] usedScrollCount int iCurrScrollCount = 0 Event OnInit() usedScrollsArr = new Form[4] ;4possible quip types usedScrollCount = new int[4] EndEvent Event OnObjectEquipped(Form akBase, ObjectReference akRef) if akBase as scroll int i = usedScrollsArr.Find(akBase) if i < 0 i = usedScrollsArr.Find(none) endif usedScrollsArr[i] = akBase usedScrollCount[i] = usedScrollCount[i] + 1 usedScrollsFLST.AddForm(akBase) iCurrScrollCount = PlayerRef.GetItemCount(usedScrollsFLST) if usedScrollsFLST.GetSize() > 0 && GetState() == "" GoToState("ScrollState") endif endif EndEvent Event OnObjectUnequipped(Form akBase, ObjectReference akRef) if akBase as scroll Utility.Wait(0.1) ;give OnSpellCast() time to fire int i = usedScrollsArr.Find(akBase) if i >= 0 usedScrollCount[i] = usedScrollCount[i] - 1 if usedScrollCount[i] == 0 usedScrollsArr[i] = none usedScrollsFLST.RemoveAddedForm(akBase) endif endif if usedScrollsFLST.GetSize() == 0 && GetState() == "ScrollState" GoToState("") endif endif EndEvent State ScrollState Event OnSpellCast(Form akSpell) int iOldCnt = iCurrScrollCount iCurrScrollCount = PlayerRef.GetItemCount(usedScrollsFLST) if iOldCnt > iCurrScrollCount ; we casted a scroll ;do stuff here endif EndEvent EndState [/spoiler] Because of DualWiedling and because of a bug in IsEquipped() that doesn't let you track items in the off hand properly(yeah why would anything work like its supoosed to...) i created this array setup that should in theory respect and track dualwielding the same or different kind of scrolls properly
  13. Instead of OnItemRemoved() you could just use OnSpellCast() this event will fire for scrolls something like this could work for you Keyword Property VendorItemScroll Auto int iScrollCount = 0 Event OnObjectEquipped(Form akBase, ObjectReference akRef) if akBase.HasKeyword(VendorItemScroll) iScrollCount += 1 if iScrollCount > 0 && GetState() == "" GoToState("ScrollState") endif endif EndEvent Event OnObjectUnequipped(Form akBase, ObjectReference akRef) if akBase.HasKeyword(VendorItemScroll) iScrollCount -= 1 if iScrollCount == 0 && GetState() == "ScrollState" GoToState("") endif endif EndEvent State ScrollState Event OnSpellCast(Form akSpell) if akSpell.HasKeyword(VendorItemScroll) ;do stuff here endif EndEvent EndState Note that you could just use OnSpellCast() alone but i added in some state tracking so you don't overrun the papyrus engine by checking everey spell cast but only when the player has actually equipped a scroll. The OnObjectUnequipped() event will fire when the player used up all spells/scrolls in the equipped slot
  14. Ok it's just like i suspected. You have more than 1 channel in your uvw modifiers. If you want the mesh to stay in 1 piece you need to move all uv mappings to a single channel. You would have to unwrap again anyway because they are poorly unwrapped atm. Also it's better to move the uvw modifier below the skin modifier or collapse it to the mesh. It will save a bit of headache for when you later want to add a BSDismember modifier. That modifier is a little diva and does not like if there are any modifiers above it or between it and the skin modifier. Hope this helps
  15. 1) What Plugin Version do you use? 2) What Game are you exporting for? 3) Can you upload your .max file? I can have a look at it
  16. 1) You already have Auto Properties in your script. You Can treat Auto Properties as variables with outside accsess. Meaning they provide the same functionality as variables but can be accessed by other scripts or the CK. I think you misunderstand the way the instancing works When you attach a script to an object it receives one instance of the script but not multiple. When you create multiple instances of said object they each get a independant instance of the script. When you happen to spam the activate button there are not multiple instances beeing called but the same instance calls the OnActivate event multiple times. This is why you want to use a lock variable - user spams button - 1st iteration of OnActivate gets called, the following are queued - 1st iteration sets lock = true and proceeds - 2nd, 3rd, etc iteration enters OnActivate and sees lock == true -> skips locked code and leaves ( does nothing) - 1st iteration finishes and sets locked = false 2) The examples where you want to eliminate functions i gave you are very specific cases and may have been a bit misleading. It is best-practice to keep your code in small logical functions that have a specific task. Your BuyMenu and Deletall functions were totally fine in that regard. When i mentioned the overhead on small functions i meant the ratio between the function statement and the actual code. So while very short functions may produce more overhead in relative terms, very large functions still produce more overhead in absolute terms. Again this falls under the case of mirco-optimization and you should worry about the functionality of your code befor this. There is a phrase in programming saying: premature optimization is the root of all evil
  17. instead of self.Disable() use a boolean toggle or use states something like this would work boolean lock example: bool bLocked Event OnActivate() if !bLocked bLocked = true ; lock OnActivate() to prevent spamming ; rest of code goes here ; use bLocked = false to unlock endif EndEvent About the function question: Of course using functions has its pros and cons but most of the time it is perfectly fine to use functions even when they are only called once in your script. A few situations come to mind where you might want to avoid them: - you need to keep the string count down (every function increases the string count in the save) should be of no concern in most cases unless you add hundres or throusands of functions with your scripts - avoid overhead there may be times where you have resource intensive tasks (while loops for example) where you are better off not using functions. Generally speaking function statements increase the amount of instructions the cpu has to process (start/exit adress, function parameters etc. google function overhead if you want an in depth explanation) This is normally not a problem for bigger functions but on small functions the overhead may even outweigh the actual function and you are better of just using a direct statement if speed is of concern (keyword micro-optimization) The Papyrus engine is also fps-linked. That means that per thread a maximum of 1 function call per frame can be made. So to sum it up: Your example should be fine using functions. You can avoid functions where speed is priority but in speed is that much of a priority you most likely will find other bottlenecks in your code before this one. And don't forget that you also have to read your code or may want others to read your code. One function line is often easier to read that big a block of text (in your script for example)
  18. Check if the Skinned flag in the BSLightningShaderProperty is properly checked.
  19. This is not necessarily a texture issue. It can also stem from the mesh. When the verteces along the UV-seams are not welded you end up with a result like this. This is because you then have 2 sets of normals along the borders which creates this hard-egde effect. OR This could also be a case of texture bleeding. If thats the case you can try editing the textures to add some padding to the UV-islands. (you will have to edit all textures - diffuese, normal, etc,) explanation link: http://wiki.polycount.com/wiki/Edge_padding
  20. You now that there is a mega thread specifically for requesting/offering voice-acting right? https://forums.nexusmods.com/index.php?/topic/951656-the-voice-actors-of-skyrim-nexus/
  21. Try this: create a copy of the magic effect and set it to script type this will be a dummy effect and will only be used to trigger the script events remove the scripts from the original effect leave the old effect as peak value modifier add both of your magic effects to the potion both with the same magnitude set the condition on the dummy to hasMagiceffect(originalEffect) > 0 This means whenever you already drank the potion (and thus receive the originalEffect) only your dummy effect will trigger and you can use the script Events
  22. 1) make a new property in your script xxNameOfScriptYouWantToAccess Property mScript Auto * mScript.myproperty = value ** Or mScript.myFunction() ** * xxNameOfScriptYouWantToAccess is the name that is written behind Scriptname right on the header of the script and not the name of the .psc file When you create a new script you essentially create a new object class along with it and you can then fill the property in the CK to obtain an actual object within your script ** Since you now have an object you can access any properties and functions like you would do with any other object you can't convert a float to a global or vice versa. You make a global in the CK and use it as a property and then use .GetValue() and .SetValue() on the global to work with them. These methods return/request float values though. Also Read the Wiki https://www.creationkit.com/index.php?title=Variables_and_Properties 2) AutoCloseDoorDelayFlags() and AutoCloseDoorDistanceFlags() do exactly the same you only need 1 and can delete the other You can then rewrite that function so that it takes a float int Function AutoCloseDoorDelayFlags(float fArg) if ( fArg ) ;float is implicitly cast as a bool here where 0 equals false and everything else means true return OPTION_FLAG_NONE else return OPTION_FLAG_DISABLED endif EndFunction you can then call that function like you did with other functions in your script already AutoCloseDoorDelayFlags(AutoCloseDoorDistance.GetValue()) 3) the slider is initialized with this function AddSliderOption("Delay", AutoCloseDoorDelay.GetValue(), AutoCloseDoorDelayFlags()) you pass AutoCloseDoorDelay.GetValue() as the initial value which likely is 1 by default and then when OnSliderOptionAccept() gets calles later you update the value and thats why it will show the correct value the next time I would suggest converting all your AutoReadOnly Properties to Auto and then initialize them with a seperate function on the OnPageReset() event something like this function initVArs() variable1 = global1.GetValue() variable2 = global2.GetValue() ;etc endfunction then instead of calling the globals everytime you call your variables directly which also has the advantage of beeing a bit faster Or if you are comfortable with some "advanced scripting" you can link your variables and the globals through defining custom properties as it is explained here: https://www.creationkit.com/index.php?title=Property_Reference
  23. I don't think you'd explicitly get permissions from the voice actors though. Look at it this way if you simply extract the voice files, throw them into some audio software and cut and piece them back together thats totally fine and there are mods that do exactly this without getting into legal trouble. If you would need to get permission for every game asset individially in order to modify it most mods couldn't/wouldn't exist as they do. Plus i'm asking myself this: Aren't you actually creating independent content by using this technology? I mean technically you aren't building on top of existing creations but using is as a template or reference in this case. You are not taking the original files and modify them but rather look (or hear) at the originals and imitate them. Analogy: If i want to port some kind of Asset from another game into skyrim (say a weapon from WoW) i would get in trouble. But if i use said weapon as a reference and create my own Version of it from scratch that would be allowed. It could look exactly the same but it would still pass as my creation. And please don't use this as legal advice, i just want to share my views on it and i welcome others to join the discussion
  24. Now first of all let me share what i have found out about attaching nifs to nodes there are 2 methods that look the same but behave a little different: AttachT Method ------- NiStringsExtraData named AttachT ---NiStringS - don'T overlook the s Array[1] = NamedNode& nameofTheNode* works with ---------- as NiNode and BSFadenode OK Magic Hit Effect Art -OK ArmorAA -Niet only workts in nistringSextradata in array can be pointed to custom nodes added through either ARMA/ARTO** PRN Method ------- NiStringExtraData - without the s, this is not an array named PRN text = nameOfTheNode* works with ------------ as NiNode and BSFadenode OK Magic Hit Effect Art -NIET ARmorAA -OK can be pointed to custom nodes added through either ARMA/ARTO** *This is the name of the bone/node you want to attach the nif to (ex: for pelvis use: NPC Pelvis [Pelv] **You can add a new node with one nif and with another nif point to this new node if the actor has the effect/armor eqipped If you use the wrong ExtraData for the wrong job or if your ExtraData has spelling errors this will result in the effect beeing moved to the pivot For the animation issue you can look at some of the vanilla files to see how they work. some work just as you want your effect to work as well for example Data\meshes\magic\frostbarrier01.nif has 3 sequences called: mBegin --when the MagicEffect starts, mLoop, -- loop, mEnd - when the magicEffect ends So you could use that as a template and replace those 3 with your animations Google for NiControllerManager, NiControllerSequence or NiTransformController, there are a few tutorials/docs on how to use them (i don't have the links on hand) I hope this helps a little
×
×
  • Create New...