[BETA/RELz/WIPz] NifSE v1.0

Post » Wed Mar 30, 2011 6:23 am

I'd need a lot more information on how EGM files work, but my first guess is that this is something beyond the purview of NifSE. I don't think EGM files are related to the NetImmerse File format, which means Niflib does not support anything about them, which means Oblivion's use of them is something I know nothing about. I could, however, be wrong. Can you explain some more about EGM files, how they're usually created and how you usually get them to correspond to a given NIF?
User avatar
Lucky Boy
 
Posts: 3378
Joined: Wed Jun 06, 2007 6:26 pm

Post » Wed Mar 30, 2011 12:53 pm

It's FaceGen-based, but since it's used in conjunction with NIFs I thought you could try adding in forced support... I suggest looking at hair and helmet NIFs and see how they're prepared for EGM usage.
User avatar
Schel[Anne]FTL
 
Posts: 3384
Joined: Thu Nov 16, 2006 6:53 pm

Post » Wed Mar 30, 2011 9:19 am

OK, to be blunt: I have more than enough on my plate right now, so I'm not going to start digging through the NIFs and EGMs and figuring it out. Maybe I would at some point, but not any time soon - there are plenty of things I know how to do that I can do, which would come first. If you want this kind of thing added to NifSE, you're going to have to do some of that legwork for me so I can learn how it works.
User avatar
Laura
 
Posts: 3456
Joined: Sun Sep 10, 2006 7:11 am

Post » Wed Mar 30, 2011 9:46 am

Hi!

Can I just say - excellent work!!!

Unfortunately, I've been having a go at a little script, but failing at the last hurdle :(

I have an activator and a static painting.

The script uses NifSE to replace one of the textures on the painting.
The nifse.log indicates this is happening correctly, however in game it doesn't appear to update!

I tried adding update3d as well as disable/enable, but now I just get an odd octagonal shape?

Am I missing something silly?

scn twScriptref pPaintingstring_var ppathstring_var filepathshort nifIDshort blockType_NiTexturingPropertyarray_var childshort childIndexarray_var childrenarray_var propshort propIndexshort propTypearray_var propsshort slotCountshort slotIndexshort texIndexbegin onactivate	set pPainting to twPainting	let ppath := pPainting.GetModelPath	let nifID := NifOpen $filepath 1	let filepath := NifGetPath nifID	Print filepath	SetModelPath filepath pPainting	if eval ( filepath != "" )		let blockType_NiTexturingProperty := GetNifTypeIndex "NiTexturingProperty"		let childIndex := NiNodeGetNumChildren nifID		Print "Num children: "+$childIndex		let children := NiNodeGetChildren nifID		foreach child <- children			let childIndex := *child			let filepath := NiObjectNETGetName nifID childIndex			Print "Child #"+$childIndex+" name: "+filepath			let props := NiAVObjectGetProperties nifID childIndex			foreach prop <- props				let propIndex := *prop				let propType := NiObjectGetType nifID propIndex				if eval ( propType == blockType_NiTexturingProperty )										Print "NiTexturingProperty (block #"+$propIndex+"):"					let slotIndex := 0					let slotCount := NiTexturingPropertyGetTextureCount nifID propIndex					while (slotIndex < slotCount)						if eval ( NiTexturingPropertyHasTexture slotIndex nifID propIndex )							let texIndex := NiTexturingPropertyGetTextureSource slotIndex nifID propIndex							let filepath := NiSourceTextureGetFile nifID texIndex							print $filepath														if filepath == "clutter\paintings\paintingforest03.dds"															NiSourceTextureSetExternalTexture "clutter\paintings\paintingforest03_alt01.dds" nifID texIndex							endif												endif						let slotIndex += 1					loop				endif			loop		loop	endif	pPainting.disable	pPainting.enable	pPainting.update3dend

User avatar
Matthew Aaron Evans
 
Posts: 3361
Joined: Wed Jul 25, 2007 2:59 am

Post » Wed Mar 30, 2011 3:17 am

Well, rather than looping through the properties, you could use NiAVObjectGetPropertyByType - it'd be a bit more cleaner-looking/efficient. Not going to fix any problems though. You might also figure out the name of the child block that you want to change, rather than looping through those, and use NiNodeGetChildByName. Again, not going to fix problems.

