Wow, lots of questions to answer here
First off; the way the system currently works is by having most objects just be "the prototype". This saves a lot of memory, since non-prototyped objects need all their data alloc'ed, as you have discovered.
That said, if you want the effect you are looking for, you are on the right path, and the algorithm looks about how I imagine it needs to be. But you don't need to alter so much - every item in the game is already instantiated, and the save function should check if it needs to save some information differently.
1. When saving object vnum "X", as GET_OLC_OBJ(ch)
2. Loop through all items in game, "item"
3. If item->vnum == X
4. For each value on the item, "val"
5. If item->val != GET_OLC_OBJ(ch)->val (may use strcmp or similar for strings here)
6. if item->val != obj_proto->val ----> free(item->val); fi
7. item->val = GET_OLC_OBJ(ch)->val (may use strdup or similar for strings here)
8. endif #5
9. end foreach #4
10. end if #3
You should not need to alter the real number of the item.
An instantiated, altered object will have pointers to the correct places:
obj->name == obj_proto[obj->rnum].name == "foo bar"
obj->value_1 == 12 (obj_proto[obj->rnum].value_1 == 14)
obj->short_desc == "some string" (obj_proto[obj->rnum].short_desc == "the original desc")
And the save function already checks if these point to the same value as the obj_proto before saving:
Code:
#define TEST_OBJS(obj1, obj2, field) ((!obj1->field || !obj2->field || \
strcmp(obj1->field, obj2->field)))
#define TEST_OBJN(field) (obj->obj_flags.field != temp->obj_flags.field)
if (TEST_OBJS(obj, temp, name))
fprintf(fp, "Name: %s\n", obj->name ? obj->name : "Undefined");
if (TEST_OBJS(obj, temp, short_description))
fprintf(fp, "Shrt: %s\n", obj->short_description ? obj->short_description : "Undefined");