Saints Row IV & SR:TT Save Game schema

Arglaar

Nitpicking Bastard
As you may know, Corrodias has put together a fairly comprehensive Save-Game editor that is unfortunately missing a few key elements.

Would you happen to have the list handy of what data is stored in the save files and their offsets?
 
Ah, yes.. trial and error has revealed enough to satisfy our basic desires, but there's always more. I'm actually not very good at this sort of hacking, so my ham-fisted approach has its limits. Some examples of the specific challenges off the top of my head:

The vehicle data in the garage slots is not understood. We can copy and move vehicles around, and i know the vehicle's ID, but editing its upgrades, colors, and whatnot is not yet possible.

The structure of the owned territory list is only partly understood. I'm currently identifying them by offset, but it seems that some kind of signature comes before the status of each territory. It's a hash of the name, maybe, but it's 8 bytes and i haven't been able to tell what it means. We identified the territories by hand: edit, load game, see which changed, etc. Activities and properties are probably similar; we haven't bothered to figure out which is which.

As i recall, weapon upgrades consist of a 200 byte area for the hashes of the weapon names, then 200 bytes of weapon levels that run in parallel with the first array. That was tricky; fortunately, Minimaul already had that figured out. It would have taken me a while!

Mission completion status works a lot like territories. I couldn't figure out what it is that the identifiers are hashes of, though. Doesn't seem to be the mission name (steelport here i am) or internal name (m04) upper or lowercase. Maybe the hashing just works differently.

For all of these, i'm using static lists of territories, weapons, etc. If those things change, the editor will cope with them to varying degrees of success. Adding a territory to the game would completely confuse it. If i learn more about where they're listed in the game's files, and how they're matched up with the records in the save, i assume i can make it dynamically determine the names of things.
 
Looks like it breaks down like this(this is big):

uint32 checksum
uint32 version
uint32 minor version (I think minor changes can still be loaded, so we can change something but still load old data)
int32 build version
65 characters for the level name, null terminated
uint64 object handle of the closest crib to the save(where you will come back when you load this save)
9 bytes(maybe 18 if unicode?) for save time
9 bytes(maybe 18 if unicode?) for save data
uint32 mission save description id
uint percent of game completed

this says game clock time:
uint16 current year
uint8 month
uint8 day
uint8 hour
uint8 minutes
uint8 seconds
uint8 day of week
uint8 moon day (number of days along the moon-phase cycle)
uint32 current day ticks with the following large comment:
// The current time of day. This maps to a 24 hour period, when the integer rolls over,
// a new day begins.
// Note: This is much more accurate than having a float that is incremented every
//frame by another float. For example, assuming 30fps and a non-scaled time,
//this method would be off by 15 frames, or half a second over a 24-hour period.
//If it just used floats, it would be off by 6068 frames, or 202 seconds! At
//120fps, this method is off by 53 seconds.
float elapsed seconds
uint32 elapsed seconds
uint32 bitfield for unlocked dlc packs when the save was made

bool has cheated
int number of saved cheats
array of 200 uint32 checksums for saved cheats

int32 number of aerial stunts found
int32 number of secret areas found
int32 number of jumps found
int32 number of collectibles
foreach collectible(24 of them I believe):
uint64 object handle of collectible​
uint32 enum of collectible type (drug=0, money, sex doll, photo op)​

// avatar appearance data
int32 number of morphs
for each of 128 possible morphs:
int32 instance index​
float value​
int32 hair color save buffer size
48 bytes for hair color save buffers
int32 number of active customizations
foreach customization possible(128):
uint32 checksum of item name​
int32 variant id​
uint32 enum of player slot(body=0, head hair, beard hair, eyebrows, mouth, headwear, facewear, eyewear, ear piercing, neck, bra, lower body, shoes, left wrist, right wrist, gloves, face piercing, suit, hat hair combined, privacy bar top, privacy bar bottom, parachute)​
uint32 num shader values​
9 uint32 checksum values for shaders (for hair values are paired for primary and secondary color)​
int32 mesh id​
uint8 gender enum (male = 0, female)
uint8 race enum (asian, blcok, hispanic, white)
uint32 player preset enum (average=0, slender, overweight, atheletic, obese, bodybuilder)
uint8 skin swatch index
int32 triangle slider x value
int32 triangle slider y value
513 uint8's for active composite layers

