New item types

Posted by Orik on Fri 17 Aug 2007 02:56 AM — 34 posts, 110,231 views.

USA #0
Ok, I'm putting socketed items into my mud. I've got everything done except for the socket function. In the function I'm checking to see if the item is either a blue gem, a red gem or a yellow gem. For some reason that I cannot explain it is messing up. Here's the code:



/*These if checks are to see if the item_type is working*/

  if (first_ob->item_type == ITEM_GEM_RED)
    send_to_char( "This item is a red gem!\n\r", ch );

  if (first_ob->item_type != ITEM_GEM_RED)
    send_to_char( "This item is not a red gem!\n\r", ch );

  if (second_ob->item_type == ITEM_WEAPON)
    send_to_char( "This item is a sword!\n\r", ch );

/* This is where it stops. My != if check isn't working correctly. */

  if (   first_ob->item_type != ITEM_GEM_BLUE
	  || first_ob->item_type != ITEM_GEM_RED
	  || first_ob->item_type != ITEM_GEM_YELLOW )
  {  
    send_to_char( "This item must be a gem!\n\r", ch );
    return;
  }


Here's my test. I had a gem and a sword. The gem is item_gem_red.

<1564hp 1240mv> 
< 2>socket gem sword
This item is a red gem!
This item is a sword!
This item must be a gem!

I then changed the gem to a blue gem for the second if check to see if it's working.

<1564hp 1240mv> 
< 2>oset gem type gem-blue
Build: Orik: oset gem type gem-blue

<1564hp 1240mv> 
< 2>socket gem sword
This item is not a red gem!
This item is a sword!
This item must be a gem!


Can anyone see what's going on? I've stared at this things for quite awhile and can't figure it out. Either my != is wrong or my || is wrong somehow? I'm not sure.
Amended on Fri 17 Aug 2007 02:59 AM by Orik
USA #1
well i would assume your last ifcheck is wrong, just to make sure, you do understand what an OR statement does in an ifcheck right? i think you meant this:


  if (   first_ob->item_type != ITEM_GEM_BLUE
	  && first_ob->item_type != ITEM_GEM_RED
	  && first_ob->item_type != ITEM_GEM_YELLOW )
  {  
    send_to_char( "This item must be a gem!\n\r", ch );
    return;
  }
USA #2
I'm an idiot..lol. Thanks Gohan, I completely missed that one.
Amended on Fri 17 Aug 2007 03:39 AM by Orik
USA #3
Ok, now I've run into another problem. I've got my socket function working to run to the end and now I'm actually writing how to add the affects from the gem to the actual item. Here's what I have which I know isn't correct, but I needed a starting point.


/*Taken from ostat code*/
for( paf = first_ob->pIndexData->first_affect; paf; paf = paf->next )
  ch_printf_color( ch, "Adding %s by %d\n\r", affect_loc_name( paf->location ), paf->modifier );

/* taken from enchant_weapon */
  seperate_obj( second_ob );
  CREATE( paf, AFFECT_DATA, 1 );
  paf->type = -1;
  paf->duration = -1;

/* This needs to be paf->location from first_ob */
  paf->location = APPLY_HITROLL; 

/* This needs to be paf->modifier from first_ob */
  paf->modifier = level / 15; 

  xCLEAR_BITS( paf->bitvector );
  LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );

  extract_obj( first_obj );


So if a gem has 2 hitroll, when socketed, that will add 2 hitroll to the weapon/armor permanently.
Amended on Fri 17 Aug 2007 05:23 AM by Orik
USA #4
Came up with this, although still, I know it won't compile, but I'm getting closer I think:



/*Taken from ostat code*/
for( paf = first_ob->pIndexData->first_affect; paf; paf = paf->next )
{
  ch_printf_color( ch, "Adding %s by %d\n\r", affect_loc_name( paf->location ), paf->modifier );

/*I don't know how to define att in the function to find the string from affect_loc_name. I made mod an int. */
   att = affect_loc_name( paf->location );
   mod = paf->modifier;

/* taken from enchant_weapon */
  seperate_obj( second_ob );
  CREATE( paf, AFFECT_DATA, 1 );
  paf->type = -1;
  paf->duration = -1;

/* This needs to be paf->location from first_ob */
  paf->location = att; 

/* This needs to be paf->modifier from first_ob */
  paf->modifier = mod; 

  xCLEAR_BITS( paf->bitvector );
  LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );
}
  extract_obj( first_obj );

