Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Lab Assistant
Original Poster
#1 Old 11th Aug 2007 at 4:12 AM
Default Cloning GMDC
I need to clone a GMDC mesh group, for a couple additional features.

Tell me if I'm missing anything?

Clone the gmdc entry.
Rename it.
add 0x0001 to the instance ID.
add 0x0001 to the high instance ID.

Clone the same gmnd entry.
rename it.
add 0x0001 to the instance id. and high instance id.
Change the cObjectGraphNode entry to point to the new name
Set the reference to point to the new gmdc instance.
Set the sub type to point to the new gmdc high instance.

Clone the resource (Cres),
apply +1 to id and high id.
rename it.
set cObjectGraphNode to new name.

Clone the shp, add 1 to instance.
renamed the items to the correct gmnd

Finally in STR#, instance 85h, Add it to the list.

Now my gmnd all references is pointing to the correct gmdc.
the shape all ref. points to the gmnd
the resource all ref. points to the shape.

Anything else I need to do?
Advertisement
Retired Duck
retired moderator
#2 Old 11th Aug 2007 at 6:38 AM
All of these file types have Type/Group/Instance (TGI) values based on their names. Thus, changing the instances and high instances won't normally work for these files. If you rename them all, then run "Fix Integrity" then you should get the correct TGI values.

If you want the clone to use separate materials, you'll also want to clone the TXMTs, MMATs and TXTRs.

You may need to reconnect the files manually for some of these ones though. The GMND references the GMDC under its "Reference" tab. The SHPE references the GMND under its "items" tab. The CRES references the SHPE under its "Reference" tab. You can check if they're all connected using the Scenegrapher (Tools > Object Tools > Scenegrapher), but you'll generally know if they're not because you won't be able to get the preview under the GMDC.
Lab Assistant
Original Poster
#3 Old 11th Aug 2007 at 7:00 AM
Oh, I more work than needed. Everything I think looks good, the shape item is the gmnd name, the gmnd points references the gmdc.

I'll have to get back to this after a short bug fix. It appears attributes aren't automaticall stored with the accessory. I.e. it resets itself back to default when i hide it then redisplay it. I'll just reuse one of his existing attributes that I'm not using anymore, hopefully that'll work.
One horse disagreer of the Apocalypse
#4 Old 11th Aug 2007 at 9:11 AM
Does having separate GMDC instead of just separate subsets stop that annoying "bleeding through" you get when using an alpha blend material?

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Lab Assistant
Original Poster
#5 Old 11th Aug 2007 at 9:56 AM Last edited by ScoobyDoo : 11th Aug 2007 at 10:07 AM.
I dunno, thats how crammy did it, and i'm just following what he did. I'm having a more serious problem on how he saves and retrieves the attributes. He's using manage inventory with tokens and something about Set to Next token of guid, along with non-visible non-memory? I've tried to insert my additional attribute in there but it complains about stack errors.

Actually it wasn't stake error it was this: "Reference to tree tree parameter when no parameter exists." Could this be because I'm trying to read a parameter (attribute) that isn't in the file/memory? Because I had to add an additional attribute to his collection. Is there a way to avoid this, for example, when you first switch over from his original to my new vesion?
One horse disagreer of the Apocalypse
#6 Old 11th Aug 2007 at 10:26 AM
The parameter error could be because you haven't changed the number in the Parameters box. For example you're referring to Param 2 (which is the 3rd parameter as they start from 0) while your Params count box only says there are two params.

"You can do refraction by raymarching through the depth buffer" (c. Reddeyfish 2017)
Lab Assistant
Original Poster
#7 Old 11th Aug 2007 at 10:07 PM
Ok was reading the thread about Manage Inventory

heres part of his main dealing with reading the settings. He first sets local's to the stack object's attributes.