// personality
uint8 taunt
uint8 compliment
uint8 show parachute
uint8 unused
uint32 persona type
int32 facial expression
uint32 voice enum (male white=0, male black, male white accent, female white, female black, female latino, zombie)
512 bytes reserved for future use(might be in use for dlc, unknown)
uint32 difficulty level enum (casual = 0, normal, hardcore)

// gang customization
4 uint32 character crcs
4 uint32 category crcs
uint8 tag index
uint8 pose index
uint8 voice index
3 uint8 vehicle infos

// gameplay

// activity stuff
uint8 bit flags for played escort tutorial, heli tp rescue mission, and heli br rescue mission
for each activity info(64 of them):
uint32 checksum of activity name​
uint32 max level completed​
uint8 completed levels(bitfield since you can play odd levels with coop)​
uint8 completed levels in coop​
uint32 num infos
uint64 activity trigger explorations

// hitman
uint32 number of saved hitman
for each target group(7 of them):
uint32 num targets​
uint32 num completed targets​
for each possible target(7 of them):​
uint8 bitfield(completed, unlocked, targeted)​

// chop shops
for each chop shop(5 of them):
uint32 checksum of shop name​
uint32 wanted vehicle index​
uint8 completed vehicle bitfield​
bool unlocked​

// challenges
for each challenge(41 of them):
float progress​
uint8 bitfield(unlcoked, completed)​
// survival
for each survival(26 of them):
uint64 survival object handle​
uint32 respect earned​
uint8 survival difficulty enum(easy=0, medium, hard)​
bool unlocked​

// flashpoints
32 uint64 object handles
uint32 bitfield for completed flashpoints

