The Carnivores 2 *.SAV files are saved games, containing the hunter's name, points, settings, and trophies. These files are always exactly 1659 bytes long.
File name[]
All saved games are named according to the pattern "trophy0#.sav", where # is a number between 0 and 5, corresponding to each game slot.
Code[]
The following code in Hunt.h defines the structure of the sav files:
typedef struct _TTrophyItem {
int ctype, weapon, phase,
height, weight, score,
date, time;
float scale, range;
int r1, r2, r3, r4;
} TTrophyItem;
typedef struct _TStats {
int smade, success;
float path, time;
} TStats;
typedef struct _TTrophyRoom {
char PlayerName[128];
int RegNumber;
int Score, Rank;
TStats Last, Total;
TTrophyItem Body[24];
} TTrophyRoom;
The following code in Game.cpp loads the sav files:
void LoadTrophy()
{
int pr = TrophyRoom.RegNumber;
FillMemory(&TrophyRoom, sizeof(TrophyRoom), 0);
TrophyRoom.RegNumber = pr;
DWORD l;
char fname[128];
int rn = TrophyRoom.RegNumber;
wsprintf(fname, "trophy0%d.sav", TrophyRoom.RegNumber);
HANDLE hfile = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile==INVALID_HANDLE_VALUE) {
PrintLog("===> Error loading trophy!\n");
return;
}
ReadFile(hfile, &TrophyRoom, sizeof(TrophyRoom), &l, NULL);
ReadFile(hfile, &OptAgres, 4, &l, NULL);
ReadFile(hfile, &OptDens , 4, &l, NULL);
ReadFile(hfile, &OptSens , 4, &l, NULL);
ReadFile(hfile, &OptRes, 4, &l, NULL);
ReadFile(hfile, &FOGENABLE, 4, &l, NULL);
ReadFile(hfile, &OptText , 4, &l, NULL);
ReadFile(hfile, &OptViewR, 4, &l, NULL);
ReadFile(hfile, &SHADOWS3D, 4, &l, NULL);
ReadFile(hfile, &OptMsSens, 4, &l, NULL);
ReadFile(hfile, &OptBrightness, 4, &l, NULL);
ReadFile(hfile, &KeyMap, sizeof(KeyMap), &l, NULL);
ReadFile(hfile, &REVERSEMS, 4, &l, NULL);
ReadFile(hfile, &ScentMode, 4, &l, NULL);
ReadFile(hfile, &CamoMode, 4, &l, NULL);
ReadFile(hfile, &RadarMode, 4, &l, NULL);
ReadFile(hfile, &Tranq , 4, &l, NULL);
ReadFile(hfile, &OPT_ALPHA_COLORKEY, 4, &l, NULL);
ReadFile(hfile, &OptSys , 4, &l, NULL);
ReadFile(hfile, &OptSound , 4, &l, NULL);
ReadFile(hfile, &OptRender, 4, &l, NULL);
SetupRes();
CloseHandle(hfile);
TrophyRoom.RegNumber = rn;
PrintLog("Trophy Loaded.\n");
// TrophyRoom.Score = 299;
}
This code in Game.cpp (immediately following the above LoadTrophy()
function) saves the sav file:
void SaveTrophy()
{
DWORD l;
char fname[128];
wsprintf(fname, "trophy0%d.sav", TrophyRoom.RegNumber);
int r = TrophyRoom.Rank;
TrophyRoom.Rank = 0;
if (TrophyRoom.Score >= 100) TrophyRoom.Rank = 1;
if (TrophyRoom.Score >= 300) TrophyRoom.Rank = 2;
HANDLE hfile = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
PrintLog("==>> Error saving trophy!\n");
return;
}
WriteFile(hfile, &TrophyRoom, sizeof(TrophyRoom), &l, NULL);
WriteFile(hfile, &OptAgres, 4, &l, NULL);
WriteFile(hfile, &OptDens , 4, &l, NULL);
WriteFile(hfile, &OptSens , 4, &l, NULL);
WriteFile(hfile, &OptRes, 4, &l, NULL);
WriteFile(hfile, &FOGENABLE, 4, &l, NULL);
WriteFile(hfile, &OptText , 4, &l, NULL);
WriteFile(hfile, &OptViewR, 4, &l, NULL);
WriteFile(hfile, &SHADOWS3D, 4, &l, NULL);
WriteFile(hfile, &OptMsSens, 4, &l, NULL);
WriteFile(hfile, &OptBrightness, 4, &l, NULL);
WriteFile(hfile, &KeyMap, sizeof(KeyMap), &l, NULL);
WriteFile(hfile, &REVERSEMS, 4, &l, NULL);
WriteFile(hfile, &ScentMode, 4, &l, NULL);
WriteFile(hfile, &CamoMode , 4, &l, NULL);
WriteFile(hfile, &RadarMode, 4, &l, NULL);
WriteFile(hfile, &Tranq , 4, &l, NULL);
WriteFile(hfile, &OPT_ALPHA_COLORKEY, 4, &l, NULL);
WriteFile(hfile, &OptSys , 4, &l, NULL);
WriteFile(hfile, &OptSound , 4, &l, NULL);
WriteFile(hfile, &OptRender, 4, &l, NULL);
CloseHandle(hfile);
PrintLog("Trophy Saved.\n");
}
This code in the function AddShipTask()
in Game.cpp saves a trophy to the trophy room:
if (!Tranq) {
TrophyTime = 20 * 1000;
TrophyBody = t;
TrophyRoom.Body[t].ctype = Characters[cindex].CType;
TrophyRoom.Body[t].scale = Characters[cindex].scale;
TrophyRoom.Body[t].weapon = CurrentWeapon;
TrophyRoom.Body[t].score = (int)score;
TrophyRoom.Body[t].phase = (RealTime & 3);
TrophyRoom.Body[t].time = (st.wHour<<10) + st.wMinute;
TrophyRoom.Body[t].date = (st.wYear<<20) + (st.wMonth<<10) + st.wDay;
TrophyRoom.Body[t].range = VectorLength( SubVectors(Characters[cindex].pos, PlayerPos) ) / 64.f;
PrintLog("Trophy added: ");
PrintLog(DinoInfo[Characters[cindex].CType].Name);
PrintLog("\n");
}
Format[]
The actual format is as follows:
- char(128) - Hunter's name,
fname
(maximum name length is actually only 10 characters; the rest of the field is null-padded)
- long -
RegNumber
(corresponds to the position on the game sign-in screen; this doesn't actually have any effect and only seems to be written when an account is initially created)
- long - Total credits
- long - Rank (This is left over from the Carnivores ranking system. It is reset to 0 and recalculated every time the account is saved; if the player has more than 100 credits, it's set to 1; and if more than 300 credits, it's set to 2.)
- long - Shots made during the last hunt
- long - Shots succeeded during the last hunt (equal to the number of pointable animals downed)
- float(4) - Path traveled during the last hunt
- float(4) - Time hunted during the last hunt
- long - Total shots made
- long - Total shots succeeded (equal to the number of pointable animals downed)
- float(4) - Total path traveled
- float(4) - Total time hunted
- // For each trophy (1-24)
- long - Animal,
ctype
(This is a number from 1 to n corresponding with the position in _RES.TXT (for instance, Parasaurolophus is the seventh animal listed in _RES.TXT, so the value in this field for a Parasaurolophus would be 7). When a trophy is removed, this field is actually just changed to 0, and the trophy information is not otherwise changed until another trophy gets saved in the same slot, making trophy unremoval possible.)
- long - Weapon (Similar to the animal field, this is a number from 0 to n-1 corresponding with the position in _RES.TXT, so the Rifle, which is fifth, has a value of 4.)
- long -
phase
(the purpose of this field is unknown, but it is calculated via RealTime AND 3; RealTime is based on timeGetTime()
, which is how many milliseconds have passed since the system was last started up)
- long - Height (seems to never be used; scale is instead used to calculate a trophy's height)
- long - Weight (seems to never be used; scale is instead used to calculate a trophy's weight)
- long - Score
- long - Date (this is calculated by left-shifting the year by 20, left-shifting the month by 10, and adding them and the date together:
(st.wYear<<20) + (st.wMonth<<10) + st.wDay;
(in Game.cpp))
- long - Time (this is calculated by left-shifting the hour by 10 and adding it to the minute:
(st.wHour<<10) + st.wMinute;
(in Game.cpp))
- float(4) - Scale (as calculated from scaleO and scaleA in _RES.TXT)
- float(4) - Range of kill
- long - r1 (unused; possibly meant to allow for future addition of trophy information)
- long - r2 (unused; possibly meant to allow for future addition of trophy information)
- long - r3 (unused; possibly meant to allow for future addition of trophy information)
- long - r4 (unused; possibly meant to allow for future addition of trophy information)
- long - Aggressivity
- long - Density
- long - Sensitivity
- long - Resolution
- long - Fog
- long - Textures
- long - View range
- long - 3D shadows
- long - Mouse sensitivity
- long - Brightness
- long - Forward
- long - Backward
- long - Turn up
- long - Turn down
- long - Turn left
- long - Turn right
- long - Fire
- long - Get weapon
- long - Step left
- long - Step right
- long - Strafe
- long - Jump
- long - Run
- long - Crouch
- long - Call
- long - Change call
- long - Binoculars
- long - Reverse mouse
- long - Cover scent
- long - Camouflage
- long - Radar
- long - Tranquilizer
- long - OPT_ALPHA_COLORKEY
- long - Measurement
- long - Audio driver
- long - Video driver
|