44 #include <rapidjson/rapidjson.h>
47 #define SAVEGAME_FILE_FORMAT 3
55 std::string GameContext::GetQuicksaveFilename()
60 return "quicksave_" + StringUtil::replaceAll(terrain_name,
".terrn2",
"") + mp +
".sav";
63 void GameContext::LoadScene(std::string
const& filename)
66 m_actor_manager.LoadScene(filename);
69 void GameContext::SaveScene(std::string
const& filename)
71 m_actor_manager.SaveScene(filename);
74 std::string GameContext::ExtractSceneName(std::string
const& filename)
77 rapidjson::Document j_doc;
79 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber() ||
80 !j_doc.HasMember(
"scene_name") || !j_doc[
"scene_name"].IsString())
83 return j_doc[
"scene_name"].GetString();
86 std::string GameContext::ExtractSceneTerrain(std::string
const& filename)
89 rapidjson::Document j_doc;
91 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber() ||
92 !j_doc.HasMember(
"terrain_name") || !j_doc[
"terrain_name"].IsString())
95 return j_doc[
"terrain_name"].GetString();
98 void GameContext::HandleSavegameHotkeys()
205 dialog->
mbc_title =
_LC(
"QuickloadDialog",
"Load game?");
206 dialog->
mbc_text =
_LC(
"QuickloadDialog",
"You will lose all unsaved progress!");
239 bool ActorManager::LoadScene(Ogre::String save_filename)
242 rapidjson::Document j_doc;
244 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber())
247 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: File invalid or missing"));
253 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: File format mismatch"));
258 String terrain_name = j_doc[
"terrain_name"].GetString();
262 if (save_filename ==
"autosave.sav")
267 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: Terrain mismatch"));
270 if (j_doc[
"actors"].GetArray().Size() > 3)
273 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: Too many vehicles"));
278 m_forced_awake = j_doc[
"forced_awake"].GetBool();
285 if (j_doc.HasMember(
"daytime"))
293 auto data = j_doc[
"player_position"].GetArray();
294 Vector3 position = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat());
299 auto actors_changed =
false;
302 std::vector<ActorPtr> actors;
303 std::vector<ActorPtr> x_actors = GetLocalActors();
304 for (rapidjson::Value& j_entry: j_doc[
"actors"].GetArray())
307 String rigdef_filename = j_entry[
"filename"].GetString();
311 if (j_entry.HasMember(
"skin"))
317 if (j_entry.HasMember(
"tuneup_document"))
319 const char* tuneup_str = j_entry[
"tuneup_document"].GetString();
320 size_t tuneup_len = j_entry[
"tuneup_document"].GetStringLength();
321 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream((
void*)tuneup_str, tuneup_len));
322 std::vector<TuneupDefPtr> tuneups = TuneupUtil::ParseTuneups(datastream);
324 working_tuneup = tuneups[0];
327 String section_config = j_entry[
"section_config"].GetString();
330 int index =
static_cast<int>(actors.size());
331 if (index < x_actors.size())
333 if (j_entry[
"filename"].GetString() != x_actors[index]->ar_filename ||
334 (skin !=
nullptr && skin->
dname != x_actors[index]->m_used_skin_entry->dname) ||
335 section_config != x_actors[index]->getSectionConfig())
337 if (x_actors[index] == player_actor)
341 else if (x_actors[index] == prev_player_actor)
346 actors_changed =
true;
350 actor = x_actors[index];
355 if (actor ==
nullptr)
357 bool preloaded = j_entry[
"preloaded_with_terrain"].GetBool();
362 rq->
asr_position.y = preloaded ? j_entry[
"position"][1].GetFloat() : j_entry[
"min_height"].GetFloat();
364 rq->
asr_rotation = Quaternion(Degree(270) - Radian(j_entry[
"rotation"].GetFloat()), Vector3::UNIT_Y);
368 rq->
asr_origin = preloaded ? ActorSpawnRequest::Origin::TERRN_DEF : ActorSpawnRequest::Origin::SAVEGAME;
371 rq->
asr_saved_state = std::shared_ptr<rapidjson::Document>(
new rapidjson::Document());
375 actors_changed =
true;
379 actors.push_back(actor);
381 for (
size_t index = actors.size(); index < x_actors.size(); index++)
383 if (x_actors[index] == player_actor)
387 else if (x_actors[index] == prev_player_actor)
392 actors_changed =
true;
395 const int num_actors =
static_cast<int>(j_doc[
"actors"].Size());
396 for (
int index = 0; index < num_actors; index++)
398 if (actors[index] ==
nullptr)
402 rapidjson::Value& j_entry = j_doc[
"actors"][index];
404 this->RestoreSavedState(actor, j_entry);
407 if (save_filename !=
"autosave.sav")
410 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene loaded"));
416 bool ActorManager::SaveScene(Ogre::String filename)
418 std::vector<ActorPtr> x_actors = GetLocalActors();
422 if (filename ==
"autosave.sav")
424 if (x_actors.size() > 3)
427 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene: Too many vehicles"));
432 rapidjson::Document j_doc;
438 String scene_name =
StringUtil::format(
"%s [%d]", pretty_name.c_str(), x_actors.size());
439 j_doc.AddMember(
"scene_name", rapidjson::StringRef(scene_name.c_str()), j_doc.GetAllocator());
442 j_doc.AddMember(
"terrain_name", rapidjson::StringRef(
App::sim_terrain_name->getStr().c_str()), j_doc.GetAllocator());
447 j_doc.AddMember(
"daytime",
App::GetGameContext()->GetTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator());
451 j_doc.AddMember(
"forced_awake", m_forced_awake, j_doc.GetAllocator());
453 j_doc.AddMember(
"physics_paused",
App::GetGameContext()->GetActorManager()->IsSimulationPaused(), j_doc.GetAllocator());
456 rapidjson::Value j_player_position(rapidjson::kArrayType);
457 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
x, j_doc.GetAllocator());
458 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
y, j_doc.GetAllocator());
459 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
z, j_doc.GetAllocator());
460 j_doc.AddMember(
"player_position", j_player_position, j_doc.GetAllocator());
461 j_doc.AddMember(
"player_rotation",
App::GetGameContext()->GetPlayerCharacter()->getRotation().valueRadians(), j_doc.GetAllocator());
463 std::map<int, int> vector_index_lookup;
466 vector_index_lookup[actor->ar_vector_index] = -1;
467 auto search = std::find_if(x_actors.begin(), x_actors.end(), [actor](
ActorPtr b)
468 { return actor->ar_instance_id == b->ar_instance_id; });
469 if (search != x_actors.end())
471 vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search);
476 rapidjson::Value j_actors(rapidjson::kArrayType);
479 rapidjson::Value j_entry(rapidjson::kObjectType);
484 Ogre::StringUtil::splitFilename(actor->getUsedActorEntry()->resource_bundle_path, bname, bpath);
485 std::string bq_filename =
fmt::format(
"{}:{}", bname, actor->ar_filename);
486 rapidjson::Value j_bq_filename(bq_filename.c_str(), j_doc.GetAllocator());
487 j_entry.AddMember(
"filename", j_bq_filename, j_doc.GetAllocator());
489 rapidjson::Value j_actor_position(rapidjson::kArrayType);
490 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.x, j_doc.GetAllocator());
491 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.y, j_doc.GetAllocator());
492 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.z, j_doc.GetAllocator());
493 j_entry.AddMember(
"position", j_actor_position, j_doc.GetAllocator());
494 j_entry.AddMember(
"rotation", actor->getRotation(), j_doc.GetAllocator());
495 j_entry.AddMember(
"min_height", actor->getMinHeight(), j_doc.GetAllocator());
496 j_entry.AddMember(
"spawn_rotation", actor->m_spawn_rotation, j_doc.GetAllocator());
497 j_entry.AddMember(
"preloaded_with_terrain", actor->isPreloadedWithTerrain(), j_doc.GetAllocator());
498 j_entry.AddMember(
"sim_state",
static_cast<int>(actor->ar_state), j_doc.GetAllocator());
499 j_entry.AddMember(
"physics_paused", actor->ar_physics_paused, j_doc.GetAllocator());
500 j_entry.AddMember(
"player_actor", actor==
App::GetGameContext()->GetPlayerActor(), j_doc.GetAllocator());
501 j_entry.AddMember(
"prev_player_actor", actor==
App::GetGameContext()->GetPrevPlayerActor(), j_doc.GetAllocator());
503 if (actor->m_used_skin_entry)
505 j_entry.AddMember(
"skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator());
508 if (actor->getWorkingTuneupDef())
511 rapidjson::Value j_tuneup_document(rapidjson::kStringType);
513 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream(tuneup_buf.
GetBuffer(), tuneup_buf.
GetCapacity()));
514 TuneupUtil::ExportTuneup(datastream, actor->getWorkingTuneupDef());
515 j_tuneup_document.SetString(datastream->getAsString().c_str(), j_doc.GetAllocator());
516 j_entry.AddMember(
"tuneup_document", j_tuneup_document, j_doc.GetAllocator());
519 j_entry.AddMember(
"section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator());
522 if (actor->ar_engine)
524 j_entry.AddMember(
"engine_gear", actor->ar_engine->GetGear(), j_doc.GetAllocator());
525 j_entry.AddMember(
"engine_rpm", actor->ar_engine->GetEngineRpm(), j_doc.GetAllocator());
526 j_entry.AddMember(
"engine_auto_mode", actor->ar_engine->GetAutoMode(), j_doc.GetAllocator());
527 j_entry.AddMember(
"engine_auto_select", actor->ar_engine->getAutoShift(), j_doc.GetAllocator());
528 j_entry.AddMember(
"engine_is_running", actor->ar_engine->isRunning(), j_doc.GetAllocator());
529 j_entry.AddMember(
"engine_has_contact", actor->ar_engine->hasContact(), j_doc.GetAllocator());
530 j_entry.AddMember(
"engine_wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
531 j_entry.AddMember(
"alb_mode", actor->alb_mode, j_doc.GetAllocator());
532 j_entry.AddMember(
"tc_mode", actor->tc_mode, j_doc.GetAllocator());
533 j_entry.AddMember(
"cc_mode", actor->cc_mode, j_doc.GetAllocator());
534 j_entry.AddMember(
"cc_target_rpm", actor->cc_target_rpm, j_doc.GetAllocator());
535 j_entry.AddMember(
"cc_target_speed", actor->cc_target_speed, j_doc.GetAllocator());
538 j_entry.AddMember(
"hydro_dir_state", actor->ar_hydro_dir_state, j_doc.GetAllocator());
539 j_entry.AddMember(
"hydro_aileron_state", actor->ar_hydro_aileron_state, j_doc.GetAllocator());
540 j_entry.AddMember(
"hydro_rudder_state", actor->ar_hydro_rudder_state, j_doc.GetAllocator());
541 j_entry.AddMember(
"hydro_elevator_state", actor->ar_hydro_elevator_state, j_doc.GetAllocator());
542 j_entry.AddMember(
"parking_brake", actor->ar_parking_brake, j_doc.GetAllocator());
543 j_entry.AddMember(
"trailer_parking_brake", actor->ar_trailer_parking_brake, j_doc.GetAllocator());
544 j_entry.AddMember(
"avg_wheel_speed", actor->ar_avg_wheel_speed, j_doc.GetAllocator());
545 j_entry.AddMember(
"wheel_speed", actor->ar_wheel_speed, j_doc.GetAllocator());
546 j_entry.AddMember(
"wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
548 j_entry.AddMember(
"custom_particles", actor->m_custom_particles_enabled, j_doc.GetAllocator());
551 j_entry.AddMember(
"lights", (
int)actor->getHeadlightsVisible(), j_doc.GetAllocator());
552 j_entry.AddMember(
"blink_type", (
int)actor->getBlinkType(), j_doc.GetAllocator());
555 j_entry.AddMember(
"beacon_light", actor->getBeaconMode(), j_doc.GetAllocator());
556 j_entry.AddMember(
"high_beams_on", actor->getHighBeamsVisible(), j_doc.GetAllocator());
557 j_entry.AddMember(
"fog_lights_on", actor->getFogLightsVisible(), j_doc.GetAllocator());
560 rapidjson::Value j_custom_lights(rapidjson::kArrayType);
563 j_custom_lights.PushBack(actor->getCustomLightVisible(i), j_doc.GetAllocator());
565 j_entry.AddMember(
"custom_lights", j_custom_lights, j_doc.GetAllocator());
568 if (actor->m_buoyance)
570 j_entry.AddMember(
"buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator());
574 rapidjson::Value j_aeroengines(rapidjson::kArrayType);
575 for (
int i = 0; i < actor->ar_num_aeroengines; i++)
577 rapidjson::Value j_aeroengine(rapidjson::kObjectType);
578 j_aeroengine.AddMember(
"rpm", actor->ar_aeroengines[i]->getRPM(), j_doc.GetAllocator());
579 j_aeroengine.AddMember(
"reverse", actor->ar_aeroengines[i]->getReverse(), j_doc.GetAllocator());
580 j_aeroengine.AddMember(
"ignition", actor->ar_aeroengines[i]->getIgnition(), j_doc.GetAllocator());
581 j_aeroengine.AddMember(
"throttle", actor->ar_aeroengines[i]->getThrottle(), j_doc.GetAllocator());
582 j_aeroengines.PushBack(j_aeroengine, j_doc.GetAllocator());
584 j_entry.AddMember(
"aeroengines", j_aeroengines, j_doc.GetAllocator());
587 rapidjson::Value j_screwprops(rapidjson::kArrayType);
588 for (
int i = 0; i < actor->ar_num_screwprops; i++)
590 rapidjson::Value j_screwprop(rapidjson::kObjectType);
591 j_screwprop.AddMember(
"rudder", actor->ar_screwprops[i]->getRudder(), j_doc.GetAllocator());
592 j_screwprop.AddMember(
"throttle", actor->ar_screwprops[i]->getThrottle(), j_doc.GetAllocator());
593 j_screwprops.PushBack(j_screwprop, j_doc.GetAllocator());
595 j_entry.AddMember(
"screwprops", j_screwprops, j_doc.GetAllocator());
598 rapidjson::Value j_rotators(rapidjson::kArrayType);
599 for (
int i = 0; i < actor->ar_num_rotators; i++)
601 j_rotators.PushBack(actor->ar_rotators[i].angle, j_doc.GetAllocator());
603 j_entry.AddMember(
"rotators", j_rotators, j_doc.GetAllocator());
606 rapidjson::Value j_wheels(rapidjson::kArrayType);
607 for (
int i = 0; i < actor->ar_num_wheels; i++)
609 j_wheels.PushBack(actor->ar_wheels[i].wh_is_detached, j_doc.GetAllocator());
611 j_entry.AddMember(
"wheels", j_wheels, j_doc.GetAllocator());
614 rapidjson::Value j_wheel_diffs(rapidjson::kArrayType);
615 for (
int i = 0; i < actor->m_num_wheel_diffs; i++)
617 j_wheel_diffs.PushBack(actor->m_wheel_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
619 j_entry.AddMember(
"wheel_diffs", j_wheel_diffs, j_doc.GetAllocator());
622 rapidjson::Value j_axle_diffs(rapidjson::kArrayType);
623 for (
int i = 0; i < actor->m_num_axle_diffs; i++)
625 j_axle_diffs.PushBack(actor->m_axle_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
627 j_entry.AddMember(
"axle_diffs", j_axle_diffs, j_doc.GetAllocator());
630 if (actor->m_transfer_case)
632 rapidjson::Value j_transfer_case(rapidjson::kObjectType);
633 j_transfer_case.AddMember(
"4WD", actor->m_transfer_case->tr_4wd_mode, j_doc.GetAllocator());
634 j_transfer_case.AddMember(
"GearRatio", actor->m_transfer_case->tr_gear_ratios[0], j_doc.GetAllocator());
635 j_entry.AddMember(
"transfercase", j_transfer_case, j_doc.GetAllocator());
639 rapidjson::Value j_commands(rapidjson::kArrayType);
642 rapidjson::Value j_command(rapidjson::kArrayType);
643 j_command.PushBack(actor->ar_command_key[i].commandValue, j_doc.GetAllocator());
644 j_command.PushBack(actor->ar_command_key[i].triggerInputValue, j_doc.GetAllocator());
646 rapidjson::Value j_command_beams(rapidjson::kArrayType);
647 for (
int j = 0; j < (int)actor->ar_command_key[i].beams.size(); j++)
649 rapidjson::Value j_cmb(rapidjson::kArrayType);
650 auto& beam = actor->ar_command_key[i].beams[j];
651 j_cmb.PushBack(beam.cmb_state->auto_moving_mode, j_doc.GetAllocator());
652 j_cmb.PushBack(beam.cmb_state->pressed_center_mode, j_doc.GetAllocator());
653 j_command_beams.PushBack(j_cmb, j_doc.GetAllocator());
655 j_command.PushBack(j_command_beams, j_doc.GetAllocator());
657 j_commands.PushBack(j_command, j_doc.GetAllocator());
659 j_entry.AddMember(
"commands", j_commands, j_doc.GetAllocator());
662 rapidjson::Value j_hooks(rapidjson::kArrayType);
663 for (
const auto& h : actor->ar_hooks)
665 rapidjson::Value j_hook(rapidjson::kObjectType);
666 int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1;
667 int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1;
668 j_hook.AddMember(
"locked", h.hk_locked, j_doc.GetAllocator());
669 j_hook.AddMember(
"lock_node", lock_node, j_doc.GetAllocator());
670 j_hook.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
671 j_hooks.PushBack(j_hook, j_doc.GetAllocator());
673 j_entry.AddMember(
"hooks", j_hooks, j_doc.GetAllocator());
676 rapidjson::Value j_ropes(rapidjson::kArrayType);
677 for (
const auto& r : actor->ar_ropes)
679 rapidjson::Value j_rope(rapidjson::kObjectType);
680 int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1;
681 int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1;
682 j_rope.AddMember(
"locked", r.rp_locked, j_doc.GetAllocator());
683 j_rope.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
684 j_rope.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
685 j_ropes.PushBack(j_rope, j_doc.GetAllocator());
687 j_entry.AddMember(
"ropes", j_ropes, j_doc.GetAllocator());
690 rapidjson::Value j_ties(rapidjson::kArrayType);
691 for (
const auto& t : actor->ar_ties)
693 rapidjson::Value j_tie(rapidjson::kObjectType);
694 int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1;
695 int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1;
696 j_tie.AddMember(
"tied", t.ti_tied, j_doc.GetAllocator());
697 j_tie.AddMember(
"tying", t.ti_tying, j_doc.GetAllocator());
698 j_tie.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
699 j_tie.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
700 j_ties.PushBack(j_tie, j_doc.GetAllocator());
702 j_entry.AddMember(
"ties", j_ties, j_doc.GetAllocator());
705 rapidjson::Value j_ropables(rapidjson::kArrayType);
706 for (
const auto& r : actor->ar_ropables)
708 rapidjson::Value j_ropable(rapidjson::kObjectType);
709 j_ropable.AddMember(
"attached_ties", r.attached_ties, j_doc.GetAllocator());
710 j_ropable.AddMember(
"attached_ropes", r.attached_ropes, j_doc.GetAllocator());
711 j_ropables.PushBack(j_ropable, j_doc.GetAllocator());
713 j_entry.AddMember(
"ropables", j_ropables, j_doc.GetAllocator());
715 j_entry.AddMember(
"slidenodes_locked", actor->m_slidenodes_locked, j_doc.GetAllocator());
718 rapidjson::Value j_nodes(rapidjson::kArrayType);
719 for (
int i = 0; i < actor->ar_num_nodes; i++)
721 rapidjson::Value j_node(rapidjson::kArrayType);
724 j_node.PushBack(actor->ar_nodes[i].AbsPosition.x, j_doc.GetAllocator());
725 j_node.PushBack(actor->ar_nodes[i].AbsPosition.y, j_doc.GetAllocator());
726 j_node.PushBack(actor->ar_nodes[i].AbsPosition.z, j_doc.GetAllocator());
729 j_node.PushBack(actor->ar_nodes[i].Velocity.x, j_doc.GetAllocator());
730 j_node.PushBack(actor->ar_nodes[i].Velocity.y, j_doc.GetAllocator());
731 j_node.PushBack(actor->ar_nodes[i].Velocity.z, j_doc.GetAllocator());
734 j_node.PushBack(actor->ar_initial_node_positions[i].x, j_doc.GetAllocator());
735 j_node.PushBack(actor->ar_initial_node_positions[i].y, j_doc.GetAllocator());
736 j_node.PushBack(actor->ar_initial_node_positions[i].z, j_doc.GetAllocator());
738 j_nodes.PushBack(j_node, j_doc.GetAllocator());
740 j_entry.AddMember(
"nodes", j_nodes, j_doc.GetAllocator());
743 rapidjson::Value j_beams(rapidjson::kArrayType);
744 for (
int i = 0; i < actor->ar_num_beams; i++)
746 rapidjson::Value j_beam(rapidjson::kArrayType);
748 j_beam.PushBack(actor->ar_beams[i].maxposstress, j_doc.GetAllocator());
749 j_beam.PushBack(actor->ar_beams[i].maxnegstress, j_doc.GetAllocator());
750 j_beam.PushBack(actor->ar_beams[i].minmaxposnegstress, j_doc.GetAllocator());
751 j_beam.PushBack(actor->ar_beams[i].strength, j_doc.GetAllocator());
752 j_beam.PushBack(actor->ar_beams[i].L, j_doc.GetAllocator());
753 j_beam.PushBack(actor->ar_beams[i].bm_broken, j_doc.GetAllocator());
754 j_beam.PushBack(actor->ar_beams[i].bm_disabled, j_doc.GetAllocator());
755 j_beam.PushBack(actor->ar_beams[i].bm_inter_actor, j_doc.GetAllocator());
757 j_beam.PushBack(locked_actor ? vector_index_lookup[locked_actor->
ar_vector_index] : -1, j_doc.GetAllocator());
759 j_beams.PushBack(j_beam, j_doc.GetAllocator());
761 j_entry.AddMember(
"beams", j_beams, j_doc.GetAllocator());
763 j_actors.PushBack(j_entry, j_doc.GetAllocator());
765 j_doc.AddMember(
"actors", j_actors, j_doc.GetAllocator());
772 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene"));
776 if (filename !=
"autosave.sav")
779 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene saved"));
785 void ActorManager::RestoreSavedState(
ActorPtr actor, rapidjson::Value
const& j_entry)
791 if (j_entry[
"player_actor"].GetBool())
795 else if (j_entry[
"prev_player_actor"].GetBool())
802 int gear = j_entry[
"engine_gear"].GetInt();
803 float rpm = j_entry[
"engine_rpm"].GetFloat();
804 int automode = j_entry[
"engine_auto_mode"].GetInt();
805 int autoselect = j_entry[
"engine_auto_select"].GetInt();
806 bool running = j_entry[
"engine_is_running"].GetBool();
807 bool contact = j_entry[
"engine_has_contact"].GetBool();
817 actor->
alb_mode = j_entry[
"alb_mode"].GetBool();
818 actor->
tc_mode = j_entry[
"tc_mode"].GetBool();
819 actor->
cc_mode = j_entry[
"cc_mode"].GetBool();
844 actor->
setBeaconMode(j_entry.HasMember(
"beacon_light") ? j_entry[
"beacon_light"].GetBool() : j_entry[
"pp_beacon_light"].GetBool());
845 actor->
setHighBeamsVisible(j_entry.HasMember(
"high_beams_on") ? j_entry[
"high_beams_on"].GetBool() :
false);
846 actor->
setFogLightsVisible(j_entry.HasMember(
"fog_lights_on") ? j_entry[
"fog_lights_on"].GetBool() :
false);
849 if (j_entry.HasMember(
"custom_lights"))
851 auto flares = j_entry[
"custom_lights"].GetArray();
860 actor->
m_buoyance->sink = j_entry[
"buoyance_sink"].GetBool();
863 auto aeroengines = j_entry[
"aeroengines"].GetArray();
872 auto screwprops = j_entry[
"screwprops"].GetArray();
921 auto commands = j_entry[
"commands"].GetArray();
925 command_key.commandValue = commands[i][0].GetFloat();
926 command_key.triggerInputValue = commands[i][1].GetFloat();
927 auto command_beams = commands[i][2].GetArray();
928 for (
int j = 0; j < (int)command_key.beams.size(); j++)
930 command_key.beams[j].cmb_state->auto_moving_mode = command_beams[j][0].GetInt();
931 command_key.beams[j].cmb_state->pressed_center_mode = command_beams[j][1].GetBool();
935 auto nodes = j_entry[
"nodes"].GetArray();
936 for (rapidjson::SizeType i = 0; i <
nodes.Size(); i++)
938 auto data =
nodes[i].GetArray();
939 actor->
ar_nodes[i].
AbsPosition = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat());
941 actor->
ar_nodes[i].
Velocity = Vector3(data[3].GetFloat(), data[4].GetFloat(), data[5].GetFloat());
945 std::vector<ActorPtr> actors = this->GetLocalActors();
947 auto beams = j_entry[
"beams"].GetArray();
948 for (rapidjson::SizeType i = 0; i < beams.Size(); i++)
950 auto data = beams[i].GetArray();
955 actor->
ar_beams[i].
L = data[4].GetFloat();
959 int locked_actor = data[8].GetInt();
960 if (locked_actor != -1 &&
961 locked_actor < (
int)actors.size() &&
962 actors[locked_actor] !=
nullptr)
968 auto hooks = j_entry[
"hooks"].GetArray();
969 for (
int i = 0; i < actor->
ar_hooks.size(); i++)
971 int lock_node = hooks[i][
"lock_node"].GetInt();
972 int locked_actor = hooks[i][
"locked_actor"].GetInt();
973 if (lock_node != -1 &&
974 locked_actor != -1 &&
975 locked_actor < (
int)actors.size() &&
976 actors[locked_actor] !=
nullptr)
979 actor->
ar_hooks[i].hk_locked_actor = actors[locked_actor];
980 actor->
ar_hooks[i].hk_lock_node = &actors[locked_actor]->ar_nodes[lock_node];
981 if (actor->
ar_hooks[i].hk_beam->bm_inter_actor)
988 auto ropes = j_entry[
"ropes"].GetArray();
989 for (
int i = 0; i < actor->
ar_ropes.size(); i++)
991 int ropable = ropes[i][
"locked_ropable"].GetInt();
992 int locked_actor = ropes[i][
"locked_actor"].GetInt();
994 locked_actor != -1 &&
995 locked_actor < (
int)actors.size() &&
996 actors[locked_actor] !=
nullptr)
998 actor->
ar_ropes[i].rp_locked = ropes[i][
"locked"].GetInt();
999 actor->
ar_ropes[i].rp_locked_actor = actors[locked_actor];
1000 actor->
ar_ropes[i].rp_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1004 auto ties = j_entry[
"ties"].GetArray();
1005 for (
int i = 0; i < actor->
ar_ties.size(); i++)
1007 int ropable = ties[i][
"locked_ropable"].GetInt();
1008 int locked_actor = ties[i][
"locked_actor"].GetInt();
1009 if (ropable != -1 &&
1010 locked_actor != -1 &&
1011 locked_actor < (
int)actors.size() &&
1012 actors[locked_actor] !=
nullptr)
1014 actor->
ar_ties[i].ti_tied = ties[i][
"tied"].GetBool();
1015 actor->
ar_ties[i].ti_tying = ties[i][
"tying"].GetBool();
1016 actor->
ar_ties[i].ti_locked_actor = actors[locked_actor];
1017 actor->
ar_ties[i].ti_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1018 if (actor->
ar_ties[i].ti_beam->bm_inter_actor)
1020 actor->
ar_ties[i].ti_beam->p2 = actor->
ar_ties[i].ti_locked_ropable->node;
1025 auto ropables = j_entry[
"ropables"].GetArray();
1026 for (
int i = 0; i < actor->
ar_ropables.size(); i++)
1028 actor->
ar_ropables[i].attached_ties = ropables[i][
"attached_ties"].GetInt();
1029 actor->
ar_ropables[i].attached_ropes = ropables[i][
"attached_ropes"].GetInt();