// stats
for each stat tracked(149 of them saved to gamesave starting with enum value 68):
union:​
bool flagged​
int32 integer​
float floating​
void *complex data​
int32 total percent​
uint32 pct stat enum:​
STATS_TIME_PLAYED=0,​
STATS_HIGHEST_RANK_ACHIEVED,​
STATS_TOTAL_CASH_EARNED,​
STATS_TOTAL_CASH_SPENT,​
STATS_HOSPITAL_BILLS,​
STATS_BAIL_MONEY,​
STATS_MISSIONS_ATTEMPTED,​
STATS_MISSIONS_FAILED,​
STATS_MISSION_SUCCESS_RATE,​
STATS_DEATHS,​
STATS_HOLDUPS_STORES_ROBBED,​
STATS_ARRESTS,​
STATS_TOTAL_DAMAGE_TAKEN,​
STATS_TIME_AT_MAX_POLICE_NOTORIETY,​
STATS_TIME_AT_MAX_GANG_NOTORIETY,​
STATS_TIME_AT_MAX_DECKER_NOTORIETY,​
STATS_TIME_AT_MAX_LUCHADOR_NOTORIETY,​
STATS_TIME_AT_MAX_MORNINGSTAR_NOTORIETY,​
// Completion (NOTE: These get updated based on the savegame regardless of placement)​
STATS_MISSIONS_STRONGHOLDS_COMPLETED,​
STATS_ACTIVITIES_COMPLETED,​
STATS_NEIGHBORHOODS_EXPLORED,​
STATS_SHORTCUTS_FOUND,​
STATS_FLASHPOINTS_COMPLETED,​
STATS_STORES_OWNED,​
STATS_DRUG_PACKAGES_FOUND,​
STATS_MONEY_PALLETS_FOUND,​
STATS_SEX_DOLLS_FOUND,​
STATS_PHOTO_OPS_FOUND,​
STATS_HOMIEZ_ACQUIRED,​
STATS_NEIGHBORHOODS_CONTROLLED,​
STATS_HITMAN_TARGETS_ELIMINATED,​
STATS_CHOPSHOP_VEHICLES_DELIVERED,​
// Activities (NOTE: These get updated based on the savegame regardless of placement)​
STATS_ESCORT_LEVELS_COMPLETED,​
STATS_DRUG_TRAFFICKING_LEVELS_COMPLETED,​
STATS_HELI_ASSAULT_LEVELS_COMPLETED,​
STATS_FRAUD_LEVELS_COMPLETED,​
STATS_TANK_MAYHEM_LEVELS_COMPLETED,​
STATS_RUNNING_MAN_LEVELS_COMPLETED,​
STATS_GUARDIAN_ANGEL_LEVELS_COMPLETED,​
STATS_HUMAN_TORCH_LEVELS_COMPLETED,​
STATS_SNATCH_LEVELS_COMPLETED,​
STATS_MAYHEM_LEVELS_COMPLETED,​
// Weapons​
STATS_SHOT_HIT_PERCENTAGE,​
STATS_BEST_WEAPON,​
// Weapons (Hidden)​
STATS_SHOTS_FIRED,​
// Vehicles​
STATS_NUMBER_OF_UNIQUE_VEHICLES_OWNED, // NOTE: This gets updated based on the savegame regardless of placement​
// Distance​
STATS_TOTAL_DISTANCE_TRAVELLED,​
STATS_DISTANCE_BY_VEHICLE,​
// Distance (Hidden)​
STATS_DISTANCE_ON_FOOT,​
// Co-op​
STATS_COOP_TIME_PLAYED,​
STATS_COOP_MISSIONS_STRONGHOLDS_COMPLETED, // NOTE: This gets updated based on the savegame regardless of placement​
STATS_COOP_ACTIVITIES_COMPLETED, // NOTE: This gets updated based on the savegame regardless of placement​
STATS_COOP_KILLS,​
STATS_COOP_DEATHS,​
STATS_COOP_CAT_MOUSE_MOST_POINTS_EARNED,​
STATS_COOP_CAT_MOUSE_CASH_EARNED,​
// Hidden (used for achievement unlocking purposes)​
STATS_TIME_PLAYED_MALE,​
STATS_TIME_PLAYED_FEMALE,​
STATS_ANGEL_CITY_TAKEOVERS_COMPLETED,​
STATS_KINZIE_CITY_TAKEOVERS_COMPLETED,​
STATS_PIERCE_CITY_TAKEOVERS_COMPLETED,​
STATS_ZIMOS_CITY_TAKEOVERS_COMPLETED,​
STATS_GAMBLING_TOTAL_MONEY_GAMBLED,​
STATS_TESTICULAR_ASSAULT_TOTAL_ASSAULTS,​
STATS_TAUNTING_TOTAL_COMPLIMENTS_AND_TAUNTS,​
STATS_TOTAL_DUKES_STYLE_VEHICLE_HIJACKS,​
STATS_TOTAL_COLLECTIBLES_FOUND,​
STATS_CHALLENGES_COMPLETED,​
///////////////////////​
// SAVED TO SAVEGAME //​
///////////////////////​
// NOTE: Be sure to update STATS_FIRST_SAVEGAME_STAT!​
// NOTE: Be sure to update SAVEGAME_VERSION!​
// General​
STATS_TOTAL_RESPECT,​
STATS_CASH_EARNED_PER_DAY,​
STATS_CUSTOM_ITEMS_CASH_SPENT,​
STATS_CAR_CUSTOMIZE_CASH_SPENT,​
STATS_TAUNTING_TOTAL_COMPLIMENTS,​
STATS_TAUNTING_TOTAL_TAUNTS,​
STATS_TAUNTING_TOTAL_CIVILIANS_TAUNTED,​
STATS_TAUNTING_TOTAL_COPS_TAUNTED,​
STATS_TAUNTING_TOTAL_GANG_MEMBERS_TAUNTED,​
STATS_HOMIES_RECRUITED,​
// General (Hidden)​
STATS_CARS_CUSTOMIZED,​
STATS_GAMBLING_TOTAL_MONEY_WON,​
STATS_TIMES_GRABBED_BY_BRUTE,​
STATS_HOSTAGE_HOSTAGES_TAKEN,​
STATS_UPGRADES_PURCHASED,​
STATS_UPGRADES_CASH_SPENT,​
// Activities​
STATS_HELI_ASSAULT_TARGETS_DESTROYED,​
STATS_FRAUD_LONGEST_DIVE_DISTANCE,​
STATS_FRAUD_TOTAL_DIVE_DISTANCE,​
STATS_FRAUD_CASH_CLAIMED,​
STATS_TANK_MAYHEM_DAMAGE_DONE,​
STATS_RUNNING_MAN_CASH_EARNED,​
STATS_MAYHEM_DAMAGE_DONE,​
STATS_ACTIVITY_CASH_EARNED,​
STATS_ACTIVITY_RESPECT_EARNED,​
// Weapons (Hidden)​
STATS_PISTOL_SHOTS_FIRED,​
STATS_PISTOL_HIT_PERCENTAGE,​
STATS_SMG_SHOTS_FIRED,​
STATS_SMG_HIT_PERCENTAGE,​
STATS_SHOTGUN_SHOTS_FIRED,​
STATS_SHOTGUN_HIT_PERCENTAGE,​
STATS_RIFLE_SHOTS_FIRED,​
STATS_RIFLE_HIT_PERCENTAGE,​
STATS_RPG_SHOTS_FIRED,​
STATS_RPG_HIT_PERCENTAGE,​
STATS_THROWN_SHOTS_FIRED,​
STATS_THROWN_HIT_PERCENTAGE,​
STATS_SNIPER_SHOTS_FIRED,​
STATS_SNIPER_HIT_PERCENTAGE,​
STATS_SPECIAL_WEAPON_AMMO_USED,​
STATS_SPECIAL_WEAPON_HIT_PERCENTAGE,​
// Vehicles​
STATS_VEHICLES_HIJACKED,​
STATS_VEHICLES_DESTROYED,​
// Vehicles (Hidden)​
STATS_CARS_DESTROYED,​
STATS_TANKS_DESTROYED,​
STATS_BIKES_DESTROYED,​
STATS_HELICOPTERS_DESTROYED,​
STATS_AIRPLANES_DESTROYED,​
STATS_WATERCRAFT_DESTROYED,​
STATS_POLICE_VEHICLES_DESTROYED,​
STATS_STAG_VEHICLES_DESTROYED,​
STATS_DECKER_VEHICLES_DESTROYED,​
STATS_LUCHADOR_VEHICLES_DESTROYED,​
STATS_MORNINGSTAR_VEHICLES_DESTROYED,​
// Kills​
STATS_ENEMY_GANG_KILLED,​
STATS_DECKERS_KILLED,​
STATS_LUCHADORES_KILLED,​
STATS_MORNINGSTAR_KILLED,​
STATS_MOST_HATED_GANG,​
STATS_LAW_ENFORCEMENT_KILLED,​
STATS_BEAT_COPS_KILLED,​
STATS_SWAT_KILLED,​
STATS_STAG_KILLED,​
STATS_CIVILIANS_KILLED,​
STATS_DECKER_SPECIALISTS_KILLED,​
STATS_LUCHADOR_SPECIALISTS_KILLED,​
STATS_MORNINGSTAR_SPECIALISTS_KILLED,​
STATS_STAG_COMMANDOS_KILLED,​
STATS_PEOPLE_RUN_OVER,​
STATS_BRUTES_KILLED,​
STATS_MASCOTS_KILLED,​
STATS_GRENADE_KILLS,​
STATS_HUMAN_SHIELD_KILLS,​
STATS_UNARMED_KILLS,​
STATS_DILDO_BAT_KILLS,​
STATS_FART_IN_A_JAR_HITS,​
// Kills (Hidden)​
STATS_HEADSHOT_KILLS,​
STATS_NUT_SHOT_TOTAL_NUT_SHOTS,​
STATS_BEATDOWN_KILLS,​
// Distance​
STATS_DISTANCE_BY_CAR,​
STATS_BIG_AIR_LONGEST_JUMP,​
STATS_PARACHUTE_DISTANCE_TRAVELLED,​
STATS_FAVORITE_TRANSPORTATION,​
// Distance (Hidden)​
STATS_DISTANCE_BY_BIKE,​
STATS_DISTANCE_BY_WATERCRAFT,​
STATS_DISTANCE_BY_AIRCRAFT,​
STATS_BIG_AIR_TOTAL_DISTANCE,​
STATS_VEHICLE_SURFING_TOTAL_DISTANCE,​
STATS_WRONG_WAY_TOTAL_DISTANCE,​
// Diversions​
STATS_STREAKING_TOTAL_TIME,​
STATS_VEHICLE_SURFING_LONGEST_TIME,​
STATS_MULTI_KILL_TOTAL_MULTI_KILLS,​
STATS_DIVERSION_CASH_EARNED,​
STATS_DIVERSION_RESPECT_EARNED,​
STATS_WHEELIE_LONGEST_DISTANCE,​
STATS_BARNSTORMS_FOUND,​
STATS_STUNT_JUMPS_FOUND,​
// Diversions (Hidden)​
STATS_DRIFTING_TOTAL_TIME,​
STATS_DRIFTING_TOTAL_DISTANCE,​
STATS_DRIFTING_LONGEST_DISTANCE,​
STATS_NEAR_MISS_TOTAL_GROUND_MISSES,​
STATS_NEAR_MISS_TOTAL_AIR_MISSES,​
STATS_BASE_JUMPING_SUCCESSES,​
STATS_VEHICLE_SURFING_TOTAL_SURFING_TIME,​
STATS_HUMAN_SHIELD_TOTAL_SHIELDS_TAKEN,​
STATS_TWO_WHEELS_TOTAL_DISTANCE,​
STATS_WRONG_WAY_LONGEST_TIME,​
// Hidden (diversion total respect earned)​
STATS_BASE_JUMPING_RESPECT_EARNED,​
STATS_BIG_AIR_RESPECT_EARNED,​
STATS_BRUTE_BEAT_RESPECT_EARNED,​
STATS_BRUTE_RESPECT_EARNED,​
STATS_BURNOUT_RESPECT_EARNED,​
STATS_DRIFTING_RESPECT_EARNED,​
STATS_DRIVER_BAILOUT_RESPECT_EARNED,​
STATS_EXPLOSIVE_RESPECT_EARNED,​
STATS_GANG_KILL_RESPECT_EARNED,​
STATS_GANG_VEHICLE_RESPECT_EARNED,​
STATS_HEAD_SHOT_RESPECT_EARNED,​
STATS_HELI_OR_VTOL_RESPECT_EARNED,​
STATS_HIJACKING_RESPECT_EARNED,​
STATS_HOSTAGE_RESPECT_EARNED,​
STATS_HUMAN_SHIELD_RESPECT_EARNED,​
STATS_LOW_FLYING_RESPECT_EARNED,​
STATS_MULTI_KILL_RESPECT_EARNED,​
STATS_NEAR_MISS_RESPECT_EARNED,​
STATS_NUT_SHOT_RESPECT_EARNED,​
STATS_ONE_HIT_KILL_RESPECT_EARNED,​
STATS_QTE_DIVERSION_RESPECT_EARNED,​
STATS_ROADKILL_RESPECT_EARNED,​
STATS_SPECIALIST_RESPECT_EARNED,​
STATS_SPRINT_ATTACK_RESPECT_EARNED,​
STATS_STAG_RESPECT_EARNED,​
STATS_STAG_VEHICLE_RESPECT_EARNED,​
STATS_STOPPIE_RESPECT_EARNED,​
STATS_STREAKING_RESPECT_EARNED,​
STATS_TANK_RESPECT_EARNED,​
STATS_TAUNTING_RESPECT_EARNED,​
STATS_TESTICULAR_RESPECT_EARNED,​
STATS_THROWING_RESPECT_EARNED,​
STATS_TWO_WHEELS_RESPECT_EARNED,​
STATS_VEHICLE_SURFING_RESPECT_EARNED,​
STATS_WHEELIE_RESPECT_EARNED,​
STATS_WINDSHIELD_CANNON_RESPECT_EARNED,​
STATS_WRONG_WAY_RESPECT_EARNED,​
// Hidden (used for challenge unlocking purposes)​
STATS_WINDSHIELD_CANNON_TOTAL_DISTANCE,​
STATS_WHEELIE_TOTAL_DISTANCE,​
STATS_NEAR_MISS_TOTAL_MISSES,​
STATS_DRIVER_BAILOUT_TOTAL_DISTANCE,​
STATS_STOPPIE_TOTAL_DISTANCE,​