Amended on Fri 17 Aug 2007 05:42 AM by Orik
USA #5
If you just want the string, you can use char* or const char*. But is a string really what you want? It looks like you're assigning it into the new effect's location, so you might want to keep it as a number.
USA #6
got a couple questions:

why would you have this in a for loop?
seperate_obj( second_ob );

exactly why are you doing this when paf is already valid, you really dont need to recreate the affect anyways?
CREATE( paf, AFFECT_DATA, 1 );

also you might wanna pull the affects from the obj and not the objects index. so:
for( paf = first_ob->pIndexData->first_affect; paf; paf = paf->next )
becomes
for( paf = first_ob->first_affect; paf; paf = paf->next )

if you are copying the affect into the new object, exactly why are you removing everything that DEFINES what the affect is? i understood changing the duration to -1 so its permanent, but this i really dont.
paf->type = -1;
xCLEAR_BITS( paf->bitvector );

also like i stated why are you recreating the affect, just pull it from the object since you are gonna extract it anyways and put it on the second obj.

seperate_obj( second_ob );
for( paf = first_ob->first_affect; paf; paf = paf->next )
{
  ch_printf_color( ch, "Adding %s by %d\n\r", affect_loc_name( paf->location ), paf->modifier );
  UNLINK( paf, first_ob->first_affect, first_ob->last_affect, next, prev );
  paf->duration = -1;
  LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );
}
extract_obj( first_obj );
Amended on Fri 17 Aug 2007 08:25 AM by Gohan_TheDragonball
USA #7
Hey Gohan, That's why I was asking on here :) I didn't really know how to do what I was wanting. Your solution worked just fine. Thanks heaps.
USA #8
glad it works, i just wanted to make sure i said why i was changing what i changed instead of just reposting code.
USA #9
Ok, round three :)

Now that I have my affect adding to the second object, I want to put the short description of the first object into the second object. So when I cast ID it'll say something like


object 'a sword' is a weapon, with wear location: take wield
blah blah blah
Total Sockets: Blue (0/0) Red (1/1)  Yellow (0/1)
/*Here's the part that I want*/
Socketed: (red gem) a fiery red gem


I have this part working in the identify spell and everywhere else. I need to figure out how to put the first_ob->short_descr into the second_ob. here's what I have:


snprintf(buf1, MAX_STRING_LENGTH, "%s", first_ob->short_descr);
if ( !second_ob->sdesc1 ) /* If no socket description */
  {
    STRFREE( second_ob->sdesc1 );
    second_ob->sdesc1 = STRALLOC( buf1 );
  }


So basically, I'm putting the first object short description into buf1 then putting it into second_ob->sdesc1. This compiles, but not working. Any thoughts?
Australia Forum Administrator #10
First problem I see is that, if the description (second_ob->sdesc1) is NULL, then you are freeing it. Won't that crash?
USA #11
hmm...it didn't? So maybe that part isn't working? The if check.

**EDIT***
The problem was in the spell_identify. I was looking for obj-pIndexData->sdesc1 rather than obj->sdesc1.

It's working now. :)
Amended on Sat 18 Aug 2007 12:12 AM by Orik
USA #12
Round 4: FIGHT!

heh.