Also, there's no need to check all of the texture slots: it looks like you're only going to change slot 0 (the color map) there.

Try moving the SetModelPath filepath pPainting line down, in between the disable and enable. Maybe that will help, if you change it while it's disabled?

Otherwise, please show me NifSE.log.
User avatar
Zoe Ratcliffe
 
Posts: 3370
Joined: Mon Feb 19, 2007 12:45 am

Post » Wed Mar 30, 2011 3:55 am

Greetings!

Many thanks for the advice!

I have attempted what you suggest, ending up with this (much nicer!) code:
Spoiler

scn twPaintingScriptref pPaintingstring_var pPathstring_var nifPathstring_var filePathstring_var oldTexshort nifIDshort blockType_NiTexturingPropertyarray_var childshort childIndexarray_var childrenarray_var propshort propIndexshort propTypearray_var propsshort slotCountshort slotIndexshort texIndexbegin onactivate	set pPainting to twPainting	let pPath := pPainting.GetModelPath	let nifID := NifOpen $pPath 1	let nifPath := NifGetPath nifID	print $nifPath	if eval ( nifPath != "" )		let blockType_NiTexturingProperty := GetNifTypeIndex "NiTexturingProperty"		let childIndex := NiNodeGetNumChildren nifID		print $childIndex		let children := NiNodeGetChildren nifID		foreach child <- children			let childIndex := *child			let propIndex := NiAVObjectGetPropertyByType blockType_NiTexturingProperty nifID childIndex			let slotIndex := 0			let texIndex := NiTexturingPropertyGetTextureSource slotIndex nifID propIndex			let oldTex := NiSourceTextureGetFile nifID texIndex			if eval ( oldTex == "clutter\paintings\paintingforest03.dds" )				NiSourceTextureSetExternalTexture "clutter\paintings\paintingforest03_alt01.dds" nifID texIndex			endif								loop		pPainting.disable		SetModelPath nifPath pPainting		pPainting.enable		pPainting.update3d	endif	end



However.....