// mission data
int32 num saved missions
for each possible mission(128 of them):
uint64 object handle​
uint8 bit field of flags(unlocked, new mission, completed, completed as client, completed in coop, cutscene played, coop skip executed, unlockables given)​
// help system
for each possible nag(19 of them):
uint32 elapsed time in milliseconds​
for each tutorial(185 of them):
uint8 enum states(locked=0, unlocked, queued, active, completed)​

// homies
for each possible homie(28 of them):
uint32 checksum of name​
uint32 status enum(not gained=0, gained, just called, driving up, following, fallen, recovering, client following, hustlin)​
int16 number of homies
int16 is driveup homie free

// intangibles
int32 total respect
int32 current respect
int32 respect level
int32 rank

// perks
350 uint32 unlockable ids
44 bytes for unlockables bitfield data
44 bytes for available unlockables bitfield data
44 bytes for new unlockables bitfield data
4 floats for notoriety decay bonus factors
5 floats for damage resist factors
uint32 health restore wait bonus milliseconds
float health restore rate modifier
float sprint bonus
bool unlimited sprint
float vehicle repair discount
float respect bonus modifier
float melee damage multiplier
float cheat fall damage multiplier
float firearm accuracy multiplier
bool vehicle customization unlocked
bool character customization unlocked
uint16 reward payments amount