Ok, so apparently this:

	separate_obj( second_ob );
	   for( paf = first_ob->pIndexData->first_affect; paf; paf = paf->next )
		{
		   ch_printf_color( ch, "&cAffects &w%s &cby &w%d.\r\n", affect_loc_name( paf->location ), paf->modifier );
		   UNLINK( paf, first_ob->pIndexData->first_affect, first_ob->pIndexData->last_affect, next, prev);
		   paf->duration = -1;
		   LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );
			
		}
			snprintf(buf1, MAX_STRING_LENGTH, "%s", first_ob->short_descr);
			
			if( !second_ob->sdesc1 || second_ob->sdesc1[0] == '\0' )
			{
				STRFREE( second_ob->sdesc1 );
				second_ob->sdesc1 = STRALLOC( buf1 );
			}
			else if( !second_ob->sdesc2 || second_ob->sdesc2[0] == '\0' )
			{
				STRFREE( second_ob->sdesc2 );
				second_ob->sdesc2 = STRALLOC( buf1 );
			}
			else if( !second_ob->sdesc3 || second_ob->sdesc3[0] == '\0' )
			{
				STRFREE( second_ob->sdesc3 );
				second_ob->sdesc3 = STRALLOC( buf1 );
			}
			else if( !second_ob->sdesc4 || second_ob->sdesc4[0] == '\0' )
			{
				STRFREE( second_ob->sdesc4 );
				second_ob->sdesc4 = STRALLOC( buf1 );
			}
			else if( !second_ob->sdesc5 || second_ob->sdesc5[0] == '\0' )
			{
				STRFREE( second_ob->sdesc5 );
				second_ob->sdesc5 = STRALLOC( buf1 );
			}
			else if( !second_ob->sdesc6 || second_ob->sdesc6[0] == '\0' )
			{
				STRFREE( second_ob->sdesc6 );
				second_ob->sdesc6 = STRALLOC( buf1 );
			}

    extract_obj( first_ob );


causes the gems to mess up. Example:

I load my sword, load a red gem, a yellow gem a blue gem. Red gem is 1 dam, yellow gem is 1 dex, blue gem is 1 hit.

I socket the red gem, sword gets +1 dam
I socket yellow gem, sword gets +1 dex
I socket blue gem, sword gets +1 hit

Sword ends up with 3 extra affects like it should. I ID sword and it is affected dam by 1(extra), dex by 1(extra) hit by 1 (extra).

What the problem is my gems. Even though it is supposed to extract them once they are done(it does) the previous gem gets the effects from the next gem and the next gem. So I socketed my red gem first then the others, when I oinvoked the red gem again, it showed that it gave 1 dam, 1 dex, 1 hit, when it was supposed to only keep the 1 dam. So somehow, first_ob isn't getting rid of the the gems entirely and adding to them as well as the second_ob(my weapon). This in turns screws up the area file.

I'm not sure why it's not extracting the the obj correctly. Would there be a better way to do this? I'm sure there is and I'm probably doing it the hard way.
Amended on Sat 18 Aug 2007 02:20 PM by Orik
#13
for (paf = first_ob->pIndexData->first_affect; paf; paf = paf->next) {
  ch_printf_color( ch, "&cAffects &w%s &cby &w%d.\r\n", affect_loc_name( paf->location ), paf->modifier );
  UNLINK( paf, first_ob->pIndexData->first_affect, first_ob->pIndexData->last_affect, next, prev);
  paf->duration = -1;
  LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );
}

The first line assumes that paf is a member of the linked list proceeding from first_ob->pIndexData->first_affect.

The UNLINK statement invalidates that.

After the LINK statement at the end of the block, paf is a member of the list proceeding from second_ob->first_affect and the iteration step (paf = paf->next) sets paf to the next object in the second_ob->first_affect list.

To get around that you need to cache the value of paf->next:
AFFECT_DATA *paf_next; /* or whatever paf is declared as */
for (paf = first_ob->pIndexData->first_affect; paf; paf = paf_next) {
  paf_next = paf->next;
  ch_printf_color( ch, "&cAffects &w%s &cby &w%d.\r\n", affect_loc_name( paf->location ), paf->modifier );
  UNLINK( paf, first_ob->pIndexData->first_affect, first_ob->pIndexData->last_affect, next, prev);
  paf->duration = -1;
  LINK( paf, second_ob->first_affect, second_ob->last_affect, next, prev );
}



