Myst42 Posted November 29, 2014 Posted November 29, 2014 Hello again A few weeks ago I was doing a medusa race Got interrupted by new mass install and now I started working again Thing is, It's probably on my best interest to use blockhead on some stuff I have For example: -Snake tails for medusa race -Got my hands on khajiit paws and raptor claws I mixed with HGEC, Robert's Male v5 and ZKEC type bodies I'd like to eventually use on the future to make beast race models. Hooves are also in the collection -Pic related cause that's what' khajiits should look like I'm trying to wrap my head around Blockhead to make it work: It says I must place files in Meshes/Characters/BodyAssetOverrides/PerRace/M-F Then rename files to (RaceName)_(BodyPart).nif And that supposedly will make the game target new files in those folders under those names Question: Does it work on complete body part redirections? I.E target everything looking for "foot" and "lowerbody" to new file, or it works only for nude models? In other words is it possible to use it so when playing Khajiit I get the paws mesh when nude and get the pawed boots when using boots? Also, if possible, how? If I rename files, there's no room for armor folder name, just race and body part ---------------------------------------------------------------------- Tried looking at that "setbody reloaded blockhead edition" mod The old one used to work by a script and token replacement Couldn't make sense of the new one as I can't find where is the part where it redirects models to "Bombshell" folder ----------------------------------------------------------------------- Considering that maybe blockhead and setbody only work for nude models, I collected a mod which allows to redirect clothing models called SetBody Expanded, works by adding "factions" and you can have alter "meshes" folder named after said factions How could I make an automated function for it when playing beast races? ---------------------------------------------------------------------- Lastly I tried taking a look at another mod "Tamago Setbody Reboot" which does everything I wish happen with races but with pregnant women One would try to make the condition for mesh swap to be "IsRace" instead of "IsPregnant" right? Just drawing lines here cause my work juice ran out and I couldn't make sense of them scripts either ----------------------------------------------------------------------- Don't wanna give up yet But I'm clueless Can I do this? How? Could you guys explain any of this stuff please? What do I need to do, how do I do it and where do I learn to do it?
Symon Posted November 29, 2014 Posted November 29, 2014 The Blockhead documentation could do with some more examples. It's easy to get wrong so nothing seems to be happening. It doesn't help that what examples there are are for vanilla meshes and textures which almost no-one uses!!!! Basically, texture swaps always occur. So if you designated Imperials to always use a tattooed skin, you'll see those tattoos even with armour. Meshes however are NOT used in place of armour. If you give all male Argonians erections, this will only be seen if they drop their trousers. It also doesn't spell out that you need to refer to the base ref, so for the player 00000007 (player) NOT 00000014 (playerref) Some examples to help (my machines paths, adjust for your own):- Meshes This overides the players lowerbody mesh E:\Oblivion\Data\meshes\Characters\BodyAssetOverrides\PerNPC\oblivion.esm\00000007_lowerbody.nif This for a particular PC E:\Oblivion\Data\meshes\Characters\BodyAssetOverrides\PerNPC\sonia.esp\000008EE_upperbody.nif Textures This overides the players whole body skin E:\Oblivion\Data\Textures\Characters\BodyAssetOverrides\PerNPC\Oblivion.esm\00000007_foot.dds All female Imperials E:\Oblivion\Data\Textures\Characters\BodyAssetOverrides\PerRace\F\Imperial_foot.dds A Script Example scn asxsfsetaroused;UpperBody – 2;LowerBody – 3;Hand - 4;Foot - 5;Tail - 15ref actorshort levelshort npcfemaleshort u3dbegin function {actor, level, u3d} set npcfemale to actor.getissex female if level == 0 actor.ResetBodyAssetOverride 2 2 actor.ResetBodyAssetOverride 3 2 printc "ASX: aroused off 0" elseif level == 1 if npcfemale == 1 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedub1.nif" 2 2 else actor.SetBodyAssetOverride "Characters\asx\m\asxaroused1.nif" 3 2 endif printc "ASX: aroused on 1" elseif level == 2 if npcfemale == 1 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedub1.nif" 2 2 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedlb2.nif" 3 2 else actor.SetBodyAssetOverride "Characters\asx\m\asxaroused2.nif" 3 2 endif printc "ASX: aroused on 2" elseif level == 3 if npcfemale == 1 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedub1.nif" 2 2 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedlb3.nif" 3 2 else actor.SetBodyAssetOverride "Characters\asx\m\asxaroused3.nif" 3 2 endif printc "ASX: aroused on 3" elseif level == 4 if npcfemale == 1 ; correct this actor.SetBodyAssetOverride "Characters\asx\f\asxArousedub1.nif" 2 2 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedlb3.nif" 3 2 else actor.SetBodyAssetOverride "Characters\asx\m\asxaroused4.nif" 3 2 endif printc "ASX: aroused on 4" elseif level == 5 if npcfemale == 1 ; correct this actor.SetBodyAssetOverride "Characters\asx\f\asxArousedub1.nif" 2 2 actor.SetBodyAssetOverride "Characters\asx\f\asxArousedlb3.nif" 3 2 else actor.SetBodyAssetOverride "Characters\asx\m\asxaroused4.nif" 3 2 ;actor.SetBodyAssetOverride asxqcore.ml4 3 2 endif printc "ASX: aroused on 5 (fix)" endif if u3d == 1 actor.update3D endifend
Myst42 Posted November 29, 2014 Author Posted November 29, 2014 Right, I appreciate the attempt but please keep in mind: -I am NOT a programmer nor do I work with any computer related stuff, that makes me completely unfamiliar with scripting -I'm a NOOB trying to LEARN. Seeing scripts and not understanding them is exactly what brought me here -It's a tough mission but I'm willing to learn. Remember: from the bottom However I can TRY to understand that (Just tell me if I'm wrong): -Script is an attempt so swap models based on "arousal" variable -I recognize if (condition) elseif (other condition) else (condition not met) and endif (close sentence) -For every arousal level, script checks if npc is male or female and then redirects to specific model -When something == 0 it's false and when it's == 1 is true What I dont get: -Why beginfunction {actor, level, u3d}? -Why set npcfemale to actor.getissex female? -What the hell is u3d? -Is printc a pop up message? -How is is that level refers to arousal level and not any other kind of level... there must be a lot of "level" variables in game... -How to work with ref Means reference right? -What is short -What in oblivion are those numbers at the end of nif files? ----------------------------------------------------- Back to original question, how to use this knowledge to obtain my goal, to redirect all models for a race both in nudity and dressing? No head, no particular NPC, just a whole race Blockhead page says "tier 3" refers to racial overrides -------------------------------------------------- Looking at "Tamago Setbody" tried to find corresponding mesh swap script among the many in there Still no idea which one is it But this is tsbrFnOnActorEquip scn tsbrFnOnActorEquip ref rActor ref rItemBase int bFoundPrg int bFoundRand int i int iBa int iPrg int iDefenseType long lSlotMask ref rCurrItem array_var arIter string_var sv string_var svKey string_var svOrig string_var svPathKey string_var svPathNif Begin Function {rActor rItemBase} ; Scribe " %r====================%rtsbrFnOnActorEquip:: Processing %n equipping %n" rActor rItemBase ;We are not interested in the actors that are not loaded. ;OnActorEquip event is also fired when loading actors, so let's not worry. if PlayerRef != rActor if PlayerRef.IsInInterior if 0 == rActor.GetInSameCell PlayerRef ;if 3 <= tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: %n is in the different cell from the player, halted." rActor 1 ;endif sv_Destruct sv, svKey, svPathKey, svPathNif return endif else if PlayerRef.GetParentWorldSpace != rActor.GetParentWorldSpace ;if 3 <= tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: %n is in the different worldspace from the player, halted." rActor 1 ;endif sv_Destruct sv, svKey, svPathKey, svPathNif return endif endif endif ;Let's not mess with other important mod items. Let i := GetSourceModIndex rItemBase if eval (ar_HasKey tsbrMain.arExclude i) sv_Destruct sv, svKey, svPathKey, svPathNif return endif ;We already have checked if the (registered) actor is an npc or a creature ;So additional checking shouldn't be needed Let svKey := GetRawFormIDString rActor ;We check if this event is set for the wrong actor. if 1 > rActor.GetItemCount a4tcWomb || rActor.GetIsSex Male ;if 3 <= tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: %n is not an appropriate subject, halted." rActor 1 ;endif sv_Destruct sv, svKey, svPathKey, svPathNif return endif if eval !(ar_HasKey tsbrMain.arSpermOverrides svKey) ;this part functions only if this actor is not overridden by spermy. Scribe "tsbrFnOnActorEquip:: %n not found in SpermOverride." rActor 1 if 110 > rActor.GetItemCount a4tcWombState || 140 < rActor.GetItemCount a4tcWombState Scribe "tsbrFnOnActorEquip:: and not pregnant either. return." 1 sv_Destruct sv, svKey, svPathKey, svPathNif return endif endif ;We are not interested in weapons or anything like that. if 0 == IsArmor rItemBase && 0 == IsClothing rItemBase ;if 3 <= tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: %n's item %n is neither armor nor clothing, halted." rActor rItemBase 1 ;endif sv_Destruct sv, svKey, svPathKey, svPathNif return endif ;Check if this item is compatible or what should we do with this. ;Get the mesh path of the item, and convert it to a compatible key ;Realism level 0 allows male actors getting pregnant, but we don't want to set them a pregnant belly anyway! Let iDefenseType := IsArmor rItemBase Let iDefenseType += GetArmorType rItemBase Let lSlotMask := GetBipedSlotMask rItemBase Let sv := GetBipedModelPath 1 rItemBase if 1 > sv_Length sv ;mesh path not found? then it may be a male-only item. Let sv := GetBipedModelPath 0 rItemBase endif if 1 > sv_Length sv ;still not found? bah, then this is a wrong item. sv_Destruct sv, svKey, svPathKey, svPathNif return endif Let svPathKey := Call tsbrFnGetPBPath sv 0 0 0 Let svOrig := svPathKey + ".Nif" ; Scribe " %rtsbrFnOnActorEquip:: %n sv = %z svPathKey = %z" rItemBase sv svPathKey Let bFoundPrg := Call tsbrFnCheckEquipment svPathKey lSlotMask iDefenseType ;if 2 <= tsbrMain.iDebug ;Scribe " %rtsbrFnOnActorEquip:: Found Prg meshes? = %g" bFoundPrg 1 ;endif Let svKey := GetRawFormIDString rItemBase if 0 == bFoundPrg Let svPathKey := "" ;To check if we should apply the new mesh path or not. endif ;Else, we should see if we must pick a new random mesh for this item. if tsbrMain.bAllowRandomMesh && 0 == bFoundPrg if eval (ar_HasKey tsbrMain.arRandData[iDefenseType] lSlotMask) ForEach arIter <- tsbrMain.arRandData[iDefenseType][lSlotMask] Let rCurrItem := arIter["value"]["Object"] if rItemBase == rCurrItem Let svPathKey := arIter["value"]["Key"] Let bFoundRand := 1 ;if 2 <= tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: Found a random mesh! = %z" svPathKey 1 ;endif break endif loop if eval !(ar_HasKey tsbrMain.arEquipPath[iDefenseType] lSlotMask) ;What? We had discovered this mesh before, but can't find it now? Then discover it again. ;This happens if the randomly assigned mesh path wasn't from the ini. Let bFoundRand := Call tsbrFnBuildEntry svPathKey lSlotMask iDefenseType elseif eval !(ar_HasKey tsbrMain.arEquipPath[iDefenseType][lSlotMask] svPathKey) Let bFoundRand := Call tsbrFnBuildEntry svPathKey lSlotMask iDefenseType endif endif if 0 == bFoundRand ;We either couldn't find the matching item at all, or the user has deleted the mesh. ;Whatever. Pick a random mesh path for this item. Let svPathKey := Call tsbrFnPickRandom rItemBase lSlotMask endif endif if 0 < sv_Length svPathKey ;if 2 <= tsbrMain.iDebug ;Scribe " %rtsbrFnOnActorEquip:: svPathKey is valid, processing = %z" svPathKey 1 ;endif ;Now that we know we should swap the mesh path of this item, we need to know in which prg/ba state this actor is. ;Break Armor first, if any if IsModLoaded "BreakArmor.esp" Let iBa := Call tsbrFnGetBAIndex rActor rItemBase ; if 0 == iBa ; Let iBa := Call tsbrFnGetBAIndexAlt sv ; endif ;Let's make sure that not having enough prg meshes causing out of index error. if eval (iBa > ar_Last tsbrMain.arEquipPath[iDefenseType][lSlotMask][svPathKey]) Let iBa := ar_Last tsbrMain.arEquipPath[iDefenseType][lSlotMask][svPathKey] endif endif ;Womb State (Prg) next. Let i := ar_Size tsbrMain.arEquipPath[iDefenseType][lSlotMask][svPathKey][iBa] Let iPrg := Call tsbrFnGetWombStateIndex rActor i ;And get the new nif path with them. Let svPathNif := tsbrMain.arEquipPath[iDefenseType][lSlotMask][svPathKey][iBa][iPrg] ; Scribe " %rtsbrFnOnActorEquip:: Final svPathNif = %z" svPathNif ; if 0 == sv_Compare $sv svPathNif ;Commented out in v194, because this is causing incorrect mesh swap issue. ;;Too bad... this item's path doesn't need to be changed. ;if tsbrMain.iDebug ;Scribe "tsbrFnOnActorEquip:: Don't need to change path(%z), halted." sv 1 ;endif ; sv_Destruct sv, svKey, svPathKey, svPathNif ; return ; endif ;Change nif path here, and queue a new task in the swap queue array to revert the path back a few frames later SetFemaleBipedPath $svPathNif rItemBase if eval !(ar_HasKey tsbrActionQueueController.arSwapQueue svKey) Let tsbrActionQueueController.arSwapQueue[svKey] := ar_Construct StringMap Let tsbrActionQueueController.arSwapQueue[svKey]["Ref"] := rItemBase Let tsbrActionQueueController.arSwapQueue[svKey]["PathBack"] := svOrig ; Let tsbrActionQueueController.arSwapQueue[svKey]["PathNew"] := svPathNif Let tsbrActionQueueController.arSwapQueue[svKey]["Counter"] := tsbrMain.iBADelayFrame else ;Overwrite the new path entry with the new one, hope this won't give too much trouble ; Let tsbrActionQueueController.arSwapQueue[svKey]["PathNew"] := svPathNif Let tsbrActionQueueController.arSwapQueue[svKey]["Counter"] += tsbrMain.iBADelayFrame endif if 0 == GetQuestRunning tsbrActionQueueController StartQuest tsbrActionQueueController Let tsbrActionQueueController.iDelayFrame := 1 endif endif ; Scribe "--------------------%r " sv_Destruct sv, svKey, svPathKey, svPathNif End And it doesn't make half the sense the other one does
Symon Posted November 29, 2014 Posted November 29, 2014 OK, I'll do my best. -Script is an attempt so swap models based on "arousal" variable-I recognize if (condition) elseif (other condition) else (condition not met) and endif (close sentence) -For every arousal level, script checks if npc is male or female and then redirects to specific model -When something == 0 it's false and when it's == 1 is true All spot on! Scripts are less mysterious to you than some (grin). The places to learn more are: http://cs.elderscrolls.com/index.php?title=Portal:Scripting http://obse.silverlock.org/obse_command_doc.html Be wanred, scripts are a lot of reading, learning and experimentation. -Why beginfunction {actor, level, u3d}? A function is a script then can be called from other scripts. http://obse.silverlock.org/obse_command_doc.html#User_Defined_Functions -Why set npcfemale to actor.getissex female? I could have passed the sex of the actor but having already passed the ref, it makes sense to find the sex for certain. We do this because we want textures or meshes to be appropriate for the actors sex. -What the hell is u3d? The option to update the 3D of the actor, if doing so at this stage is desired. http://cs.elderscrolls.com/index.php?title=Update3D A lot of people think this is buggy when used on the player, but it seems to work fine IF you remember it updates the current 1st/3rd person view. So if the player is in 1st person and you want to update the 3rd person (the usual thing you want to do), it will not work. You have to switch to a 3rd person view first, then call update3d. -Is printc a pop up message? No. A diagnostic message to the console. -How is is that level refers to arousal level and not any other kind of level... there must be a lot of "level" variables in game... Arousal level is part of the ASX mod Nessa and I are working on. (http://www.loverslab.com/topic/13194-asxwipthe-sisterhood-of-sin/?) -How to work with ref Means reference right? Spot on! -What is short A number: http://cs.elderscrolls.com/index.php?title=Short_Integer -What in oblivion are those numbers at the end of nif files? Block head parameters. The first is the body part being set. The second 2 means 'a mesh'. A 1 would have meant 'a texture'. Hope that helps a bit. Scripting is a big subject! I program for a living and many Oblivion mods reveal to me that the author found scripting really hard too!
Myst42 Posted November 30, 2014 Author Posted November 30, 2014 Thank you! I guess there's no place for TLDR on this stuff... Well I got my reading to do... In the meantime I'd like to keep speculating on the final vision of the project How would you guys do an effective mesh swap for beast races? Should I focus on Blockhead? Or perhaps Tamago Setbody is a better option as it also engages the problem of armor and clothing? Is Blockhead any useful for this anyway? Or perhaps as it functions only for nude models I should be returning to scripts?
movomo Posted November 30, 2014 Posted November 30, 2014 Enthusiasm, aren't you! Firstly let's clarify your objectives. You want to achieve two different goals, swap nude bodies and swap armors. They are different. Some below may not make sense to you right now, well just don't panic and read on. For nude bodies, blockhead should do the job. Satyrist made a beast body add-on for setbody reloaded, you can use that one to automatically assign beast bodies to beast races. At the moment setbody has a nasty bug with that add-on pack, but the fixed version will be released very soon. http://www.loverslab.com/topic/36199-setbody-beast-body-menu-add-on/ If you go for scripting it yourself, using blockhead is as simple as typing this: ;Blockhead Body Parts convention ;2 upperbody ;3 lowerbody ;4 hand ;5 foot ;15 tail rActor.SetBodyAssetOverride $sFootPath 5 2 rActor.SetBodyAssetOverride $sHandPath 4 2 rActor.SetBodyAssetOverride $sUpperbodyPath 2 2 rActor.SetBodyAssetOverride $sLowerbodyPath 3 2 This is the part that you were seeking in setbody reloaded, this is all. Isn't it simple! What isn't simple is other stuff, building data arrays, constructing menu structure with indefinite number of items, updating actors, and so forth. These "other" works consume over 90% of setbody scripts. Speaking of updating actors, I don't use update3D because of two reasons. First, it resets whatever animation that is currently playing. Second, when called on the player, it sometimes makes the game report player's state as playing animation, causing you to be stuck with the current weapon (including bare hands), you can't equip anything else just like when you are attacking. However, using update3D has one certain advantage - you can finish the job in the same frame (npcs can not be updated within one frame without update3D). For swapping armors, the example plugin you've picked(tamago setbody) isn't bad. EXCEPT, it is way too complicated for a starter. Actually it isn't that horrible, just you are confused by all the fancy expressions, idioms, abbreviations. Generally speaking, making sense of scripts means you anyway will have to learn how to code scripts yourself. And the fastest way to learn scripting is to grab an example plugin, see what's going on and write one by your own, imitating the workflow of your chosen example. Now that you said you can make sense of basic scripts, you can try a bit further. The best scripting guide for obse/nvse scripting is by one of our mods Doctasax and they can be found here: http://www.loverslab.com/topic/26749-tutorial-nvse4-part-1-syntax-and-expressions/ http://www.loverslab.com/topic/26802-tutorial-nvse4-part-2-user-defined-functions-udfs/ http://www.loverslab.com/topic/26963-tutorial-nvse4-part-3-string-variables/ http://www.loverslab.com/topic/27076-tutorial-nvse4-part-4-array-variables/ http://www.loverslab.com/topic/39417-tutorial-nvse4-part-5-event-handlers-user-defined-events-udes/ One important trick in unassemblying any kind of script-based mod is to find the right entry point. It's in many cases a quest script and tend to be named as "init" or "main" or something like that. If the mod has multiple quests, the entry point quest is most likely set as "start-game enabled". Basically every script runs top to bottom, above to below, but keep in mind that it does not mean the actual workflow starts from the top. And in oblivion every variable is initially numeric zero, so if you encounter a new variable used that has never been assigned of any value, assume it to be a zero. So.. let me recommend a slightly better example plugin. https://www.loverslab.com/topic/37578-player-clothing-replacer/ This one. It's a very very simple plugin that is solely dedicated to swapping player's equipments, and only the player's. Its scripts are very short too, so a bit easier to understand, and yet it features some example uses of array, string and event handler. The bad side is that I didn't bother documenting it at all. My bad practice. Speaking of commenting, Break Armor is very kindly documented; it explains how and why do something, almost line by line. Although it works a bit differently than tamago setbody or player clothing replacer, and although it's quite complex by its own, it should give you a good idea of the detailed workflow of a mesh-swap framework. Tamago setbody is kind of even more complicated than Break Armor. But the basic idea is exactly same as player clothing replacer which is very simple. So the complexity of tamago setbody shouldn't be a problem once you get the hang of it. Feel free to throw a question when you get stumped. I'll try to explain it in more detail.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.