diff options
Diffstat (limited to 'src/scenes/save_state_select.c')
| -rw-r--r-- | src/scenes/save_state_select.c | 466 |
1 files changed, 464 insertions, 2 deletions
diff --git a/src/scenes/save_state_select.c b/src/scenes/save_state_select.c index a901864..026362d 100644 --- a/src/scenes/save_state_select.c +++ b/src/scenes/save_state_select.c @@ -1,4 +1,3 @@ -
typedef struct t_save_file_entry
{
bool exists;
@@ -117,6 +116,465 @@ extern world* _active_world; static void load_save_file(s32 index)
{
log_info("Loading save file.");
+
+ save_file_entry entry = save_entries[index];
+ if (!entry.exists) return;
+
+ file_content save_file = platform_read_file_content(entry.path, "rb");
+ if (save_file.file_error) return;
+
+ printf("Loading file: %s.\n", entry.path);
+
+ cJSON *json_object = cJSON_Parse(save_file.content);
+ if (!json_object) {
+ log_info("Failed to load save file.");
+ game_set_active_scene(GAME_STATE_ERROR);
+ return;
+ }
+
+ world* new_world = world_create_new(false);
+ if (!new_world) {
+ log_info("Failed to load save file.");
+ game_set_active_scene(GAME_STATE_ERROR);
+ return;
+ }
+
+ // TODO return on error here in release.
+ #define GET_PROP(_prop, _obj, _str)\
+ cJSON* _prop = cJSON_GetObjectItem(_obj, _str);\
+ if (!_prop) {\
+ log_info("Failed to load save file.");\
+ game_set_active_scene(GAME_STATE_ERROR);\
+ }
+
+ GET_PROP(version, json_object, "version");
+ if (version->valueint != 1) return;
+
+ GET_PROP(simulation_time, json_object, "simulation_time");
+ new_world->simulation_time = simulation_time->valueint;
+
+ GET_PROP(start_year, json_object, "start_year");
+ new_world->start_year = start_year->valueint;
+
+ GET_PROP(money, json_object, "money");
+ new_world->money = money->valuedouble;
+
+ GET_PROP(next_id, json_object, "next_id");
+ new_world->next_id = next_id->valueint;
+
+ GET_PROP(simulation_speed, json_object, "simulation_speed");
+ new_world->simulation_speed = simulation_speed->valueint;
+
+ GET_PROP(days_since_last_random_event, json_object, "days_since_last_random_event");
+ new_world->days_since_last_random_event = days_since_last_random_event->valueint;
+
+ GET_PROP(bank_info, json_object, "bank_info");
+ GET_PROP(loan1, bank_info, "loan1");
+ GET_PROP(loan2, bank_info, "loan2");
+ GET_PROP(loan3, bank_info, "loan3");
+
+ { // Loan 1
+ GET_PROP(amount, loan1, "amount");
+ new_world->bank_info.loan1.amount = amount->valueint;
+
+ GET_PROP(interest, loan1, "interest");
+ new_world->bank_info.loan1.interest = interest->valuedouble;
+
+ GET_PROP(days_left, loan1, "days_left");
+ new_world->bank_info.loan1.days_left = days_left->valueint;
+
+ GET_PROP(monthly_payment, loan1, "monthly_payment");
+ new_world->bank_info.loan1.monthly_payment = monthly_payment->valuedouble;
+
+ GET_PROP(is_active, loan1, "is_active");
+ new_world->bank_info.loan1.is_active = is_active->valueint;
+ }
+
+ { // Loan 2
+ GET_PROP(amount, loan2, "amount");
+ new_world->bank_info.loan2.amount = amount->valueint;
+
+ GET_PROP(interest, loan2, "interest");
+ new_world->bank_info.loan2.interest = interest->valuedouble;
+
+ GET_PROP(days_left, loan2, "days_left");
+ new_world->bank_info.loan2.days_left = days_left->valueint;
+
+ GET_PROP(monthly_payment, loan2, "monthly_payment");
+ new_world->bank_info.loan2.monthly_payment = monthly_payment->valuedouble;
+
+ GET_PROP(is_active, loan2, "is_active");
+ new_world->bank_info.loan2.is_active = is_active->valueint;
+ }
+
+ { // Loan 3
+ GET_PROP(amount, loan3, "amount");
+ new_world->bank_info.loan3.amount = amount->valueint;
+
+ GET_PROP(interest, loan3, "interest");
+ new_world->bank_info.loan3.interest = interest->valuedouble;
+
+ GET_PROP(days_left, loan3, "days_left");
+ new_world->bank_info.loan3.days_left = days_left->valueint;
+
+ GET_PROP(monthly_payment, loan3, "monthly_payment");
+ new_world->bank_info.loan3.monthly_payment = monthly_payment->valuedouble;
+
+ GET_PROP(is_active, loan3, "is_active");
+ new_world->bank_info.loan3.is_active = is_active->valueint;
+ }
+
+ GET_PROP(investments, json_object, "investments");
+ {
+ GET_PROP(marketing, investments, "marketing");
+ new_world->investments.marketing = marketing->valueint;
+
+ GET_PROP(human_resources, investments, "human_resources");
+ new_world->investments.human_resources = human_resources->valueint;
+
+ GET_PROP(training, investments, "training");
+ new_world->investments.training = training->valueint;
+
+ GET_PROP(legal, investments, "legal");
+ new_world->investments.legal = legal->valueint;
+ }
+
+ GET_PROP(log, json_object, "log");
+ {
+ GET_PROP(write_cursor, log, "write_cursor");
+ new_world->log.write_cursor = write_cursor->valueint;
+
+ GET_PROP(has_unread_messages, log, "has_unread_messages");
+ new_world->log.has_unread_messages = has_unread_messages->valueint;
+
+ GET_PROP(events, log, "events");
+ cJSON* event_iter;
+ cJSON_ArrayForEach(event_iter, events)
+ {
+ GET_PROP(type, event_iter, "type");
+ GET_PROP(message, event_iter, "message");
+
+ event new_event;
+ new_event.data = 0;
+ new_event.type = type->valueint;
+ memset(&new_event.job_time, 0, sizeof(scheduled_job_time));
+ string_copyn(new_event.message, message->valuestring, MAX_EVENT_MESSAGE_LENGTH);
+
+ array_push(&new_world->log.events, &new_event);
+ }
+ }
+
+ GET_PROP(locations, json_object, "locations");
+ cJSON* location_iter;
+ cJSON_ArrayForEach(location_iter, locations)
+ {
+ GET_PROP(name, location_iter, "name");
+
+ world_location* existing_loc = world_get_location_by_name(new_world, name->valuestring);
+ if (existing_loc == 0) {
+ printf("LOAD ERROR: location '%s' does not exist.\n", name->valuestring);
+ continue;
+ }
+
+ GET_PROP(is_owned, location_iter, "is_owned");
+ existing_loc->is_owned = is_owned->valueint;
+
+ GET_PROP(purchase_year, location_iter, "purchase_year");
+ existing_loc->purchase_year = purchase_year->valueint;
+
+ GET_PROP(score, location_iter, "score");
+ existing_loc->score = score->valuedouble;
+
+ GET_PROP(employees, location_iter, "employees");
+ cJSON* employee_iter;
+ cJSON_ArrayForEach(employee_iter, employees)
+ {
+ employee* employee1 = mem_alloc(sizeof(employee));
+
+ GET_PROP(id, employee_iter, "id");
+ employee1->id = (u32)id->valuedouble;
+
+ GET_PROP(name, employee_iter, "name");
+ string_copyn(employee1->name, name->valuestring, MAX_EMPLOYEE_NAME_LENGTH);
+
+ GET_PROP(age, employee_iter, "age");
+ employee1->age = age->valueint;
+
+ GET_PROP(experience, employee_iter, "experience");
+ employee1->experience = experience->valuedouble;
+
+ GET_PROP(salary, employee_iter, "salary");
+ employee1->salary = salary->valuedouble;
+
+ GET_PROP(happiness, employee_iter, "happiness");
+ employee1->happiness = happiness->valuedouble;
+
+ GET_PROP(days_below_happiness_treshold, employee_iter, "days_below_happiness_treshold");
+ employee1->days_below_happiness_treshold = happiness->valueint;
+
+ GET_PROP(current_location_id, employee_iter, "current_location_id");
+ employee1->current_location_id = (u32)current_location_id->valuedouble;
+
+ GET_PROP(original_location_id, employee_iter, "original_location_id");
+ employee1->original_location_id = (u32)original_location_id->valuedouble;
+
+ GET_PROP(active_job_id, employee_iter, "active_job_id");
+ employee1->active_job_id = active_job_id->valueint;
+
+ employee1->assigned_truck = 0; // Is set after loading trucks.
+
+ GET_PROP(portrait_hair_type, employee_iter, "portrait_hair_type");
+ employee1->portrait_hair_type = portrait_hair_type->valueint;
+
+ GET_PROP(hair_color, employee_iter, "hair_color");
+ GET_PROP(face_color, employee_iter, "face_color");
+ GET_PROP(body_color, employee_iter, "body_color");
+
+ { // hair_color
+ GET_PROP(r, hair_color, "r");
+ GET_PROP(g, hair_color, "g");
+ GET_PROP(b, hair_color, "b");
+ GET_PROP(a, hair_color, "a");
+ employee1->hair_color = rgba(r->valueint, g->valueint, b->valueint, a->valueint);
+ }
+
+ { // face_color
+ GET_PROP(r, face_color, "r");
+ GET_PROP(g, face_color, "g");
+ GET_PROP(b, face_color, "b");
+ GET_PROP(a, face_color, "a");
+ employee1->face_color = rgba(r->valueint, g->valueint, b->valueint, a->valueint);
+ }
+
+ { // body_color
+ GET_PROP(r, body_color, "r");
+ GET_PROP(g, body_color, "g");
+ GET_PROP(b, body_color, "b");
+ GET_PROP(a, body_color, "a");
+ employee1->body_color = rgba(r->valueint, g->valueint, b->valueint, a->valueint);
+ }
+
+ array_push(&existing_loc->employees, &employee1);
+ }
+
+ GET_PROP(job_offers, location_iter, "job_offers");
+ cJSON* joboffer_iter;
+ cJSON_ArrayForEach(joboffer_iter, job_offers)
+ {
+ job_offer new_offer;
+ new_offer.connections = array_create(sizeof(world_location*));
+
+ GET_PROP(id, joboffer_iter, "id");
+ new_offer.id = id->valueint;
+
+ GET_PROP(expire_date, joboffer_iter, "expire_date");
+ new_offer.expire_date = (s64)expire_date->valuedouble;
+
+ GET_PROP(company_id, joboffer_iter, "company_id");
+ new_offer.company = world_get_company_by_name(new_world, company_id->valuestring);
+
+ GET_PROP(prod, joboffer_iter, "product");
+ new_offer.product = world_get_product_by_name(new_world, prod->valuestring);
+
+ GET_PROP(shipday_count, joboffer_iter, "shipday_count");
+ new_offer.shipday_count = (s32)shipday_count->valueint;
+
+ GET_PROP(reward, joboffer_iter, "reward");
+ new_offer.reward = (u32)reward->valueint;
+
+ GET_PROP(total_distance, joboffer_iter, "total_distance");
+ new_offer.total_distance = (float)total_distance->valuedouble;
+
+ GET_PROP(boat_distance, joboffer_iter, "boat_distance");
+ new_offer.boat_distance = (float)boat_distance->valuedouble;
+
+ GET_PROP(duration_sec_min, joboffer_iter, "duration_sec_min");
+ new_offer.duration_sec_min = (time_t)duration_sec_min->valuedouble;
+
+ GET_PROP(duration_sec_max, joboffer_iter, "duration_sec_max");
+ new_offer.duration_sec_max = (time_t)duration_sec_max->valuedouble;
+
+ GET_PROP(duration_sec_min_excluding_boat, joboffer_iter, "duration_sec_min_excluding_boat");
+ new_offer.duration_sec_min_excluding_boat = (time_t)duration_sec_min_excluding_boat->valuedouble;
+
+ GET_PROP(shipdays, joboffer_iter, "shipdays");
+ cJSON* shipday_iter;
+ int shipday_index = 0;
+ cJSON_ArrayForEach(shipday_iter, shipdays)
+ {
+ new_offer.shipdays[shipday_index] = (weekday)shipday_iter->valueint;
+ shipday_index++;
+ }
+
+ GET_PROP(connections, joboffer_iter, "connections");
+ cJSON* connection_iter;
+ cJSON_ArrayForEach(connection_iter, connections)
+ {
+ u64 id = (u32)connection_iter->valuedouble;
+ world_location* loc = get_world_location_by_id(new_world, id);
+ if (loc) array_push(&new_offer.connections, &loc);
+ }
+
+ array_push(&existing_loc->job_offers, &new_offer);
+ }
+
+ GET_PROP(resumes, location_iter, "resumes");
+ cJSON* resume_iter;
+ cJSON_ArrayForEach(resume_iter, resumes)
+ {
+ resume new_resume;
+ new_resume.animation = animation_create(RESUME_FADEOUT_MS);
+
+ GET_PROP(expire_date, resume_iter, "expire_date");
+ new_resume.expire_date = (s64)expire_date->valuedouble;
+
+ new_resume.hired = false;
+
+ // Employee is not hired yet so just make up a new employee.
+ new_resume.employee = create_employee(new_world, existing_loc);
+
+ array_push(&existing_loc->resumes, &new_resume);
+ }
+
+ GET_PROP(trucks, location_iter, "trucks");
+ cJSON* truck_iter;
+ cJSON_ArrayForEach(truck_iter, trucks)
+ {
+ GET_PROP(type, truck_iter, "type");
+ s32 truck_type = (s32)type->valuedouble;
+
+ truck* new_truck = world_get_truck_by_type(new_world, truck_type);
+
+ GET_PROP(id, truck_iter, "id");
+ new_truck->id = (s32)id->valuedouble;
+
+ GET_PROP(employee_id, truck_iter, "employee_id");
+ u32 emp_id = (u32)employee_id->valuedouble;
+
+ employee* emp = 0;
+ if (emp_id == 0) {
+ new_truck->assigned_employee = 0;
+ }
+ else {
+ emp = get_employee_by_id(existing_loc, emp_id);
+ new_truck->assigned_employee = emp;
+ }
+
+ array_push(&existing_loc->trucks, new_truck);
+
+ if (emp) {
+ emp->assigned_truck = array_at(&existing_loc->trucks, existing_loc->trucks.length-1);
+ }
+ }
+
+ GET_PROP(schedule, location_iter, "schedule");
+ cJSON* job_iter;
+ cJSON_ArrayForEach(job_iter, schedule)
+ {
+ scheduled_job existing_job;
+ existing_job.location = existing_loc;
+
+ GET_PROP(trust, job_iter, "trust");
+ existing_job.trust = (float)trust->valuedouble;
+
+ GET_PROP(offer, job_iter, "offer");
+ { // Load job offer of existing job.
+ job_offer new_offer;
+ new_offer.connections = array_create(sizeof(world_location*));
+
+ GET_PROP(id, offer, "id");
+ new_offer.id = id->valueint;
+
+ GET_PROP(expire_date, offer, "expire_date");
+ new_offer.expire_date = (s64)expire_date->valuedouble;
+
+ GET_PROP(company_id, offer, "company_id");
+ new_offer.company = world_get_company_by_name(new_world, company_id->valuestring);
+
+ GET_PROP(prod, offer, "product");
+ new_offer.product = world_get_product_by_name(new_world, prod->valuestring);
+
+ GET_PROP(shipday_count, offer, "shipday_count");
+ new_offer.shipday_count = (s32)shipday_count->valueint;
+
+ GET_PROP(reward, offer, "reward");
+ new_offer.reward = (u32)reward->valueint;
+
+ GET_PROP(total_distance, offer, "total_distance");
+ new_offer.total_distance = (float)total_distance->valuedouble;
+
+ GET_PROP(boat_distance, offer, "boat_distance");
+ new_offer.boat_distance = (float)boat_distance->valuedouble;
+
+ GET_PROP(duration_sec_min, offer, "duration_sec_min");
+ new_offer.duration_sec_min = (time_t)duration_sec_min->valuedouble;
+
+ GET_PROP(duration_sec_max, offer, "duration_sec_max");
+ new_offer.duration_sec_max = (time_t)duration_sec_max->valuedouble;
+
+ GET_PROP(duration_sec_min_excluding_boat, offer, "duration_sec_min_excluding_boat");
+ new_offer.duration_sec_min_excluding_boat = (time_t)duration_sec_min_excluding_boat->valuedouble;
+
+ GET_PROP(shipdays, offer, "shipdays");
+ cJSON* shipday_iter;
+ int shipday_index = 0;
+ cJSON_ArrayForEach(shipday_iter, shipdays)
+ {
+ new_offer.shipdays[shipday_index] = (weekday)shipday_iter->valueint;
+ shipday_index++;
+ }
+
+ GET_PROP(connections, offer, "connections");
+ cJSON* connection_iter;
+ cJSON_ArrayForEach(connection_iter, connections)
+ {
+ u64 id = (u32)connection_iter->valuedouble;
+ world_location* loc = get_world_location_by_id(new_world, id);
+ if (loc) array_push(&new_offer.connections, &loc);
+ }
+
+ existing_job.offer = new_offer;
+ }
+
+ for (s32 i = 0; i < MAX_SHIPDAYS; i++) {
+ existing_job.timeslots[i] = (scheduled_job_time){-1, -1, 0, 0};
+ }
+
+ GET_PROP(timeslots, job_iter, "timeslots");
+ cJSON* timeslot_iter;
+ int timeslot_index = 0;
+ cJSON_ArrayForEach(timeslot_iter, timeslots)
+ {
+ scheduled_job_time job_time;
+
+ GET_PROP(day, timeslot_iter, "day");
+ job_time.day = (s16)trust->valueint;
+
+ GET_PROP(timeslot, timeslot_iter, "timeslot");
+ job_time.timeslot = (s16)timeslot->valueint;
+
+ GET_PROP(stay_at_destination, timeslot_iter, "stay_at_destination");
+ job_time.stay_at_destination = (bool)stay_at_destination->valueint;
+
+ GET_PROP(employee_id, timeslot_iter, "assignee_id");
+ u32 emp_id = (u32)employee_id->valuedouble;
+
+ job_time.assignee = get_employee_by_id(existing_loc, emp_id);
+
+ existing_job.timeslots[timeslot_index] = job_time;
+ timeslot_index++;
+ }
+
+ array_push(&existing_loc->schedule.jobs, &existing_job);
+ }
+ }
+
+
+ world_map_set_active_world(new_world);
+ enable_insights_for_current_month(new_world);
+ world_update_location_scores(new_world);
+
+ game_set_active_scene(GAME_STATE_WORLD_MAP);
}
static void write_save_file(s32 index)
@@ -139,6 +597,7 @@ static void write_save_file(s32 index) cJSON_AddItemToObject(world, "name", cJSON_CreateString(name_buf));
}
+ cJSON_AddItemToObject(world, "version", cJSON_CreateNumber(1));
cJSON_AddItemToObject(world, "save_index", cJSON_CreateNumber(index));
cJSON_AddItemToObject(world, "simulation_time", cJSON_CreateNumber(_active_world->simulation_time));
@@ -198,7 +657,7 @@ static void write_save_file(s32 index) event* e = array_at(&_active_world->log.events, i);
cJSON *event = cJSON_CreateObject();
cJSON_AddItemToObject(event, "type", cJSON_CreateNumber(e->type));
- cJSON_AddItemToObject(event, "message", cJSON_CreateString (e->message));
+ cJSON_AddItemToObject(event, "message", cJSON_CreateString(e->message));
cJSON_AddItemToArray(entries, event);
}
@@ -215,6 +674,7 @@ static void write_save_file(s32 index) if (!location->is_owned) continue;
cJSON *loc = cJSON_CreateObject();
+ cJSON_AddItemToObject(loc, "name", cJSON_CreateString(location->name));
cJSON_AddItemToObject(loc, "is_owned", cJSON_CreateNumber(location->is_owned));
cJSON_AddItemToObject(loc, "purchase_year", cJSON_CreateNumber(location->purchase_year));
cJSON_AddItemToObject(loc, "score", cJSON_CreateNumber(location->score));
@@ -274,6 +734,7 @@ static void write_save_file(s32 index) cJSON *offer = cJSON_CreateObject();
cJSON_AddItemToObject(offer, "id", cJSON_CreateNumber(o->id));
+ cJSON_AddItemToObject(offer, "reward", cJSON_CreateNumber(o->reward));
cJSON_AddItemToObject(offer, "expire_date", cJSON_CreateNumber(o->expire_date));
cJSON_AddItemToObject(offer, "company_id", cJSON_CreateString(o->company->name));
cJSON_AddItemToObject(offer, "product", cJSON_CreateString(o->product->name));
@@ -368,6 +829,7 @@ static void write_save_file(s32 index) cJSON *offer = cJSON_CreateObject();
cJSON_AddItemToObject(offer, "id", cJSON_CreateNumber(scheduled_job->offer.id));
cJSON_AddItemToObject(offer, "expire_date", cJSON_CreateNumber(scheduled_job->offer.expire_date));
+ cJSON_AddItemToObject(offer, "reward", cJSON_CreateNumber(scheduled_job->offer.reward));
cJSON_AddItemToObject(offer, "company_id", cJSON_CreateString(scheduled_job->offer.company->name));
cJSON_AddItemToObject(offer, "product", cJSON_CreateString(scheduled_job->offer.product->name));
cJSON_AddItemToObject(offer, "shipday_count", cJSON_CreateNumber(scheduled_job->offer.shipday_count));
|