As a side note, (and it's been a while since I had to write portable C), can't the second section be rewritten as something like:
char **sdescs[6] = { &(second_ob->sdesc1), &(second_ob->sdesc2), &(second_ob->sdesc3), &(second_ob->sdesc4), &(second_ob->sdesc5), &(second_ob->sdesc6) };
short i = 0;
for (; i < 6; ++i) {
  if (*(sdescs[ i ]) == NULL || (*(sdescs[ i ]))[0] == '\0') {
    STRFREE(*(sdescs[ i ]));
    *(sdescs[ i ]) = STRALLOC( buf1 );
    break;
  }
}
Amended on Sat 18 Aug 2007 08:03 PM by Isthiriel
USA #14
Thanks Isthiriel,

I think the UNLINK statement is now where I'm getting my problems from.

If I use it, it takes away the affect from the actual gem object as if it were prototyped and you rmaffect it.

If I comment it out, it adds the affects from the next gem's affect to the previous gem. So it does what I stated above and wrecks the area file.

I don't want to use

for( paf = first_ob->first_affect; paf; paf = paf->next )


because then it takes from the extra affect field and my items don't have extra affects. I want to take the perm affects and put them onto the item as extras(which it does), it's just that the gems are getting messed up in the process.

baffling..hehe.

#15
Ok, an explanation on the uses (and abuses) of UNLINK.

SMAUG stores most objects (in the computer science sense... a struct in C) in doubly-linked lists.

A linked list is the name given to a bunch of objects where the first object has a pointer to the next, which in turn has a pointer to the next where no object in the list has a pointer to an earlier object in the list (this is important to avoid an infinite loop when attempting to traverse the list).

SMAUG's doubly-linked lists gives each object a pointer to the previous object (that is the object that points to the current object with its 'next' pointer). So it can be traversed either by following the next pointers forward, or the prev pointers backward.

Singly-linked lists are fairly easy to handle. If you want to do an insertion, you set the next pointer on the new object to the current list-head and the new object is the new head of the list.

Doubly-linked lists because you have to update three objects and four pointers (and you're usually trying to keep the number of temporary variables down) are more complicated, so the UNLINK and LINK macros are born.

LINK inserts the new object into a list specified by a head and a tail pointer.

For an empty list, new->next = NULL, new->prev = NULL, head = new, tail = new. Easy.
For a list containing item(s), we can do head- or tail- insertion, new->next = head, head->prev = new, head = new, new->prev = NULL.

So far, so good.

UNLINK has to find the object its handed in the list and then remove it from the list and repair all the references.

For an empty list, no work.
For a list containing the one item (to be removed), del->next = NULL, del->prev = NULL, head = NULL, tail = NULL.
For a list containing the item as the head, head = del->next, head->prev = NULL, del->next = NULL, del->prev = NULL.
(Ditto, but backwards for item-as-tail.)
For a list containing the item in the middle, del->prev->next = del->next, del->next->prev = del->prev, del->prev = NULL, del->next = NULL.


Taking this back to your code, the iteration follows the paf->next pointer to get the next affect in the list BUT you are calling UNLINK/LINK which both change what paf->next is actually pointing to. This is what I was trying to get across with my earlier post.

If your goal is to remove the affect from the gem and add it to the sword, then you should be able to use your code provided you cache the value of paf->next for the iteration.


IIRC, pIndexData is the prototype information? So you shouldn't be modifying (UNLINKing) it for a change to an instance. Personally, I'd destroy the gem once it has transferred its affects to the weapon. Though, that way you have to duplicate the affect from the gem pIndexData before applying it to the weapon.

Something like:

/*
 * gem_ob is the pointer to the gem object (sane variable names ftw!)
 * socketed_ob is the pointer to the socketed object receiving affects
 */
  separate_obj(gem_ob);
  for (paf = gem_ob->pIndexData->first_affect; paf; paf = paf->next) {
    /* paf is now iterating across the affects on the gem prototype, we want to copy this affect and apply it to socketed_ob */
/* Taken from SMAUG 1.8b mud.h: (tells us what we need to copy)
struct	affect_data
{
    AFFECT_DATA *	next;
    AFFECT_DATA *	prev;
    sh_int		type;
    int			duration;
    sh_int		location;
    int			modifier;
    EXT_BV		bitvector;
};
*/
    CREATE(new_paf, AFFECT_DATA, 1);
    new_paf->type = paf->type;
    new_paf->duration = paf->duration;
    new_paf->location = paf->location;
    new_paf->modifier = paf->modifier;
    xCLEAR_BITS(new_paf->bitvector);
    xSET_BITS(new_paf->bitvector, paf->bitvector);
    /* new_paf should now be a good copy of paf, so we can add it to the socketed_ob */
    LINK(new_paf, socketed_ob->first_affect, socketed_ob->last_affect, next, prev);
  }
  extract_obj(gem_ob); /* this destroys the gem? */
USA #16
yeah sorry about that i usually remember to do that, was rewriting your code kind of quick. its your call where you want to pull the affects from, it is the same either way actually, as the permanent affects are in the first-obj->first_affect list anyways. i also did that way because its then just a simple unlink/link (simple being the idiot who told you to do it that way remembers to do it properly lol).

also nick already mentioned this but you haven't seemed to change it so ill restate that i really dont know why you are freeing a null string.

			if( !second_ob->sdesc1 || second_ob->sdesc1[0] == '\0' )
			{
				STRFREE( second_ob->sdesc1 );
				second_ob->sdesc1 = STRALLOC( buf1 );
			}

it just needs to be

			if( !second_ob->sdesc1 || second_ob->sdesc1[0] == '\0' )
				second_ob->sdesc1 = STRALLOC( buf1 );
USA #17
Thanks guys, It's working great now.

Thanks for the tutorial Isthiriel. I gave everyone credit in the comments.
Amended on Sun 19 Aug 2007 03:20 AM by Orik
Australia Forum Administrator #18
I was almost going to comment again, but he changed it to:


if( !second_ob->sdesc1 || second_ob->sdesc1[0] == '\0' )


Thus, the string isn't necessarily NULL, it might be present, but empty (maybe).
#19
Strictly, shouldn't it be:
if (second_ob->sdesc1 && second_ob->sdesc1[0] == '\0') {
  STRFREE(second_ob->sdesc1);
}
if (!second_ob->sdesc1) { /* or == NULL for Correctness */
  second_ob->sdesc1 = STRALLOC(buf1);
}

Because otherwise you're leaking a byte everytime the function runs.
Australia Forum Administrator #20
Er, no I don't think so. The way it was written it did this:

  • If there is no description pointer, or
  • If there is a description pointer, and it was an empty string


Then:

  • Free the old description pointer (which would have no effect if the pointer was NULL) - however if it was the empty string it would be freed.


However the problem I see now is that if there is an existing description, however you want the new one to be different, then it won't be.
#21
So STRFREE is null-checked?

Quote:
However the problem I see now is that if there is an existing description, however you want the new one to be different, then it won't be.


That's why it's repeated six times with else-ifs. It tries to put buf1 in each of the six sdesc slots, until it either succeeds (by finding an "empty" slot) or runs off the end.

And if that's SMAUG's standard idiom for it, then it badly needs at least some utility functions to clean it up and/or conversion to a linked-list structure.

... just because it's C doesn't mean you can't make it object-oriented :)
USA #22
Quote:
And if that's SMAUG's standard idiom for it, then it badly needs at least some utility functions to clean it up and/or conversion to a linked-list structure.

Groan. Don't get me started on places where SMAUG could use utility functions to make things cleaner, safer and easier to understand. #1 and #3 are just cosmetic (still important in my book) but I think everybody would agree that #2 is good no matter what...
USA #23
On to round 5 of this madness.

Everything is working except for the loading of the item.

It writes successfully in fwrite_fuss_object, but in fread_fuss_object it doesn't read it correctly. It just sets the Socket values back to 0. I copied the Item values code pretty much so here's what Sockets looks like in fread_fuss_object:


           if( !str_cmp( word, "Sockets" ) )
            {
               char *ln = fread_line( fp );
               int x1, x2, x3, x4, x5, x6;
               x1 = x2 = x3 = x4 = x5 = x6 = 0;

               sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );

               pObjIndex->socket[0] = x1;
               pObjIndex->socket[1] = x2;
               pObjIndex->socket[2] = x3;
               pObjIndex->socket[3] = x4;
               pObjIndex->socket[4] = x5;
               pObjIndex->socket[5] = x6;

               break;
            }


It's setting the values back at 0. When I savearea and check the file to see if it saved, it'll say

"Sockets 1 1 2 0 0 0"

That means that i had 1 blue, 1 red, 2 yellow sockets. It shows it directly in the area file after a savearea. Then when I reboot or shutdown and start again, the file loads as

"Sockets 0 0 0 0 0 0"

So for some odd reason, the socket value isn't carrying over.

**EDIT**
Ok, I've found out that it loads with the socket values, but when I oinvoke and ostat the sword it shows no values. Then when I savearea it saves to "Sockets 0 0 0 0 0 0"

do_ostat

   ch_printf_color( ch, "&cSocketed Slots : &BBlue &z(&w%d/&W%d&z) &RRed &z(&w%d/&W%d&z) &YYellow &z&z(&w%d/&W%d&z)&w\r\n",
                    obj->pIndexData->usocket[0], obj->pIndexData->socket[0], 
                                        obj->pIndexData->usocket[1], obj->pIndexData->socket[1],
                    obj->pIndexData->usocket[2], obj->pIndexData->socket[2]);


it shows "Socketed Slots : Blue (0/0) Red (0/0) Yellow (0/0)"

when it should show
"Socketed Slots : Blue (0/1) Red (0/1) Yellow (0/2)"

I'm guessing it's going to be in db.c create_object function. hmm..

create_object

   obj->socket[0] = pObjIndex->socket[0];
   obj->socket[1] = pObjIndex->socket[1];
   obj->socket[2] = pObjIndex->socket[2];

   obj->usocket[0] = 0;
   obj->usocket[1] = 0;
   obj->usocket[2] = 0;
Amended on Sun 19 Aug 2007 08:04 PM by Orik
USA #24
So when I set

obj->socket[0] = 1;
obj->socket[1] = 2;
obj->socket[2] = 3;

It was able to load as 1, 2, and 3. When I set it back to

  obj->socket[0] = pObjIndex->socket[0];
   obj->socket[1] = pObjIndex->socket[1];
   obj->socket[2] = pObjIndex->socket[2];


It showed 0 again on oinvoking. The area file still read that it was what it was supposed to be, it just loaded as 0's.

I then added 3 more value types in all the respective areas and added the 3 new value types in create_object and when I loaded, set the new value types, savea, checked file, was still correct, shutdown, checked file again, was correct, booted up, correct, oinvoke, the three new value types were 0 on the object even though they were correct in the area file.

Gah, this is annoying.
#25
Hmm. Not really enough information to work from.

I assume you're running some version of SmaugFuss?

Have you tried examining sscanf's return value?

I might be able to help more with the complete listings of fread_fuss_object, fwrite_fuss_object and create_object :-/ (Is there any way to attach files to posts here?)
USA #26
I am using Smaugfuss1.8.

I'll get more detailed information when I get home from work. I'll check out sscanf as well.

USA #27
maximum is 6000 chars. I'll post my code.
fread_fuss_object
Here's my sockets.

            if( !str_cmp( word, "Sockets" ) )^M
            {^M
               char *ln = fread_line( fp );^M
               int x1, x2, x3, x4, x5, x6;^M
               x1 = x2 = x3 = x4 = x5 = x6 = 0;^M
^M
               sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );^M
^M
               pObjIndex->socket[0] = x1;^M
               pObjIndex->socket[1] = x2;^M
               pObjIndex->socket[2] = x3;^M
               pObjIndex->socket[3] = x4;^M
               pObjIndex->socket[4] = x5;^M
               pObjIndex->socket[5] = x6;^M
^M
               break;^M
            }^M
            KEY( "Socketable", pObjIndex->socket_item, fread_number( fp ) );^M
            KEY( "Socket1", pObjIndex->sdesc1, fread_string( fp ) );^M
            KEY( "Socket2", pObjIndex->sdesc2, fread_string( fp ) );^M
            KEY( "Socket3", pObjIndex->sdesc3, fread_string( fp ) );^M
            KEY( "Socket4", pObjIndex->sdesc4, fread_string( fp ) );^M
            KEY( "Socket5", pObjIndex->sdesc5, fread_string( fp ) );^M
            KEY( "Socket6", pObjIndex->sdesc6, fread_string( fp ) );^M