I am still getting the same little black octagon when I flick the switch :(

Here is my NifSE log:
Spoiler


NifSE v1.00 b:5 a:f

query
load

oblivion root = C:\Games\Oblivion\
List of BSA files: (excluding BSA files known to contain non-NIF data)
C:\Games\Oblivion\Data\1em_Vilja.bsa
C:\Games\Oblivion\Data\All Natural.bsa
C:\Games\Oblivion\Data\Better Cities - Bravil Docks.bsa
C:\Games\Oblivion\Data\Better Cities - Meshes.bsa
C:\Games\Oblivion\Data\Better Cities - Shipyard.bsa
C:\Games\Oblivion\Data\Better Cities - Sounds EV.bsa
C:\Games\Oblivion\Data\Better Cities - Textures EV.bsa
C:\Games\Oblivion\Data\Better Cities - Textures.bsa
C:\Games\Oblivion\Data\bgMagicEV.bsa
C:\Games\Oblivion\Data\CastleEltz.bsa
C:\Games\Oblivion\Data\DLCBattlehornCastle.bsa
C:\Games\Oblivion\Data\DLCFrostcrag.bsa
C:\Games\Oblivion\Data\DLCHorseArmor.bsa
C:\Games\Oblivion\Data\DLCOrrery.bsa
C:\Games\Oblivion\Data\DLCShiveringIsles - Meshes.bsa
C:\Games\Oblivion\Data\DLCThievesDen.bsa
C:\Games\Oblivion\Data\DLCVileLair.bsa
C:\Games\Oblivion\Data\Harvest [Flora].bsa
C:\Games\Oblivion\Data\Knights.bsa
C:\Games\Oblivion\Data\Mart's Monster Mod for OOO.bsa
C:\Games\Oblivion\Data\Oblivion - Meshes.bsa
C:\Games\Oblivion\Data\P1DseeYouSleep.bsa
C:\Games\Oblivion\Data\The Lost Spires.bsa
C:\Games\Oblivion\Data\xulAspenWood.bsa
C:\Games\Oblivion\Data\xuldarkforest.bsa
C:\Games\Oblivion\Data\xulSkingradOutskirts.bsa
26 total.

Registering OBSE script interface.

Listening to OBSE dispatches.

Registering String Interface.

Setting Serialization callbacks.

Initializing NifSE Hooks.

Initialization complete.


Game loaded: Creating ni\ directory.

NifLoad - Loading NifSE data.
NifLoad - Clearing previous RegList.
NifLoad - Load complete.

NifOpen - "Clutter\MiddleClass\Paintings\MiddlePaintingForest03a.NIF" opened for editing.
NifFile c'tor - NifFile created for editing.
NifFile.loadNif - Loading "Clutter\MiddleClass\Paintings\MiddlePaintingForest03a.NIF"!
NifFile.readNif - Read 22469 of 22469 bytes.
NifFile.loadNif - Nif is good; v20.0.0.5. Loaded 25 blocks.
NifFile.reg - Registering "Clutter\MiddleClass\Paintings\MiddlePaintingForest03a.NIF" on RegList.
NifFile.reg - Registered as #183-0.
NifOpen - "Clutter\MiddleClass\Paintings\MiddlePaintingForest03a.NIF" registered as #183-0.

NifGetPath - Getting the path to nif #183-0
NifGetPath - Returning "ni\twobsetest_0.nif".

GetNifTypeIndex - Getting the code for Nif block type "NiTexturingProperty".
GetNifTypeIndex - Returning 316.

NiNodeGetNumChildren - Getting number of Children nodes in nif #183-0 block #0.
NiNodeGetNumChildren - Returning 3 Children nodes.

NiNodeGetChildren - Getting Children nodes to nif #183-0 block #0.
NiNodeGetChildren - Returning node's children.

NiAVObjectGetPropertyByType - Getting the index of the "316" Property of nif #183-0 block #6.
NiAVObjectGetPropertyByType - Returning 10.

NiTexturingPropertyGetTextureSource - Getting texture #0 of the NiTexturingProperty (nif #183-0 block #10).
NiTexturingPropertyGetTextureSource - Returning block #11.

NiSourceTextureGetFile - Getting the filename of the texture used by the NiSourceTexture (nif #183-0 block #11).
NiSourceTextureGetFile - Returning "wood\intstainewood01.dds".

NiAVObjectGetPropertyByType - Getting the index of the "316" Property of nif #183-0 block #13.
NiAVObjectGetPropertyByType - Returning 16.

NiTexturingPropertyGetTextureSource - Getting texture #0 of the NiTexturingProperty (nif #183-0 block #16).
NiTexturingPropertyGetTextureSource - Returning block #17.

NiSourceTextureGetFile - Getting the filename of the texture used by the NiSourceTexture (nif #183-0 block #17).
NiSourceTextureGetFile - Returning "clutter\middleclass\MIddleFrame01.dds".

NiAVObjectGetPropertyByType - Getting the index of the "316" Property of nif #183-0 block #19.
NiAVObjectGetPropertyByType - Returning 22.

NiTexturingPropertyGetTextureSource - Getting texture #0 of the NiTexturingProperty (nif #183-0 block #22).
NiTexturingPropertyGetTextureSource - Returning block #23.

NiSourceTextureGetFile - Getting the filename of the texture used by the NiSourceTexture (nif #183-0 block #23).
NiSourceTextureGetFile - Returning "clutter\paintings\PaintingForest03.dds".

NiSourceTextureSetExternalTexture - Setting the filename of the texture used by the NiSourceTexture (nif #183-0 block #23).
NiSourceTextureSetExternalTexture - Setting file name to "clutter\paintings\paintingforest03_alt01.dds".

Game quit: Deleting ni\ directory.




I was wondering if there was someway to view the temporary Nif in the Ni\ directory, whilst Oblivion is running, but I can't see anything in the directory when I look?
Or is the Octagon a placeholder of some kind??
User avatar
electro_fantics
 
Posts: 3448
Joined: Fri Mar 30, 2007 11:50 pm

Post » Wed Mar 30, 2011 12:45 am

NifSE.log shows no record of Oblivion ever requested the NIF, which would seem to imply that the SetModelPath line didn't work. Uhh... I'm not entirely sure. Try putting a debug message in there to show what nifPath holds before you call SetModelPath?

As for viewing the NIF, yes. There is an undocumented (mostly because I forgot to) debug function called NifWriteToDisk which does exactly what it says on the tin - it writes a (permanent, unless you manually go into your folders and delete it) copy of the NIF to the disk. The syntax is as follows:
(bool:success) NifWriteToDisk string:FilePath short:nifID
The filepath is where it will be written to; don't put it in the ni\ directory, please. This is, as usual, relative to the Meshes\ directory. You can look at the copy after you quit the game to see what its state was at the time.
User avatar
Charity Hughes
 
Posts: 3408
Joined: Sat Mar 17, 2007 3:22 pm

Post » Wed Mar 30, 2011 7:51 am

Huzzah!!!

Got it working!

Checked the path... that looked fine...
Checked the nif exported via that handy function... that looked fine....

Changed:
SetModelPath nifPath pPainting


To:
SetModelPath $nifPath pPainting


And no more black octagon! Awesome!

Now to tinker some more...

Many many thanks
User avatar
Eliza Potter
 
Posts: 3481
Joined: Mon Mar 05, 2007 3:20 am

Post » Wed Mar 30, 2011 2:15 pm

Oh, yeah. That gets me all the time; I'm never sure when you are and are not supposed to use the $, heh.
User avatar
sara OMAR
 
Posts: 3451
Joined: Wed Jul 05, 2006 11:18 pm

Post » Wed Mar 30, 2011 12:42 am

Does the file structure of .kf files allow this to be used on them?

And if so, would one of the existing functions allow me to edit NiStringPalette blocks, or would that require a new function?
User avatar
Isabella X
 
Posts: 3373
Joined: Sat Dec 02, 2006 3:44 am

Post » Wed Mar 30, 2011 6:15 am

I haven't tested it; it's on my list of things to do (but not for 1.0). Unfortunately, even if Niflib would allow .kf's to be loaded, I think NifSE itself (i.e. my own code) would choke on one somewhere. But hey, feel free to try it! If it works, all the better! I'd love to know what happens when a .kf is fed to NifOpen.
User avatar
Trey Johnson
 
Posts: 3295
Joined: Thu Oct 11, 2007 7:00 pm

Post » Wed Mar 30, 2011 11:39 am

Hi all!

I've searched around to no avail, so I guess I'll just ask (and I'm sorry if this is in an obvious place and I just missed it :( ).

Now that the getoffhand function is deprecated...how do we get an off-hand mesh of a one-handed weapon now? I'm guessing it's one of the translation functions, but as I'm completely unversed in nif files, I have no guesses beyond that.

Thank you for your time!
User avatar
Jack
 
Posts: 3483
Joined: Sat Oct 20, 2007 8:08 am

Post » Wed Mar 30, 2011 5:56 am

Stupid bloody gamesas forums turning off subscriptions bracka fracka grumble.

Anyway, all you need to do is find the NiStringExtraData block named "Prn", since that's what Oblivion uses for deciding where it attaches to the body. Use let prnBlockID := http://cs.elderscrolls.com/constwiki/index.php/NiObjectNETGetExtraDataByName "Prn" nifID followed by let prnString := http://cs.elderscrolls.com/constwiki/index.php/NiExtraDataGetString nifID prnBlockID to check what it is, and then http://cs.elderscrolls.com/constwiki/index.php/NiExtraDataGetString "new value" nifID prnBlockID to set it. One-handed weapons should be set to "SideWeapon", two-handed weapons should be set to "BackWeapon", and for best results, off-hand weapons should use "Torch".
User avatar
Philip Lyon
 
Posts: 3297
Joined: Tue Aug 14, 2007 6:08 am

Post » Wed Mar 30, 2011 3:11 am

Stupid bloody gamesas forums turning off subscriptions bracka fracka grumble.

Anyway, all you need to do is find the NiStringExtraData block named "Prn", since that's what Oblivion uses for deciding where it attaches to the body. Use let prnBlockID := http://cs.elderscrolls.com/constwiki/index.php/NiObjectNETGetExtraDataByName "Prn" nifID followed by let prnString := http://cs.elderscrolls.com/constwiki/index.php/NiExtraDataGetString nifID prnBlockID to check what it is, and then http://cs.elderscrolls.com/constwiki/index.php/NiExtraDataGetString "new value" nifID prnBlockID to set it. One-handed weapons should be set to "SideWeapon", two-handed weapons should be set to "BackWeapon", and for best results, off-hand weapons should use "Torch".

Thank you much, DW. I was just coming around to that idea after combing over the source code, but it would've taken me many more hours to figure this out on my own (It's been far too long since I've done any serious scripting or programming). I really appreciate it. :)

I was very close to creating weird ghosty weapons that float around to the player's left and move in sync with their right hand. :P


[ADDENDUM]

Can there only be one Prn block per nif file? For instance, if I wanted to make a single nif that had both the main hand and off hand weapon, could I have the main hand block have a Prn == "SideWeapon" and the offhand block have a Prn == "Torch"?

I ask because I see that NiObjectNETGetExtraDataByName returns a single value, and not an array of values. If you had possible Prn blocks, would they break the nif, or does the function just return the first "Prn" (or whatever) block it finds?

I hope I'm not asking too many questions. I hate to impose, considering that I'm delving into a field of which I know little with all this .nif business.
User avatar
Jeremy Kenney
 
Posts: 3293
Joined: Sun Aug 05, 2007 5:36 pm

Post » Wed Mar 30, 2011 9:08 am

Something I'd like to ask - Is it possible to turn off or modify the collision for meshes without having to create a new static? Say you want to put strawberries in a bowl but don't want them to explode when they are that close to each other, but still be able to pick them up or be put into the bowl...
User avatar
Alina loves Alexandra
 
Posts: 3456
Joined: Mon Jan 01, 2007 7:55 pm

Post » Wed Mar 30, 2011 4:30 am

Thank you much, DW. I was just coming around to that idea after combing over the source code, but it would've taken me many more hours to figure this out on my own (It's been far too long since I've done any serious scripting or programming). I really appreciate it. :)

I was very close to creating weird ghosty weapons that float around to the player's left and move in sync with their right hand. :P

Haha, oh no! Glad I could save you that headache.


Can there only be one Prn block per nif file? For instance, if I wanted to make a single nif that had both the main hand and off hand weapon, could I have the main hand block have a Prn == "SideWeapon" and the offhand block have a Prn == "Torch"?

I ask because I see that NiObjectNETGetExtraDataByName returns a single value, and not an array of values. If you had possible Prn blocks, would they break the nif, or does the function just return the first "Prn" (or whatever) block it finds?

I hope I'm not asking too many questions. I hate to impose, considering that I'm delving into a field of which I know little with all this .nif business.

I have no idea how Oblivion would handle a mesh with multiple Prn nodes; there's only supposed to be one. It'd probably just use whichever value it came to first. By a single nif, do you mean having one mesh that you switch between these two (you can do that by changing the Prn node), or do you mean having a single mesh that does both at once (I'm fairly certain this cannot be done because Oblivion doesn't have any support for it)?

Something I'd like to ask - Is it possible to turn off or modify the collision for meshes without having to create a new static? Say you want to put strawberries in a bowl but don't want them to explode when they are that close to each other, but still be able to pick them up or be put into the bowl...

Currently, no. You could create the NIF you need easily enough by using NiNodeCopyChild from the strawberries over to an almost-blank NIF that has no collision, but you couldn't simply remove the collision from the strawberries. That capability is planned to be the last feature I include in v1.0. Currently my computer is inoperable; I'm waiting on the manufacturer to fix or give up on fixing my video card, and send it (or a replacement) back to me — this could take as much as three weeks to get back to me.
User avatar
Ryan Lutz
 
Posts: 3465
Joined: Sun Sep 09, 2007 12:39 pm

Post » Wed Mar 30, 2011 11:41 am

Ah, darn. I was hoping for a single mesh that does both at once, but oh well. I can still work with that.

Follow up: If I added a child mesh to a weapon mesh's scabbard (Find scabbard using NiNodeGetChildByName "Scb"), could I rotate and translate that child independent of the parent? For instance, if I wanted to have the player with two side-by-side scabbards...

I guess I should just wait until I'm in front of the CS to test these things out. I'm sorry if I'm too impatient. :P
User avatar
Britta Gronkowski
 
Posts: 3475
Joined: Mon Apr 09, 2007 3:14 pm

Post » Wed Mar 30, 2011 11:25 am

I'm not certain how children-of-child-nodes work, but I suspect that will work the way you want it to.
User avatar
Hussnein Amin
 
Posts: 3557
Joined: Sun Aug 05, 2007 2:15 am

Post » Wed Mar 30, 2011 9:25 am

Aaaand I'm back! This is my first time using OBSE's special variables. When I try to run the NiAVObjectSetLocalTranslation command, I get an error stating that param type 38 is unitialized in ScriptCompiler::StandardCompiler. Regardless of how I initialize my array (either with ar_Construct Array at the start, or by using let TransArray := NiAVObjectGetLocalTranslation), I get this error.

Am I missing something basic? I didn't get the impression that Array_Vars require any additional plugins, but maybe I overlooked something? Again, I'm sorry to keep posting my noobish questions.
User avatar
rae.x
 
Posts: 3326
Joined: Wed Jun 14, 2006 2:13 pm

Post » Wed Mar 30, 2011 3:06 am

Can this extension to OBSE be used to modify KF files?

I am looking to determine if there is a way to change sound tags inside an animation that is running. From what I can tell this extension just modifies NIF files, but I wanted to make sure.
User avatar
Lillian Cawfield
 
Posts: 3387
Joined: Thu Nov 30, 2006 6:22 pm

Post » Wed Mar 30, 2011 2:50 pm

Aaaand I'm back! This is my first time using OBSE's special variables. When I try to run the NiAVObjectSetLocalTranslation command, I get an error stating that param type 38 is unitialized in ScriptCompiler::StandardCompiler. Regardless of how I initialize my array (either with ar_Construct Array at the start, or by using let TransArray := NiAVObjectGetLocalTranslation), I get this error.

Am I missing something basic? I didn't get the impression that Array_Vars require any additional plugins, but maybe I overlooked something? Again, I'm sorry to keep posting my noobish questions.

Did you use the compiler override? It's necessary to pass array variables to plugin functions.

Can this extension to OBSE be used to modify KF files?

I am looking to determine if there is a way to change sound tags inside an animation that is running. From what I can tell this extension just modifies NIF files, but I wanted to make sure.

Here's the answer I gave Disco; nothing's changed on this front, I'm afraid:
Does the file structure of .kf files allow this to be used on them?

And if so, would one of the existing functions allow me to edit NiStringPalette blocks, or would that require a new function?
I haven't tested it; it's on my list of things to do (but not for 1.0). Unfortunately, even if Niflib would allow .kf's to be loaded, I think NifSE itself (i.e. my own code) would choke on one somewhere. But hey, feel free to try it! If it works, all the better! I'd love to know what happens when a .kf is fed to NifOpen.

For your particular case (the sound bits), I know it's not going to work even if NifSE opens a .kf, though, since I have no exposed those blocks yet. It can be made to do what you want, but it will be... quite some time, most likely, before that happens.
User avatar
Tanika O'Connell
 
Posts: 3412
Joined: Fri Jan 26, 2007 1:34 am

Post » Wed Mar 30, 2011 8:43 am

Did you use the compiler override? It's necessary to pass array variables to plugin functions.

Ah, I did not. Thank you once again. Sorry to have bothered you with an obvious question like that. ^^;
User avatar
Lisa Robb
 
Posts: 3542
Joined: Mon Nov 27, 2006 9:13 pm

Post » Wed Mar 30, 2011 7:06 am

OK, I have a new version of NifSE that I'll be testing over the next couple of days. It adds some basic functionality for working with collision (Get/Clear/Copy Collision Object, Get/Set Collision Mode), as well as the functions for working with BSFurnitureMarkers that someone requested.

My plan is for this to be the last beta before final release, barring any bugs that need squashing. I would really like all features for v1.0 final to appear in this beta. As such, I would really appreciate any and all requests for new features to be made now.

Thanks.
User avatar
Alex [AK]
 
Posts: 3436
Joined: Fri Jun 15, 2007 10:01 pm

Post » Wed Mar 30, 2011 7:25 am

I hope CSE IntelliSense support makes the final release :spotted owl:
User avatar
Kerri Lee
 
Posts: 3404
Joined: Sun Feb 25, 2007 9:37 pm

Post » Tue Mar 29, 2011 10:43 pm

Point, I will finally set that up before this beta.
User avatar
meghan lock
 
Posts: 3451
Joined: Thu Jan 11, 2007 10:26 pm

PreviousNext

Return to IV - Oblivion