I needed to add a new local for size [Expression (Local 0x0008 := Stack Object's attribute 0x0008)]

Code:
Manage Inventory (Set to Next Token of GUID 0xEC191A23: non-visible non-memory)
Manage Inventory (Read Token at Index Into Temp) // index:local = 0 neighbor: local = 1
Manage Inventory (Set Nth Property from Token into Temp) // property: literal = 1, value: local = 1

// Repeat for 2 to 6

Manage Inventory (Save Token in Temp)


How do I change this to add an additional entry?

I tried adding Manage Inventory (Set Nth Property From Token In Temp) // index: local=8 value: literal=7 (he doesn't use #7 in the manage inventory),
but it complains about stack number out of range with the very first Set Nth property.
Retired Duck
retired moderator
#8 Old 12th Aug 2007 at 2:19 AM
Very first thing to check - you're using local 0x8, so your "local var count" (top right in the PJSE BHAV plugin) for that BHAV must be 0x9 or higher. If it's not, then you will be getting errors, because you're trying to use a local variable that the game hasn't created yet.
Lab Assistant
Original Poster
#9 Old 12th Aug 2007 at 4:02 AM
Ok that was well hidden, that'll help a lot so I don't have to keep recycling locals.

Back to "Reference to tree tree parameter when no parameter exists".
BTW what is a token? Is it sorta like an array or a pointer to an array?

Am I reading this right with what he has done?
**** Token - Set Stats (inst. 1028)
1. seems like prework, saving object id in temp, etc...
2. he assigns the locals the attributes (i assign my local 8 with a attribute 8)
3. set to next token of guid..... (does this set the pointer to the correct object's token?)
4. he loads the token into temp
5. Set Nth property from token in temp (is that temptoken[X] = localY ?)
6. saves the array (if successful the function returns)

if anything starting with #3 fails he then:
1. removes the array
2. rebuilds it

It seems my log errors are currently in the removing the array

his remove routine (true goes to the next statement unless noted) (instance 102A)
Code:
0. Expression (local 0 := lit. FFFF)  false->error
1. Expression (local 1 := stack object atribute 07) false->error
2. Expression (local 2 := param 0x000) false>error
3. Dialog (......) true->error false ->error
4. Manage inventory (set to next token....) false->return true
5. manage inventory (remove token at index) true->goto 0, false->goto 0


This code makes no sense... #3 return error all the time, #4 is never called, #5 always goes to #0

Should I rewrite the load/saving completely? Are there any tutorials or good examples that I should look at?
Retired Duck
retired moderator
#10 Old 12th Aug 2007 at 5:01 AM
A token is a special kind of invisible object, generally with no particular behaviour or anything, which gets put into a sim's hidden inventory. They're used to keep track of things for that sim which can't be easily stored in the standard sim attributes. They can store a stack of properties which can be read and written, but it can be a bit messy. The most obvious use of tokens in game is the storing of sims' memories, but they show up in quite a few places.

The "Reference to tree/tree parameter when no parameter exists" error is almost always caused you an attempt to read or write to a variable which you haven't declared. I can see you're using param 0x00 there in line 2, is that parameter declared? ("Arg count", next to "Local var count", needs to be one higher than the highest param you use).

What is this code actually supposed to be doing? Is it Maxis or custom?
Lab Assistant
Original Poster
#11 Old 12th Aug 2007 at 6:37 AM
It's Crammyboy's male anatomy mod. I've got the meshes all done, I'm just trying to expand the options available. Argcount is 1. It's not getting that far the error is on line #2.

I think my best bet is to start from scratch (or at least use some better template coding) for token loading/saving. That way I know what is exactly going on.

I've got the "How to use Manage Inventory" post bookmarked. Are tokens sim specific (theres "storage" [global/house/family/neighbor])?
Retired Duck
retired moderator
#12 Old 12th Aug 2007 at 6:51 AM
Not sure what your question means... There are different types of tokens, certainly, but most of the ones modders work with are the neighbour (single sim) types.
Lab Assistant
Original Poster
#13 Old 12th Aug 2007 at 6:56 AM Last edited by ScoobyDoo : 12th Aug 2007 at 7:02 AM.
I mean are tokens attached to individual sims?
I'll try writing up a simple version following his work, and post it here if it doesn'twork.
Retired Duck
retired moderator
#14 Old 12th Aug 2007 at 7:52 AM
Oh, then yes, the tokens are attached to particular sims. They end up in the sim's inventory.
Lab Assistant
Original Poster
#15 Old 12th Aug 2007 at 9:05 AM
Thats good... one less thing to worry about. I've put together a simple load and save settings. It simply stores the value 666 into token stack, then loads the value and checks to see if its 666. It's finally not producing any errors. (although the original code now is.... but thats not the issue at hand, besides it'll probably be deleted anyways)

Very first thing main calls is Set Settings, then Load Settings.

Set Settings (argcount:0, local: 2)
Code:
0 manage inventory (Set to next token of guid #: non-visible non-memory) index = Local 0, Target =  Singular neighbor Local 1
1 Expression (Local 0 == My object id)
2 Manage inventory (Remove token at index) index: literal 0 target: singular neighbor local 0 true->2 false->3
3 Manage Inventory (Push Property On Token At Index)  index: lit 0 value: lit 666 target: neighbor local 01  true->5 false->4
4 Dialog ("Unable to push token entry") error
5 Manage Inventory (Save Token in Temp)  true->6 false->7
6 Dialog ("Creating Token Entry") return
7 Dialog ("Unable to save token entry") return


I assume repeating #2 until it return false will wipe the stack empty.

When it runs it cannot push the token entry nor save it. What step(s) am I missing?
Retired Duck
retired moderator
#16 Old 12th Aug 2007 at 9:22 AM
Quote:
2 Manage inventory (Remove token at index)

EEK! You really don't want to do that! Assuming it does what I think it does, that could potentially delete all tokens on the "my" sim, even the ones the game's put there (memories, sickness tokens, death tokens, pregnancy tokens, the works)!

Which line is it failing on, and which message are you getting? Could you post the error log so I can check out the state of your game when it's happening?
Lab Assistant
Original Poster
#17 Old 12th Aug 2007 at 11:31 AM
Ok I'll fix that prompto, thankfully I'm using a spare copy of my hood. The thing is, it's not failing in Set Settings. It's just lines #3 and #5 fail (return false). The closest thing I can get to a line tracing debugger is using dialogs. God I thought I got rid of line numbers when I quit using Basic

BTW what happens if you try to save token in temp when an existing token already exists (from the original mod). Does the original token get replaced or does it need some cleaning done beforehand? By cleaning I mean remove the extra attribute data stored then add the updated data.
Retired Duck
retired moderator
#18 Old 12th Aug 2007 at 11:58 AM
Dialogs are a pretty irritating way of debugging certainly, so very first thing, you know how to get the stack traces from the error logs, yeah?

Okay, so as far as temps and tokens go, the "temp token" is not the same as the regular "temp" variables. The temp token is a particular variable (token type, not regular type,) which you can load a token into, edit it, then write it back to the inventory.

Now, in the code above I can't see anywhere where you're actually giving the sim the token. You'll want something like this in your code to create the token before you try to do anything else to it:
Manage Inventory (Add Token Of GUID, token: GUID [whatever], Category: non-visible non-memory, Inventory (singular): Neighbor: [Subject Neighbour ID])

Now, if you want to give it a value, you run the "set to next" first, then run the "push property".

Not sure if it's of any use to you, but you can try downloading the cauldron from the Harry Potter project and checking out the two functions "Magic - Give Token if needed" and "Magic - Increase Skill Level". The former creates the token, assigns it to the sim, and initializes the properties attached to it. The latter finds the token on the sim, reads its value, increments it, then saves it back. It's pretty straightforward code, and probably easier to follow than this one if you're trying to work with tokens for the first time.

I'm afraid though, that at this point you've about exhausted my off-the-top-of-the-head knowledge about tokens!
Lab Assistant
Original Poster
#19 Old 12th Aug 2007 at 9:59 PM Last edited by ScoobyDoo : 12th Aug 2007 at 11:01 PM.
All I know about stack debugging is using the reset error. Besides that doesn't show me the flow within a function, just the call stack.

Hmm, writing to inventory must be time consuming, hence the need for a temporary token.

Sweet.... that cauldron code is much easier to understand. Crammy's using a lot of tweaks and tricks. It's sorta like learning a new language and having a Perl tweaker as a guide LOL.
Lab Assistant
Original Poster
#20 Old 13th Aug 2007 at 4:09 AM Last edited by ScoobyDoo : 13th Aug 2007 at 4:14 AM.
Ok I spoke too soon...but having some success, but at least I've got ops 3, 24, and 33 memorized LOL.

It's still having troubles reading from the token stack. Through dialog messages, I've found that it does find the stack, reads the token, but fails at get nth property. The first entry in the stack should be 0 right? The cauldron uses #1. It might be storing something else in #0. Is it possible that whatever crammy is stuffing into the first local is unreadable?

Basically during save settings:
it finds the stack - ok
set the next token of guid - ok
read token to temp - ok
get nth prop from token - ok
set nth prop from token - failed.

Btw how do you empty the token stack for the object? That way I can get rid of all his stuff and start fresh each time I have to save settings.
Retired Duck
retired moderator
#21 Old 13th Aug 2007 at 4:46 AM
I think it may start at 1 in the stack (They're horribly inconsistent with the starting indices in this engine).

I'm not aware of any way to clear the stack completely, but then I haven't tried... In most examples of its use it's not really used as a stack, rather as a variable length array. To reset those, you'd just go through and set each value to 0 or -1 or some such.
Lab Assistant
Original Poster
#22 Old 13th Aug 2007 at 5:48 AM
Ok, I'll see what I can do with index at 1. After spending some time away from it, actually with the game, I think I've come the realization that I'll need to get a new GUID for it. Mainly because I won't know if I'm loading Crammyboy's token or my token, which is probably where this mess is starting from. I don't suppose their nice enough to have versioning.
Lab Assistant
Original Poster
#23 Old 14th Aug 2007 at 1:15 AM
Ok I want to rewrite the main code, he put all the loading code messed right into main

First what is Stack Object ID? Is this just a generic (aka temp) pointer or points to this object/accessory/etc...? Does Stack Object ID determine what Stack Object holds (gender age, etc...)? (I would think so)

Second whats my container id? (i noticed that he first assign stack object id to my container id before checking age, so could this be the sim?)

Third whats Neighbor id and family id (i assume family is for this lot only?)?

Heres his code (in more pseudo c style) and what I think he's doing.
Code:
0  Local 7 := Stack Object ID  // save the current pointer for future use
1  idle 
2  if (My Container id > 0) goto 3 else goto 1 // keep idling until it's our turn?
3  Stack Object ID := my container id // Grab the sims pointer?
4  Check for stack objects gender if male goto 5 else goto 6 //shouldn't it just return true for female?
5  if (stack objects age > 2) goto 7 else goto 6 // Teen or older only please, still shouldn't it return true?
6  Stack object := local 7 // restore the pointer (Stack object ID)
7  local 1:= Stack Objects Person Age // get their age, this could be replaced with attribute 1 (age) := Stack Objects person Age
8  local 0 := Stack Objects neighbor id // Keep track of the neighbor id
9  local 6: = Stack Objects family number // keep track of the family id
A  stack object id := local 7 // dunno why he does this twice
B  **** Token - Get item (local 0, 3) 
C  local 2 := temp // it looks like get item uses Stack obj neigh ID and entry 3 and stores result in temp
D  token - get item (local 0, 4)
e  local 3 := temp
F  token - get item (local 0, 5)
10 local 4 := temp
11 token - get item (local 0 , 6)
12 local 5 := temp
13 if (att 0 (owner sim obj id) == my container id) goto 1a else goto 14 // check to see if we've already assigned our stuff
14 attrib 0 (owner sim obj id) := my container id) // assign our id
15 attrib 1 (age) := local 1 // Assign all the locals to the correct attributes
16 attrib 2 (skin color) := local 2
17 attrib 3 (hair color) := local 3
18 attrib 4 (state) := local 4
19 attrib 5 (show "size") := local 5
1a attrib 6 (neighbor) := local 0 // always assign our neighbor id
1b attrib 7 (family id) := local 6
1c stack object id := my object id // what are we setting this to???
1d get mesh for sim (in temp 0) // this simply finds the correct mesh group and returns it in temp 0
1e My graphic := temp 0 // use that mesh
1f if (atrrib 3 (hair color) < 10) goto 20 else 21 // check to see if theres hair in a valid range?
20 attrib 3:= 10 // hair wasn't in range, set to 10, throw error why??
21 local 0 := 0xFFFF
22 stack obj id := my object id // See 1C ???
23 Get Mesh for sim (in temp 0) // not sure why he's doing this twice
24 my graphic := temp 
25 attrib 2 (color) := local 0
26 my grpahic := temp
27 local 0 := attribute 2 (color)
28 Set skin // this sets which subobject gets the actual texture
29 idle goto 23 // this is the main logic loop


I think around 1D and onward is just the core logic so I'm not concerned with that right now.

My guessing for subdividing would be:

InitConfig
assign: attribute sims age, neighbor id, owner id, family id

LoadSettings
assign: state, size, color, hair... (this will be handled by the token)

Basically rewritten:
if sim is female or under teen return false
InitConfig (Stack object id, my container id)
LoadSettings
main logic loop.

Sorry about the long message, I think most of it is just me thinking out loud.
Lab Assistant
Original Poster
#24 Old 14th Aug 2007 at 5:32 AM
*Does hamster dance*

I've cleaned up his code bigtime, my entire main is just three lines long (InitConfig, LoadSettings and Main Logic). So far everything seems to be working. I can change the size and it remains showing. However it doesn't actually load or store values yet, just uses default values the first time it's shown. I may need your help latter... we shall see.

I'm starting to understand Stack Object better. It seems to be a pointer, once you assign it a value, then "Stack Object's" will become available. Sorta like dereferencing a pointer and it's typeless, it can be a container or an object.

Todo list:
First I need to make sure that ALL of Crammy's token code is removed, don't want anything sneaking in and ruining the token. After that then I'll get a new GUID for it, so I don't have to deal with crammy's token version. I don't know if theres any real way to know if it's his or mine and I can't just delete the token first, because it might have been mine, kinda a catch 22.

I'm going to setup the token as such:
* Version number (the very first token entry, if someone wants to modify my work and needs to change the token, they should modify this number, that way they can see which version they are loading)

* Size (as integer, NOT bit flag, if crammy had done this, i wouldn't need to be doing this)

* State (as integer)

* Skin color (as integer)

* hair color (as integer)

* options (as integer... whatever this needs to be)
Retired Duck
retired moderator
#25 Old 14th Aug 2007 at 6:17 AM
Quote:
First what is Stack Object ID? Is this just a generic (aka temp) pointer or points to this object/accessory/etc...? Does Stack Object ID determine what Stack Object holds (gender age, etc...)? (I would think so)
The stack object ID is, loosely speaking, a frame variable. A new instance of it is created for each frame on the execution stack, and all changes made to it are local to that frame... With one minor exception. When you call a function, then initially that function's stack object id takes the value that the caller's stack object had at the moment of calling. eg:

Code:
Stack Object ID := 5
print stack object ID     // prints 5
call function something
   print stack object ID  // prints 5
   stack object ID := 8
   print stack object ID  // prints 8
   return true
print stack object ID     // prints 5


The stack object ID variable itself is just an integer. You can assign any int value to it that you like. However, that value is then used as an index to access the related object's values. If I look up "Stack Object's Person Data 0x01", then the engine translates that to something like (ObjectsOnLot[Stack Object ID]).PersonData[0x01] . Yeah?

Quote:
Second whats my container id? (i noticed that he first assign stack object id to my container id before checking age, so could this be the sim?)

Assuming the object you're looking up is "contained" by another object (ie, it's in another object's slot), then its container ID is the object ID of that container object.

Quote:
Third whats Neighbor id and family id (i assume family is for this lot only?)?

Neighbour id is a unique number given to each Sim, which is maintained across loads. If your sim is born with the neighbour id 28, they will always have neighbour id 28. Not the same thing as the object ID, which is the id of the object unique to the current lot, and is not guaranteed to stay the same between loads. Family id is similar to neighbor id, only it describes families rather than individual sims.

Quote:
InitConfig
assign: attribute sims age, neighbor id, owner id, family id

This is only going to work if you're storing these values in a more broadly scoped variable, and you'll have to read them back from the same broadly scoped variable to actually use them. You can't store things in locals or params or the Stack Object ID, because when your function returns then all the stuff you loaded will be popped off the execution stack and you'll be back where you started.

Quote:
LoadSettings
assign: state, size, color, hair... (this will be handled by the token)

Similar issue as the above.

Regarding the actual code,
Quote:
2 if (My Container id > 0) goto 3 else goto 1 // keep idling until it's our turn?
Close. I'm assuming that this code is in an object which gets spawned by some other object's code? If so, it's more a matter of "keep idling until I'm completely loaded and actually placed in another object's slot", since the main function can start running before the object is completely in-world.

Quote:
3 Stack Object ID := my container id // Grab the sims pointer?
Assuming that the object is being spawned into a sim's slot, then this will make the current Stack Object that sim, yep.

Quote:
1c stack object id := my object id // what are we setting this to???
"My" in a "main" function refers to the owner of the current stack, aka, the object which the code belongs to. Basically, Stack Object ID := "this" object's ID.

Hopefully that was helpful rather than confusing.
Page 1 of 4
Back to top