Here's Values

         case 'V':
            if( !str_cmp( word, "Values" ) )
            {
               char *ln = fread_line( fp );
               int x1, x2, x3, x4, x5, x6;
               x1 = x2 = x3 = x4 = x5 = x6 = 0;

               sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );

               pObjIndex->value[0] = x1;
               pObjIndex->value[1] = x2;
               pObjIndex->value[2] = x3;
               pObjIndex->value[3] = x4;
               pObjIndex->value[4] = x5;
               pObjIndex->value[5] = x6;

               break;
            }

Here's used sockets


                 case 'U':^M
                        if( !str_cmp( word, "Used Sockets" ) )^M
            {^M
               char *ln = fread_line( fp );^M
               int x1, x2, x3, x4, x5, x6;^M
               x1 = x2 = x3 = x4 = x5 = x6 = 0;^M
^M
               sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );^M
^M
               pObjIndex->usocket[0] = x1;^M
               pObjIndex->usocket[1] = x2;^M
               pObjIndex->usocket[2] = x3;^M
               pObjIndex->usocket[3] = x4;^M
               pObjIndex->usocket[4] = x5;^M
               pObjIndex->usocket[5] = x6;^M
^M
               break;^M
            }^M
USA #28
fwrite_fuss_project

   val0 = pObjIndex->value[0];^M
   val1 = pObjIndex->value[1];^M
   val2 = pObjIndex->value[2];^M
   val3 = pObjIndex->value[3];^M
   val4 = pObjIndex->value[4];^M
   val5 = pObjIndex->value[5];^M