// player possesions
int32 money on hand in pennies

// inventory items(weapons)
int32 number of inventory items
for each inventory item(12 of them: 8 radial, 4 grenade):
uint32 item info crc​
int32 count​
int32 current rounds in magazine​
int32 rounds in reserve​
int32 alt rounds in magazine​
int32 alt rounds in reserve​
bool is dual wielding​
bool infinite ammo​
// weapon upgrades
50 uint32 checksums for upgraded weapon names
50 int32 applied upgrades

// cellphone
uint16 received phonecalls bitfield
int32 number of saved cell phone numbers
64 uint32 checksums of saved cell phone numbers

// cribs
uint16 is crib purchasing enabled
uint16 number of cribs
for each possible owned crib(10 of them):
uint64 object handle of crib​
bool locked​
uint32 current level​
uint32 interior level​
int32 cach in stash in pennies
16 bytes for available crib weapons bitfield

// owned customization items
int32 number of owned customization items
8 bytes for owned customization items bitfield

// store-purchased outfits
74 uint32 checksums for purchased store outfits
uint8 number of store outfits

// player-created outfits
for each created outfit(32 of them):
16 character string for outfit name​
19 8 byte buffers for saved outfit items​
int32 number of items​
uint32 pointer to display name(maybe runtime only and saved as null?)​
uint32 pointer to pointer to customization item variants(runtime only?)​
bool active​
bool purchased​
19 int32 variant ids​

