45 #include <rapidjson/rapidjson.h>
48 #define SAVEGAME_FILE_FORMAT 3
56 std::string GameContext::GetQuicksaveFilename()
61 return "quicksave_" + StringUtil::replaceAll(terrain_name,
".terrn2",
"") + mp +
".sav";
64 void GameContext::LoadScene(std::string
const& filename)
67 m_actor_manager.LoadScene(filename);
70 void GameContext::SaveScene(std::string
const& filename)
72 m_actor_manager.SaveScene(filename);
75 std::string GameContext::ExtractSceneName(std::string
const& filename)
78 rapidjson::Document j_doc;
80 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber() ||
81 !j_doc.HasMember(
"scene_name") || !j_doc[
"scene_name"].IsString())
84 return j_doc[
"scene_name"].GetString();
87 std::string GameContext::ExtractSceneTerrain(std::string
const& filename)
90 rapidjson::Document j_doc;
92 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber() ||
93 !j_doc.HasMember(
"terrain_name") || !j_doc[
"terrain_name"].IsString())
96 return j_doc[
"terrain_name"].GetString();
99 void GameContext::HandleSavegameHotkeys()
206 dialog->
mbc_title =
_LC(
"QuickloadDialog",
"Load game?");
207 dialog->
mbc_text =
_LC(
"QuickloadDialog",
"You will lose all unsaved progress!");
240 bool ActorManager::LoadScene(Ogre::String save_filename)
243 rapidjson::Document j_doc;
245 !j_doc.IsObject() || !j_doc.HasMember(
"format_version") || !j_doc[
"format_version"].IsNumber())
248 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: File invalid or missing"));
254 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: File format mismatch"));
259 String terrain_name = j_doc[
"terrain_name"].GetString();
263 if (save_filename ==
"autosave.sav")
268 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: Terrain mismatch"));
271 if (j_doc[
"actors"].GetArray().Size() > 3)
274 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while loading scene: Too many vehicles"));
279 m_forced_awake = j_doc[
"forced_awake"].GetBool();
286 if (j_doc.HasMember(
"daytime"))
294 auto data = j_doc[
"player_position"].GetArray();
295 Vector3 position = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat());
300 auto actors_changed =
false;
303 std::vector<ActorPtr> actors;
304 std::vector<ActorPtr> x_actors = GetLocalActors();
305 for (rapidjson::Value& j_entry: j_doc[
"actors"].GetArray())
308 String rigdef_filename_maybe_bundle_qualified = j_entry[
"filename"].GetString();
309 std::string filename;
310 std::string bundlename;
315 if (j_entry.HasMember(
"skin"))
321 if (j_entry.HasMember(
"tuneup_document"))
323 const char* tuneup_str = j_entry[
"tuneup_document"].GetString();
324 size_t tuneup_len = j_entry[
"tuneup_document"].GetStringLength();
325 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream((
void*)tuneup_str, tuneup_len));
326 std::vector<TuneupDefPtr> tuneups = TuneupUtil::ParseTuneups(datastream);
328 working_tuneup = tuneups[0];
331 String section_config = j_entry[
"section_config"].GetString();
334 int index =
static_cast<int>(actors.size());
335 if (index < x_actors.size())
337 if (filename != x_actors[index]->ar_filename ||
338 (skin !=
nullptr && skin->
dname != x_actors[index]->m_used_skin_entry->dname) ||
339 section_config != x_actors[index]->getSectionConfig())
341 if (x_actors[index] == player_actor)
345 else if (x_actors[index] == prev_player_actor)
350 actors_changed =
true;
354 actor = x_actors[index];
360 if (actor ==
nullptr && !j_entry[
"preloaded_with_terrain"].GetBool())
363 rq->
asr_filename = rigdef_filename_maybe_bundle_qualified;
367 rq->
asr_rotation = Quaternion(Degree(270) - Radian(j_entry[
"rotation"].GetFloat()), Vector3::UNIT_Y);
371 rq->
asr_origin = ActorSpawnRequest::Origin::SAVEGAME;
373 rq->
asr_saved_state = std::shared_ptr<rapidjson::Document>(
new rapidjson::Document());
377 actors_changed =
true;
381 actors.push_back(actor);
383 for (
size_t index = actors.size(); index < x_actors.size(); index++)
385 if (x_actors[index] == player_actor)
389 else if (x_actors[index] == prev_player_actor)
394 actors_changed =
true;
397 const int num_actors =
static_cast<int>(j_doc[
"actors"].Size());
398 for (
int index = 0; index < num_actors; index++)
400 if (actors[index] ==
nullptr)
404 rapidjson::Value& j_entry = j_doc[
"actors"][index];
406 this->RestoreSavedState(actor, j_entry);
409 if (save_filename !=
"autosave.sav")
412 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene loaded"));
418 bool ActorManager::SaveScene(Ogre::String filename)
420 std::vector<ActorPtr> x_actors = GetLocalActors();
424 if (filename ==
"autosave.sav")
426 if (x_actors.size() > 3)
429 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene: Too many vehicles"));
434 rapidjson::Document j_doc;
440 String scene_name =
StringUtil::format(
"%s [%d]", pretty_name.c_str(), x_actors.size());
441 j_doc.AddMember(
"scene_name", rapidjson::StringRef(scene_name.c_str()), j_doc.GetAllocator());
444 j_doc.AddMember(
"terrain_name", rapidjson::StringRef(
App::sim_terrain_name->getStr().c_str()), j_doc.GetAllocator());
449 j_doc.AddMember(
"daytime",
App::GetGameContext()->GetTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator());
453 j_doc.AddMember(
"forced_awake", m_forced_awake, j_doc.GetAllocator());
455 j_doc.AddMember(
"physics_paused",
App::GetGameContext()->GetActorManager()->IsSimulationPaused(), j_doc.GetAllocator());
458 rapidjson::Value j_player_position(rapidjson::kArrayType);
459 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
x, j_doc.GetAllocator());
460 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
y, j_doc.GetAllocator());
461 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
z, j_doc.GetAllocator());
462 j_doc.AddMember(
"player_position", j_player_position, j_doc.GetAllocator());
463 j_doc.AddMember(
"player_rotation",
App::GetGameContext()->GetPlayerCharacter()->getRotation().valueRadians(), j_doc.GetAllocator());
465 std::map<int, int> vector_index_lookup;
468 vector_index_lookup[actor->ar_vector_index] = -1;
469 auto search = std::find_if(x_actors.begin(), x_actors.end(), [actor](
ActorPtr b)
470 { return actor->ar_instance_id == b->ar_instance_id; });
471 if (search != x_actors.end())
473 vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search);
478 rapidjson::Value j_actors(rapidjson::kArrayType);
481 rapidjson::Value j_entry(rapidjson::kObjectType);
486 Ogre::StringUtil::splitFilename(actor->getUsedActorEntry()->resource_bundle_path, bname, bpath);
487 std::string bq_filename =
fmt::format(
"{}:{}", bname, actor->ar_filename);
488 rapidjson::Value j_bq_filename(bq_filename.c_str(), j_doc.GetAllocator());
489 j_entry.AddMember(
"filename", j_bq_filename, j_doc.GetAllocator());
491 rapidjson::Value j_actor_position(rapidjson::kArrayType);
492 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.x, j_doc.GetAllocator());
493 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.y, j_doc.GetAllocator());
494 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.z, j_doc.GetAllocator());
495 j_entry.AddMember(
"position", j_actor_position, j_doc.GetAllocator());
496 j_entry.AddMember(
"rotation", actor->getRotation(), j_doc.GetAllocator());
497 j_entry.AddMember(
"min_height", actor->getMinHeight(), j_doc.GetAllocator());
498 j_entry.AddMember(
"spawn_rotation", actor->m_spawn_rotation, j_doc.GetAllocator());
499 j_entry.AddMember(
"preloaded_with_terrain", actor->isPreloadedWithTerrain(), j_doc.GetAllocator());
500 j_entry.AddMember(
"sim_state",
static_cast<int>(actor->ar_state), j_doc.GetAllocator());
501 j_entry.AddMember(
"physics_paused", actor->ar_physics_paused, j_doc.GetAllocator());
502 j_entry.AddMember(
"player_actor", actor==
App::GetGameContext()->GetPlayerActor(), j_doc.GetAllocator());
503 j_entry.AddMember(
"prev_player_actor", actor==
App::GetGameContext()->GetPrevPlayerActor(), j_doc.GetAllocator());
505 if (actor->m_used_skin_entry)
507 j_entry.AddMember(
"skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator());
510 if (actor->getWorkingTuneupDef())
513 rapidjson::Value j_tuneup_document(rapidjson::kStringType);
515 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream(tuneup_buf.
GetBuffer(), tuneup_buf.
GetCapacity()));
516 TuneupUtil::ExportTuneup(datastream, actor->getWorkingTuneupDef());
517 j_tuneup_document.SetString(datastream->getAsString().c_str(), j_doc.GetAllocator());
518 j_entry.AddMember(
"tuneup_document", j_tuneup_document, j_doc.GetAllocator());
521 j_entry.AddMember(
"section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator());
524 if (actor->ar_engine)
526 j_entry.AddMember(
"engine_gear", actor->ar_engine->getGear(), j_doc.GetAllocator());
527 j_entry.AddMember(
"engine_rpm", actor->ar_engine->getRPM(), j_doc.GetAllocator());
528 j_entry.AddMember(
"engine_auto_mode",
static_cast<int>(actor->ar_engine->getAutoMode()), j_doc.GetAllocator());
529 j_entry.AddMember(
"engine_auto_select", actor->ar_engine->getAutoShift(), j_doc.GetAllocator());
530 j_entry.AddMember(
"engine_is_running", actor->ar_engine->isRunning(), j_doc.GetAllocator());
531 j_entry.AddMember(
"engine_has_contact", actor->ar_engine->hasContact(), j_doc.GetAllocator());
532 j_entry.AddMember(
"engine_wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
533 j_entry.AddMember(
"alb_mode", actor->alb_mode, j_doc.GetAllocator());
534 j_entry.AddMember(
"tc_mode", actor->tc_mode, j_doc.GetAllocator());
535 j_entry.AddMember(
"cc_mode", actor->cc_mode, j_doc.GetAllocator());
536 j_entry.AddMember(
"cc_target_rpm", actor->cc_target_rpm, j_doc.GetAllocator());
537 j_entry.AddMember(
"cc_target_speed", actor->cc_target_speed, j_doc.GetAllocator());
540 j_entry.AddMember(
"hydro_dir_state", actor->ar_hydro_dir_state, j_doc.GetAllocator());
541 j_entry.AddMember(
"hydro_aileron_state", actor->ar_hydro_aileron_state, j_doc.GetAllocator());
542 j_entry.AddMember(
"hydro_rudder_state", actor->ar_hydro_rudder_state, j_doc.GetAllocator());
543 j_entry.AddMember(
"hydro_elevator_state", actor->ar_hydro_elevator_state, j_doc.GetAllocator());
544 j_entry.AddMember(
"parking_brake", actor->ar_parking_brake, j_doc.GetAllocator());
545 j_entry.AddMember(
"trailer_parking_brake", actor->ar_trailer_parking_brake, j_doc.GetAllocator());
546 j_entry.AddMember(
"avg_wheel_speed", actor->ar_avg_wheel_speed, j_doc.GetAllocator());
547 j_entry.AddMember(
"wheel_speed", actor->ar_wheel_speed, j_doc.GetAllocator());
548 j_entry.AddMember(
"wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
550 j_entry.AddMember(
"custom_particles", actor->ar_cparticles_active, j_doc.GetAllocator());
553 j_entry.AddMember(
"lights", (
int)actor->getHeadlightsVisible(), j_doc.GetAllocator());
554 j_entry.AddMember(
"blink_type", (
int)actor->getBlinkType(), j_doc.GetAllocator());
557 j_entry.AddMember(
"beacon_light", actor->getBeaconMode(), j_doc.GetAllocator());
558 j_entry.AddMember(
"high_beams_on", actor->getHighBeamsVisible(), j_doc.GetAllocator());
559 j_entry.AddMember(
"fog_lights_on", actor->getFogLightsVisible(), j_doc.GetAllocator());
562 rapidjson::Value j_custom_lights(rapidjson::kArrayType);
565 j_custom_lights.PushBack(actor->getCustomLightVisible(i), j_doc.GetAllocator());
567 j_entry.AddMember(
"custom_lights", j_custom_lights, j_doc.GetAllocator());
570 if (actor->m_buoyance)
572 j_entry.AddMember(
"buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator());
576 rapidjson::Value j_aeroengines(rapidjson::kArrayType);
577 for (
int i = 0; i < actor->ar_num_aeroengines; i++)
579 rapidjson::Value j_aeroengine(rapidjson::kObjectType);
580 j_aeroengine.AddMember(
"rpm", actor->ar_aeroengines[i]->getRPM(), j_doc.GetAllocator());
581 j_aeroengine.AddMember(
"reverse", actor->ar_aeroengines[i]->getReverse(), j_doc.GetAllocator());
582 j_aeroengine.AddMember(
"ignition", actor->ar_aeroengines[i]->getIgnition(), j_doc.GetAllocator());
583 j_aeroengine.AddMember(
"throttle", actor->ar_aeroengines[i]->getThrottle(), j_doc.GetAllocator());
584 j_aeroengines.PushBack(j_aeroengine, j_doc.GetAllocator());
586 j_entry.AddMember(
"aeroengines", j_aeroengines, j_doc.GetAllocator());
589 rapidjson::Value j_screwprops(rapidjson::kArrayType);
590 for (
int i = 0; i < actor->ar_num_screwprops; i++)
592 rapidjson::Value j_screwprop(rapidjson::kObjectType);
593 j_screwprop.AddMember(
"rudder", actor->ar_screwprops[i]->getRudder(), j_doc.GetAllocator());
594 j_screwprop.AddMember(
"throttle", actor->ar_screwprops[i]->getThrottle(), j_doc.GetAllocator());
595 j_screwprops.PushBack(j_screwprop, j_doc.GetAllocator());
597 j_entry.AddMember(
"screwprops", j_screwprops, j_doc.GetAllocator());
600 rapidjson::Value j_rotators(rapidjson::kArrayType);
601 for (
int i = 0; i < actor->ar_num_rotators; i++)
603 j_rotators.PushBack(actor->ar_rotators[i].angle, j_doc.GetAllocator());
605 j_entry.AddMember(
"rotators", j_rotators, j_doc.GetAllocator());
608 rapidjson::Value j_wheels(rapidjson::kArrayType);
609 for (
int i = 0; i < actor->ar_num_wheels; i++)
611 j_wheels.PushBack(actor->ar_wheels[i].wh_is_detached, j_doc.GetAllocator());
613 j_entry.AddMember(
"wheels", j_wheels, j_doc.GetAllocator());
616 rapidjson::Value j_wheel_diffs(rapidjson::kArrayType);
617 for (
int i = 0; i < actor->m_num_wheel_diffs; i++)
619 j_wheel_diffs.PushBack(actor->m_wheel_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
621 j_entry.AddMember(
"wheel_diffs", j_wheel_diffs, j_doc.GetAllocator());
624 rapidjson::Value j_axle_diffs(rapidjson::kArrayType);
625 for (
int i = 0; i < actor->m_num_axle_diffs; i++)
627 j_axle_diffs.PushBack(actor->m_axle_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
629 j_entry.AddMember(
"axle_diffs", j_axle_diffs, j_doc.GetAllocator());
632 if (actor->m_transfer_case)
634 rapidjson::Value j_transfer_case(rapidjson::kObjectType);
635 j_transfer_case.AddMember(
"4WD", actor->m_transfer_case->tr_4wd_mode, j_doc.GetAllocator());
636 j_transfer_case.AddMember(
"GearRatio", actor->m_transfer_case->tr_gear_ratios[0], j_doc.GetAllocator());
637 j_entry.AddMember(
"transfercase", j_transfer_case, j_doc.GetAllocator());
641 rapidjson::Value j_commands(rapidjson::kArrayType);
644 rapidjson::Value j_command(rapidjson::kArrayType);
645 j_command.PushBack(actor->ar_command_key[i].commandValue, j_doc.GetAllocator());
646 j_command.PushBack(actor->ar_command_key[i].triggerInputValue, j_doc.GetAllocator());
648 rapidjson::Value j_command_beams(rapidjson::kArrayType);
649 for (
int j = 0; j < (int)actor->ar_command_key[i].beams.size(); j++)
651 rapidjson::Value j_cmb(rapidjson::kArrayType);
652 auto& beam = actor->ar_command_key[i].beams[j];
653 j_cmb.PushBack(beam.cmb_state->auto_moving_mode, j_doc.GetAllocator());
654 j_cmb.PushBack(beam.cmb_state->pressed_center_mode, j_doc.GetAllocator());
655 j_command_beams.PushBack(j_cmb, j_doc.GetAllocator());
657 j_command.PushBack(j_command_beams, j_doc.GetAllocator());
659 j_commands.PushBack(j_command, j_doc.GetAllocator());
661 j_entry.AddMember(
"commands", j_commands, j_doc.GetAllocator());
664 rapidjson::Value j_hooks(rapidjson::kArrayType);
665 for (
const auto& h : actor->ar_hooks)
667 rapidjson::Value j_hook(rapidjson::kObjectType);
668 int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1;
669 int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1;
670 j_hook.AddMember(
"locked", h.hk_locked, j_doc.GetAllocator());
671 j_hook.AddMember(
"lock_node", lock_node, j_doc.GetAllocator());
672 j_hook.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
673 j_hooks.PushBack(j_hook, j_doc.GetAllocator());
675 j_entry.AddMember(
"hooks", j_hooks, j_doc.GetAllocator());
678 rapidjson::Value j_ropes(rapidjson::kArrayType);
679 for (
const auto& r : actor->ar_ropes)
681 rapidjson::Value j_rope(rapidjson::kObjectType);
682 int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1;
683 int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1;
684 j_rope.AddMember(
"locked", r.rp_locked, j_doc.GetAllocator());
685 j_rope.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
686 j_rope.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
687 j_ropes.PushBack(j_rope, j_doc.GetAllocator());
689 j_entry.AddMember(
"ropes", j_ropes, j_doc.GetAllocator());
692 rapidjson::Value j_ties(rapidjson::kArrayType);
693 for (
const auto& t : actor->ar_ties)
695 rapidjson::Value j_tie(rapidjson::kObjectType);
696 int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1;
697 int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1;
698 j_tie.AddMember(
"tied", t.ti_tied, j_doc.GetAllocator());
699 j_tie.AddMember(
"tying", t.ti_tying, j_doc.GetAllocator());
700 j_tie.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
701 j_tie.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
702 j_ties.PushBack(j_tie, j_doc.GetAllocator());
704 j_entry.AddMember(
"ties", j_ties, j_doc.GetAllocator());
707 rapidjson::Value j_ropables(rapidjson::kArrayType);
708 for (
const auto& r : actor->ar_ropables)
710 rapidjson::Value j_ropable(rapidjson::kObjectType);
711 j_ropable.AddMember(
"attached_ties", r.attached_ties, j_doc.GetAllocator());
712 j_ropable.AddMember(
"attached_ropes", r.attached_ropes, j_doc.GetAllocator());
713 j_ropables.PushBack(j_ropable, j_doc.GetAllocator());
715 j_entry.AddMember(
"ropables", j_ropables, j_doc.GetAllocator());
717 j_entry.AddMember(
"slidenodes_locked", actor->m_slidenodes_locked, j_doc.GetAllocator());
720 rapidjson::Value j_nodes(rapidjson::kArrayType);
721 for (
int i = 0; i < actor->ar_num_nodes; i++)
723 rapidjson::Value j_node(rapidjson::kArrayType);
726 j_node.PushBack(actor->ar_nodes[i].AbsPosition.x, j_doc.GetAllocator());
727 j_node.PushBack(actor->ar_nodes[i].AbsPosition.y, j_doc.GetAllocator());
728 j_node.PushBack(actor->ar_nodes[i].AbsPosition.z, j_doc.GetAllocator());
731 j_node.PushBack(actor->ar_nodes[i].Velocity.x, j_doc.GetAllocator());
732 j_node.PushBack(actor->ar_nodes[i].Velocity.y, j_doc.GetAllocator());
733 j_node.PushBack(actor->ar_nodes[i].Velocity.z, j_doc.GetAllocator());
736 j_node.PushBack(actor->ar_initial_node_positions[i].x, j_doc.GetAllocator());
737 j_node.PushBack(actor->ar_initial_node_positions[i].y, j_doc.GetAllocator());
738 j_node.PushBack(actor->ar_initial_node_positions[i].z, j_doc.GetAllocator());
740 j_nodes.PushBack(j_node, j_doc.GetAllocator());
742 j_entry.AddMember(
"nodes", j_nodes, j_doc.GetAllocator());
745 rapidjson::Value j_beams(rapidjson::kArrayType);
746 for (
int i = 0; i < actor->ar_num_beams; i++)
748 rapidjson::Value j_beam(rapidjson::kArrayType);
750 j_beam.PushBack(actor->ar_beams[i].maxposstress, j_doc.GetAllocator());
751 j_beam.PushBack(actor->ar_beams[i].maxnegstress, j_doc.GetAllocator());
752 j_beam.PushBack(actor->ar_beams[i].minmaxposnegstress, j_doc.GetAllocator());
753 j_beam.PushBack(actor->ar_beams[i].strength, j_doc.GetAllocator());
754 j_beam.PushBack(actor->ar_beams[i].L, j_doc.GetAllocator());
755 j_beam.PushBack(actor->ar_beams[i].bm_broken, j_doc.GetAllocator());
756 j_beam.PushBack(actor->ar_beams[i].bm_disabled, j_doc.GetAllocator());
757 j_beam.PushBack(actor->ar_beams[i].bm_inter_actor, j_doc.GetAllocator());
759 j_beam.PushBack(locked_actor ? vector_index_lookup[locked_actor->
ar_vector_index] : -1, j_doc.GetAllocator());
761 j_beams.PushBack(j_beam, j_doc.GetAllocator());
763 j_entry.AddMember(
"beams", j_beams, j_doc.GetAllocator());
765 j_actors.PushBack(j_entry, j_doc.GetAllocator());
767 j_doc.AddMember(
"actors", j_actors, j_doc.GetAllocator());
774 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene"));
778 if (filename !=
"autosave.sav")
781 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene saved"));
787 void ActorManager::RestoreSavedState(
ActorPtr actor, rapidjson::Value
const& j_entry)
793 if (j_entry[
"player_actor"].GetBool())
797 else if (j_entry[
"prev_player_actor"].GetBool())
804 int gear = j_entry[
"engine_gear"].GetInt();
805 float rpm = j_entry[
"engine_rpm"].GetFloat();
806 int automode = j_entry[
"engine_auto_mode"].GetInt();
807 int autoselect = j_entry[
"engine_auto_select"].GetInt();
808 bool running = j_entry[
"engine_is_running"].GetBool();
809 bool contact = j_entry[
"engine_has_contact"].GetBool();
819 actor->
alb_mode = j_entry[
"alb_mode"].GetBool();
820 actor->
tc_mode = j_entry[
"tc_mode"].GetBool();
821 actor->
cc_mode = j_entry[
"cc_mode"].GetBool();
846 actor->
setBeaconMode(j_entry.HasMember(
"beacon_light") ? j_entry[
"beacon_light"].GetBool() : j_entry[
"pp_beacon_light"].GetBool());
847 actor->
setHighBeamsVisible(j_entry.HasMember(
"high_beams_on") ? j_entry[
"high_beams_on"].GetBool() :
false);
848 actor->
setFogLightsVisible(j_entry.HasMember(
"fog_lights_on") ? j_entry[
"fog_lights_on"].GetBool() :
false);
851 if (j_entry.HasMember(
"custom_lights"))
853 auto flares = j_entry[
"custom_lights"].GetArray();
862 actor->
m_buoyance->sink = j_entry[
"buoyance_sink"].GetBool();
865 auto aeroengines = j_entry[
"aeroengines"].GetArray();
874 auto screwprops = j_entry[
"screwprops"].GetArray();
923 auto commands = j_entry[
"commands"].GetArray();
927 command_key.commandValue = commands[i][0].GetFloat();
928 command_key.triggerInputValue = commands[i][1].GetFloat();
929 auto command_beams = commands[i][2].GetArray();
930 for (
int j = 0; j < (int)command_key.beams.size(); j++)
932 command_key.beams[j].cmb_state->auto_moving_mode = command_beams[j][0].GetInt();
933 command_key.beams[j].cmb_state->pressed_center_mode = command_beams[j][1].GetBool();
937 auto nodes = j_entry[
"nodes"].GetArray();
938 for (rapidjson::SizeType i = 0; i <
nodes.Size(); i++)
940 auto data =
nodes[i].GetArray();
941 actor->
ar_nodes[i].
AbsPosition = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat());
943 actor->
ar_nodes[i].
Velocity = Vector3(data[3].GetFloat(), data[4].GetFloat(), data[5].GetFloat());
947 std::vector<ActorPtr> actors = this->GetLocalActors();
949 auto beams = j_entry[
"beams"].GetArray();
950 for (rapidjson::SizeType i = 0; i < beams.Size(); i++)
952 auto data = beams[i].GetArray();
957 actor->
ar_beams[i].
L = data[4].GetFloat();
961 int locked_actor = data[8].GetInt();
962 if (locked_actor != -1 &&
963 locked_actor < (
int)actors.size() &&
964 actors[locked_actor] !=
nullptr)
970 auto hooks = j_entry[
"hooks"].GetArray();
971 for (
int i = 0; i < actor->
ar_hooks.size(); i++)
973 int lock_node = hooks[i][
"lock_node"].GetInt();
974 int locked_actor = hooks[i][
"locked_actor"].GetInt();
975 if (lock_node != -1 &&
976 locked_actor != -1 &&
977 locked_actor < (
int)actors.size() &&
978 actors[locked_actor] !=
nullptr)
981 actor->
ar_hooks[i].hk_locked_actor = actors[locked_actor];
982 actor->
ar_hooks[i].hk_lock_node = &actors[locked_actor]->ar_nodes[lock_node];
983 if (actor->
ar_hooks[i].hk_beam->bm_inter_actor)
990 auto ropes = j_entry[
"ropes"].GetArray();
991 for (
int i = 0; i < actor->
ar_ropes.size(); i++)
993 int ropable = ropes[i][
"locked_ropable"].GetInt();
994 int locked_actor = ropes[i][
"locked_actor"].GetInt();
996 locked_actor != -1 &&
997 locked_actor < (
int)actors.size() &&
998 actors[locked_actor] !=
nullptr)
1000 actor->
ar_ropes[i].rp_locked = ropes[i][
"locked"].GetInt();
1001 actor->
ar_ropes[i].rp_locked_actor = actors[locked_actor];
1002 actor->
ar_ropes[i].rp_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1006 auto ties = j_entry[
"ties"].GetArray();
1007 for (
int i = 0; i < actor->
ar_ties.size(); i++)
1009 int ropable = ties[i][
"locked_ropable"].GetInt();
1010 int locked_actor = ties[i][
"locked_actor"].GetInt();
1011 if (ropable != -1 &&
1012 locked_actor != -1 &&
1013 locked_actor < (
int)actors.size() &&
1014 actors[locked_actor] !=
nullptr)
1016 actor->
ar_ties[i].ti_tied = ties[i][
"tied"].GetBool();
1017 actor->
ar_ties[i].ti_tying = ties[i][
"tying"].GetBool();
1018 actor->
ar_ties[i].ti_locked_actor = actors[locked_actor];
1019 actor->
ar_ties[i].ti_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1020 if (actor->
ar_ties[i].ti_beam->bm_inter_actor)
1022 actor->
ar_ties[i].ti_beam->p2 = actor->
ar_ties[i].ti_locked_ropable->node;
1027 auto ropables = j_entry[
"ropables"].GetArray();
1028 for (
int i = 0; i < actor->
ar_ropables.size(); i++)
1030 actor->
ar_ropables[i].attached_ties = ropables[i][
"attached_ties"].GetInt();
1031 actor->
ar_ropables[i].attached_ropes = ropables[i][
"attached_ropes"].GetInt();