^M
   sock0 = pObjIndex->socket[0];^M
   sock1 = pObjIndex->socket[1];^M
   sock2 = pObjIndex->socket[2];^M
   sock3 = pObjIndex->socket[3];^M
   sock4 = pObjIndex->socket[4];^M
   sock5 = pObjIndex->socket[5];^M
^M
   usock0 = pObjIndex->usocket[0];^M
   usock1 = pObjIndex->usocket[1];^M
   usock2 = pObjIndex->usocket[2];^M
   usock3 = pObjIndex->usocket[3];^M
   usock4 = pObjIndex->usocket[4];^M
   usock5 = pObjIndex->usocket[5];^M

further down:

   fprintf( fpout, "Values   %d %d %d %d %d %d\n", val0, val1, val2, val3, val4, val5 );^M
   fprintf( fpout, "Socketable       %d\n", pObjIndex->socket_item );^M
   fprintf( fpout, "Sockets   %d %d %d %d %d %d\n", sock0, sock1, sock2, sock3, sock4, sock5 );^M
   fprintf( fpout, "Used Sockets   %d %d %d %d %d %d\n", usock0, usock1, usock2, usock3, usock4, usock5 );^M
   fprintf( fpout, "Stats    %d %d %d %d %d\n", pObjIndex->weight,
            pObjIndex->cost, pObjIndex->rent ? pObjIndex->rent : ( int )( pObjIndex->cost / 10 ),
            pObjIndex->level, pObjIndex->layers );