// radio
16 uint32 ids of radio stations disabled
512 int16 custom playlist tracks

// vehicle information
int32 num vehicles
for each garage slot possible(152 of them):
uint32 slot id​
int32 vehicle customization sync packet size​
float retrieval cost​
uint16 vehicle info uid​
uint16 vehicle top level variant id​
uint16 start top level variant id​
uint32 radio station id​
32 byte garage purchased component buffer​
57 byte vehicle customization description buffer​
uint8 garage slot flags(reward vehicle, smoking, on fire, instance data available(script can place a vehicle that doesn't exist into a garage slot, so data like customization would be invalid), player customized, is customizable, start variant set, is new)​
uint32 garage slot uid counter

// world state data
uint32 number of active zone swaps
64 uint32 checksums for zone swap names
237 bytes for unlocked gps shortcuts bitfield
6 bytes for disabled drawbridge bitfield
for each radio tuner event possible(8 of them):
uint32 checksum for event​
uint32 time left​
uint8 number played​
30 bytes for commercial event bools
int32 number of saved triggers
for each possible saved trigger(250 of them):
uint64 object handle​
uint8 flag bitfied(disabled, explored)​

// store data
40 int32 time available
40 uint8 current discount
40 bools fired
40 floats special discounts
40 floats base discounts
9 bytes for ownership flags
9 bytes for explored flags
72 uint64 object handles

// hoods
int32 number of saved hoods
for each possible hood(60 of them):
uint64 object handle for hood​
uint8 flag bitfield(explored, fully explored, use alternate spawning)​

// city takeover regions
int32 num takeovers
for each possible takeover(156 of them):
uint64 object handle​
flag bitfield(player controlled)​
uint8 world state info

uint32 future use version(save games from older versions of the game can use newer save data, they just copy byte for byte data they don't understand, this allows them to save the original version id)

// off disc dlc
int32 number of owned customization items
2048 8 byte buffers for owned customization items
350 uint32 unlockable ids
44 bytes for unlocables data
44 bytes for available unlockable data
44 bytes for new unlockable data

// off disc dlc activities
uint8 bit flags for played escort tutorial, heli tp rescue mission, and heli br rescue mission
for each activity info(64 of them):
uint32 checksum of activity name​
uint32 max level completed​
uint8 completed levels(bitfield since you can play odd levels with coop)​
uint8 completed levels in coop​
uint32 num infos
// off disc homies
for each possible homie(16 of them):
uint32 checksum of name​
uint32 status enum(not gained=0, gained, just called, driving up, following, fallen, recovering, client following, hustlin)​
int16 number of homies

// off disc dlc store-purchased outfits
74 uint32 checksums for purchased store outfits
uint8 number of store outfits

// off disc dlc player-created outfits
for each created outfit(32 of them):
16 character string for outfit name​
19 8 byte buffers for saved outfit items​
int32 number of items​
uint32 pointer to display name(maybe runtime only and saved as null?)​
uint32 pointer to pointer to customization item variants(runtime only?)​
bool active​
bool purchased​
19 int32 variant ids​
// off disc dlc tutorial
int32 number of tutorials
for each possible off disc tutorial(32 of them):
uint32 checksum​
uint8 enum states(locked=0, unlocked, queued, active, completed)​
uint32 padding
for each possible off disc dlc mission(64 of them):
uint64 object handle​
uint8 bit field of flags(unlocked, new mission, completed, completed as client, completed in coop, cutscene played, coop skip executed, unlockables given)​
int32 num saved missions
uint32 padding
64 uint64 object handles for activity trigger explorations
int32 number of vehicles
for each off disc dlc garage slot possible(20 of them):
uint32 slot id​
int32 vehicle customization sync packet size​
float retrieval cost​
uint16 vehicle info uid​
uint16 vehicle top level variant id​
uint16 start top level variant id​
uint32 radio station id​
32 byte garage purchased component buffer​
57 byte vehicle customization description buffer​
uint8 garage slot flags(reward vehicle, smoking, on fire, instance data available(script can place a vehicle that doesn't exist into a garage slot, so data like customization would be invalid), player customized, is customizable, start variant set, is new)​
uint32 padding
// off disc dlc gang customization
4 uint32 character crcs
4 uint32 category crcs
uint8 tag index
uint8 pose index
uint8 voice index
3 uint8 vehicle infos
3616 bytes reserved for future use
 
Wow, that's amazing.

Thanks so much.
 
Thanks, that's definitely helpful. Before i sleep for today, i'll post this question:

For a mission's "uint64 object handle", how do i go about matching that up to a mission name? And the "uint32 mission save description id" at the beginning of the file, i would like to match that up to a string to display as well.
 
I suspect for the save description id you'd need to match that up against the id in the le_strings file?
 
The object handle probably won't be matched easily. It is generated from our editor and it is not related to the name of the object at all. You'll probably just have to build a map of the known ones.
 
Mm. Okay.

What about the "mission save description id" at the beginning? In my save file, it's 0x18 (24). I checked the hud, missions, and static le_strings files, but i don't see any correlation between the number 24 and the string "INSURANCE FRAUD", which is what the save is named. That said, it's also worth noting that the list of save files displayed on the load screen is stored in the savedir.sr3d_pc file, and the format of that one i haven't been able to crack at all. It doesn't read from the saves themselves for the list.

What about hoods? The game uses that term when you use the city takeover upgrade and choose an entire hood to take over automatically. My save has some set as explored, and some with alternate spawning, so what does that status flag mean, like, what's alternate spawning?
 
What about the "mission save description id" at the beginning? In my save file, it's 0x18 (24)
The ID is an index into this hard coded array:

static const uint32 Mission_save_descriptions[] = {
crc_stri("MISSION_NAME_M01"),
crc_stri("MISSION_NAME_M02"),
crc_stri("MISSION_NAME_M03"),
crc_stri("MISSION_NAME_M04"),
crc_stri("MISSION_NAME_M05"),
crc_stri("MISSION_NAME_M06"),
crc_stri("MISSION_NAME_M07"),
crc_stri("MISSION_NAME_M08"),
crc_stri("MISSION_NAME_M09"),
crc_stri("MISSION_NAME_M10"),
crc_stri("MISSION_NAME_M11"),
crc_stri("MISSION_NAME_M12"),
crc_stri("MISSION_NAME_M13"),
crc_stri("MISSION_NAME_M14"),
crc_stri("MISSION_NAME_M15"),
crc_stri("MISSION_NAME_M16"),
crc_stri("MISSION_NAME_M17"),
crc_stri("MISSION_NAME_M18"),
crc_stri("MISSION_NAME_M19"),
crc_stri("MISSION_NAME_M20"),
crc_stri("MISSION_NAME_M21"),
crc_stri("MISSION_NAME_M22"),
crc_stri("MISSION_NAME_M23"),
crc_stri("MISSION_NAME_M24"),
crc_stri("MISSION_NAME_MM_A_01"),
crc_stri("MISSION_NAME_MM_A_02"),
crc_stri("MISSION_NAME_MM_A_03"),
crc_stri("MISSION_NAME_MM_A_04"),
crc_stri("MISSION_NAME_MM_A_05"),
crc_stri("MISSION_NAME_MM_K_01"),
crc_stri("MISSION_NAME_MM_K_02"),
crc_stri("MISSION_NAME_MM_K_03"),
crc_stri("MISSION_NAME_MM_K_04"),
crc_stri("MISSION_NAME_MM_K_05"),
crc_stri("MISSION_NAME_MM_Z_01"),
crc_stri("MISSION_NAME_MM_Z_02"),
crc_stri("MISSION_NAME_MM_Z_03"),
crc_stri("MISSION_NAME_MM_Z_04"),
crc_stri("MISSION_NAME_MM_Z_05"),
crc_stri("MISSION_NAME_MM_P_01"),
crc_stri("MISSION_NAME_MM_P_02"),
crc_stri("MISSION_NAME_MM_P_03"),
crc_stri("MISSION_NAME_MM_P_04"),
crc_stri("MISSION_NAME_MM_P_05"),
crc_stri("MISSION_NAME_MM_P_06"),
crc_stri("MISSION_NAME_MM_P_07"),
crc_stri("MISSION_NAME_SH01"),
crc_stri("MISSION_NAME_SH02"),
crc_stri("MISSION_NAME_SH03"),
crc_stri("MISSION_NAME_SH04"),
};

That said, it's also worth noting that the list of save files displayed on the load screen is stored in the savedir.sr3d_pc file, and the format of that one i haven't been able to crack at all. It doesn't read from the saves themselves for the list.

The format of savedir.sr3d_pc is:

uint32 checksum of slots
int32 num slots used
for each slot (24 of them)
bool slot is in use​
uint8 quick access data[24]​

The quick access data is a packed 186 bits (24 bytes):
7bits: num missions completed
9bits: num takeovers owned
5bits: num hoods owned
17bits: minutes played
2bits: difficulty level
1bit: cheats enabled
1bit: is autosave
7bits: percent complete
8bits: version
7bits: last mission completed save uid
5bits: crib save uid

4bits: month
5bits: day
7bits: year
5bits: hours
6bits: minutes
6bits: seconds
32bits: cash
6bits: respect level
9bits: num takeovers
32bits: current respect

// So adding bits yields only 181. Either I did my math wrong or the last 11 bits are just unused.

What about hoods? The game uses that term when you use the city takeover upgrade and choose an entire hood to take over automatically. My save has some set as explored, and some with alternate spawning, so what does that status flag mean, like, what's alternate spawning?

Each hood can have an alternate list of ambient groups to spawn, which can be toggled on/off from scripting via spawn_override_change_hood_alternate_spawning(). Without digging through all of the gameplay scripts, I believe this was used to change the DownTown hood spawning behavior once STAG showed up and locked down the DT island. This may have been used to vary other hoods at various point during the campaign as well.
 
Back
Top