^M
   if( pObjIndex->sdesc1 && pObjIndex->sdesc1[0] != '\0' )^M
      fprintf( fpout, "Socket1     %s~\n", pObjIndex->sdesc1 );^M
   if( pObjIndex->sdesc2 && pObjIndex->sdesc2[0] != '\0' )^M
      fprintf( fpout, "Socket2     %s~\n", pObjIndex->sdesc2 );^M
   if( pObjIndex->sdesc3 && pObjIndex->sdesc3[0] != '\0' )^M
      fprintf( fpout, "Socket3     %s~\n", pObjIndex->sdesc3 );^M
   if( pObjIndex->sdesc4 && pObjIndex->sdesc4[0] != '\0' )^M
      fprintf( fpout, "Socket4     %s~\n", pObjIndex->sdesc4 );^M
   if( pObjIndex->sdesc5 && pObjIndex->sdesc5[0] != '\0' )^M
      fprintf( fpout, "Socket5     %s~\n", pObjIndex->sdesc5 );^M
   if( pObjIndex->sdesc6 && pObjIndex->sdesc6[0] != '\0' )^M
      fprintf( fpout, "Socket6     %s~\n", pObjIndex->sdesc6 );^M
^M
USA #29
Create_object

   obj->wear_flags = pObjIndex->wear_flags;
   obj->value[0] = pObjIndex->value[0];^M
   obj->value[1] = pObjIndex->value[1];^M
   obj->value[2] = pObjIndex->value[2];^M
   obj->value[3] = pObjIndex->value[3];^M
   obj->value[4] = pObjIndex->value[4];^M
   obj->value[5] = pObjIndex->value[5];^M
^M
   obj->socket[0] = pObjIndex->socket[0];^M
   obj->socket[1] = pObjIndex->socket[1];^M
   obj->socket[2] = pObjIndex->socket[2];^M
^M
   obj->usocket[0] = 0;^M
   obj->usocket[1] = 0;^M
   obj->usocket[2] = 0;^M
^M
   obj->weight = pObjIndex->weight;
USA #30
The object itself writes correctly to the area file. And it loads correctly on startup. When I oinvoke the socket numbers are all 0, but when I check the area file they are the numbers that they need to be. So it needs to be in create_object I would think.
USA #31
you might wanna do something like this:

            if( !str_cmp( word, "#ENDOBJECT" ) )
            {
               if( !pObjIndex->description )
                  pObjIndex->description = STRALLOC( "" );
               if( !pObjIndex->action_desc )
                  pObjIndex->action_desc = STRALLOC( "" );
               if( !pObjIndex->sdesc1 )
                  pObjIndex->sdesc1 = STRALLOC( "" );
               if( !pObjIndex->sdesc2 )
                  pObjIndex->sdesc2 = STRALLOC( "" );
               if( !pObjIndex->sdesc3 )
                  pObjIndex->sdesc3 = STRALLOC( "" );
               if( !pObjIndex->sdesc4 )
                  pObjIndex->sdesc4 = STRALLOC( "" );
               if( !pObjIndex->sdesc5 )
                  pObjIndex->sdesc5 = STRALLOC( "" );
               if( !pObjIndex->sdesc6 )
                  pObjIndex->sdesc6 = STRALLOC( "" );
            ....

and my guess is that your use of "Used Sockets" in the write and read procedure is whats messing you up. you are supposed to use a single word, in your case sscanf is messing up since your reading "Sockets 0 0 0 0 0 0". dump the space and make it "UsedSockets" and see if the problem persists. you would have noticed this problem from the beginning except since you are scanning the whole line, the surplus at the end of the line is discarded and the error warning does not come up since there is no extra words in the file. just for the record, in this case you should not be using sscanf, but instead just using fread_number() each time. i am actually surprised its even still being used, i figured when samson switched to this area format he would get rid of it and save/read every variable separately.
USA #32
only my suggestion but here is how i would have done this:

            if( !str_cmp( word, "Socket" ) )
            {
               int x = fread_number(fp);
               pObjIndex->socket[x] = fread_number(fp);
               pObjIndex->usocket[x] = fread_number(fp);
               break;
            }

    for ( sock = 0; sock < 6; sock++ )
        fprintf( fpout, "Socket   %d %d %d\n", sock, pObjIndex->socket[sock], pObjIndex->usocket[sock]);


cuts you down from around 40 lines to 8 and reduces you from 26 variables to 2.
Amended on Wed 22 Aug 2007 08:07 AM by Gohan_TheDragonball
USA #33
I believe that was the problem. One whole space caused me quite a bit of grief...heh. It loads the object with the socket values now.

Only thing now is that when I save my char, quit, and log back in, the used sockets don't load on the object, but I believe I know how to fix that so I'll just have to wait and do that once I get home from work tonight.

Thanks for the help guys.