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())
306 String rigdef_filename = j_entry[
"filename"].GetString();
309 Str<600> msg; msg <<
_L(
"Error while loading scene: Missing content (probably not installed)") <<
" '" << rigdef_filename <<
"'";
311 actors.push_back(
nullptr);
316 if (j_entry.HasMember(
"skin"))
322 if (j_entry.HasMember(
"tuneup_document"))
324 const char* tuneup_str = j_entry[
"tuneup_document"].GetString();
325 size_t tuneup_len = j_entry[
"tuneup_document"].GetStringLength();
326 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream((
void*)tuneup_str, tuneup_len));
327 std::vector<TuneupDefPtr> tuneups = TuneupUtil::ParseTuneups(datastream);
329 working_tuneup = tuneups[0];
332 String section_config = j_entry[
"section_config"].GetString();
335 int index =
static_cast<int>(actors.size());
336 if (index < x_actors.size())
338 if (j_entry[
"filename"].GetString() != x_actors[index]->ar_filename ||
339 (skin !=
nullptr && skin->
dname != x_actors[index]->m_used_skin_entry->dname) ||
340 section_config != x_actors[index]->getSectionConfig())
342 if (x_actors[index] == player_actor)
346 else if (x_actors[index] == prev_player_actor)
351 actors_changed =
true;
355 actor = x_actors[index];
360 if (actor ==
nullptr)
362 bool preloaded = j_entry[
"preloaded_with_terrain"].GetBool();
367 rq->
asr_position.y = preloaded ? j_entry[
"position"][1].GetFloat() : j_entry[
"min_height"].GetFloat();
369 rq->
asr_rotation = Quaternion(Degree(270) - Radian(j_entry[
"rotation"].GetFloat()), Vector3::UNIT_Y);
373 rq->
asr_origin = preloaded ? ActorSpawnRequest::Origin::TERRN_DEF : ActorSpawnRequest::Origin::SAVEGAME;
376 rq->
asr_saved_state = std::shared_ptr<rapidjson::Document>(
new rapidjson::Document());
380 actors_changed =
true;
384 actors.push_back(actor);
386 for (
size_t index = actors.size(); index < x_actors.size(); index++)
388 if (x_actors[index] == player_actor)
392 else if (x_actors[index] == prev_player_actor)
397 actors_changed =
true;
400 const int num_actors =
static_cast<int>(j_doc[
"actors"].Size());
401 for (
int index = 0; index < num_actors; index++)
403 if (actors[index] ==
nullptr)
407 rapidjson::Value& j_entry = j_doc[
"actors"][index];
409 this->RestoreSavedState(actor, j_entry);
412 if (save_filename !=
"autosave.sav")
415 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene loaded"));
421 bool ActorManager::SaveScene(Ogre::String filename)
423 std::vector<ActorPtr> x_actors = GetLocalActors();
427 if (filename ==
"autosave.sav")
429 if (x_actors.size() > 3)
432 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene: Too many vehicles"));
437 rapidjson::Document j_doc;
443 String scene_name =
StringUtil::format(
"%s [%d]", pretty_name.c_str(), x_actors.size());
444 j_doc.AddMember(
"scene_name", rapidjson::StringRef(scene_name.c_str()), j_doc.GetAllocator());
447 j_doc.AddMember(
"terrain_name", rapidjson::StringRef(
App::sim_terrain_name->getStr().c_str()), j_doc.GetAllocator());
452 j_doc.AddMember(
"daytime",
App::GetGameContext()->GetTerrain()->getSkyManager()->GetTime(), j_doc.GetAllocator());
456 j_doc.AddMember(
"forced_awake", m_forced_awake, j_doc.GetAllocator());
458 j_doc.AddMember(
"physics_paused",
App::GetGameContext()->GetActorManager()->IsSimulationPaused(), j_doc.GetAllocator());
461 rapidjson::Value j_player_position(rapidjson::kArrayType);
462 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
x, j_doc.GetAllocator());
463 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
y, j_doc.GetAllocator());
464 j_player_position.PushBack(
App::GetGameContext()->GetPlayerCharacter()->getPosition().
z, j_doc.GetAllocator());
465 j_doc.AddMember(
"player_position", j_player_position, j_doc.GetAllocator());
466 j_doc.AddMember(
"player_rotation",
App::GetGameContext()->GetPlayerCharacter()->getRotation().valueRadians(), j_doc.GetAllocator());
468 std::map<int, int> vector_index_lookup;
471 vector_index_lookup[actor->ar_vector_index] = -1;
472 auto search = std::find_if(x_actors.begin(), x_actors.end(), [actor](
ActorPtr b)
473 { return actor->ar_instance_id == b->ar_instance_id; });
474 if (search != x_actors.end())
476 vector_index_lookup[actor->ar_vector_index] = std::distance(x_actors.begin(), search);
481 rapidjson::Value j_actors(rapidjson::kArrayType);
484 rapidjson::Value j_entry(rapidjson::kObjectType);
486 j_entry.AddMember(
"filename", rapidjson::StringRef(actor->ar_filename.c_str()), j_doc.GetAllocator());
487 rapidjson::Value j_actor_position(rapidjson::kArrayType);
488 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.x, j_doc.GetAllocator());
489 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.y, j_doc.GetAllocator());
490 j_actor_position.PushBack(actor->ar_nodes[0].AbsPosition.z, j_doc.GetAllocator());
491 j_entry.AddMember(
"position", j_actor_position, j_doc.GetAllocator());
492 j_entry.AddMember(
"rotation", actor->getRotation(), j_doc.GetAllocator());
493 j_entry.AddMember(
"min_height", actor->getMinHeight(), j_doc.GetAllocator());
494 j_entry.AddMember(
"spawn_rotation", actor->m_spawn_rotation, j_doc.GetAllocator());
495 j_entry.AddMember(
"preloaded_with_terrain", actor->isPreloadedWithTerrain(), j_doc.GetAllocator());
496 j_entry.AddMember(
"sim_state",
static_cast<int>(actor->ar_state), j_doc.GetAllocator());
497 j_entry.AddMember(
"physics_paused", actor->ar_physics_paused, j_doc.GetAllocator());
498 j_entry.AddMember(
"player_actor", actor==
App::GetGameContext()->GetPlayerActor(), j_doc.GetAllocator());
499 j_entry.AddMember(
"prev_player_actor", actor==
App::GetGameContext()->GetPrevPlayerActor(), j_doc.GetAllocator());
501 if (actor->m_used_skin_entry)
503 j_entry.AddMember(
"skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator());
506 if (actor->getWorkingTuneupDef())
509 rapidjson::Value j_tuneup_document(rapidjson::kStringType);
511 Ogre::DataStreamPtr datastream(
new Ogre::MemoryDataStream(tuneup_buf.
GetBuffer(), tuneup_buf.
GetCapacity()));
512 TuneupUtil::ExportTuneup(datastream, actor->getWorkingTuneupDef());
513 j_tuneup_document.SetString(datastream->getAsString().c_str(), j_doc.GetAllocator());
514 j_entry.AddMember(
"tuneup_document", j_tuneup_document, j_doc.GetAllocator());
517 j_entry.AddMember(
"section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator());
520 if (actor->ar_engine)
522 j_entry.AddMember(
"engine_gear", actor->ar_engine->GetGear(), j_doc.GetAllocator());
523 j_entry.AddMember(
"engine_rpm", actor->ar_engine->GetEngineRpm(), j_doc.GetAllocator());
524 j_entry.AddMember(
"engine_auto_mode", actor->ar_engine->GetAutoMode(), j_doc.GetAllocator());
525 j_entry.AddMember(
"engine_auto_select", actor->ar_engine->getAutoShift(), j_doc.GetAllocator());
526 j_entry.AddMember(
"engine_is_running", actor->ar_engine->isRunning(), j_doc.GetAllocator());
527 j_entry.AddMember(
"engine_has_contact", actor->ar_engine->hasContact(), j_doc.GetAllocator());
528 j_entry.AddMember(
"engine_wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
529 j_entry.AddMember(
"alb_mode", actor->alb_mode, j_doc.GetAllocator());
530 j_entry.AddMember(
"tc_mode", actor->tc_mode, j_doc.GetAllocator());
531 j_entry.AddMember(
"cc_mode", actor->cc_mode, j_doc.GetAllocator());
532 j_entry.AddMember(
"cc_target_rpm", actor->cc_target_rpm, j_doc.GetAllocator());
533 j_entry.AddMember(
"cc_target_speed", actor->cc_target_speed, j_doc.GetAllocator());
536 j_entry.AddMember(
"hydro_dir_state", actor->ar_hydro_dir_state, j_doc.GetAllocator());
537 j_entry.AddMember(
"hydro_aileron_state", actor->ar_hydro_aileron_state, j_doc.GetAllocator());
538 j_entry.AddMember(
"hydro_rudder_state", actor->ar_hydro_rudder_state, j_doc.GetAllocator());
539 j_entry.AddMember(
"hydro_elevator_state", actor->ar_hydro_elevator_state, j_doc.GetAllocator());
540 j_entry.AddMember(
"parking_brake", actor->ar_parking_brake, j_doc.GetAllocator());
541 j_entry.AddMember(
"trailer_parking_brake", actor->ar_trailer_parking_brake, j_doc.GetAllocator());
542 j_entry.AddMember(
"avg_wheel_speed", actor->ar_avg_wheel_speed, j_doc.GetAllocator());
543 j_entry.AddMember(
"wheel_speed", actor->ar_wheel_speed, j_doc.GetAllocator());
544 j_entry.AddMember(
"wheel_spin", actor->ar_wheel_spin, j_doc.GetAllocator());
546 j_entry.AddMember(
"custom_particles", actor->m_custom_particles_enabled, j_doc.GetAllocator());
549 j_entry.AddMember(
"lights", (
int)actor->getHeadlightsVisible(), j_doc.GetAllocator());
550 j_entry.AddMember(
"blink_type", (
int)actor->getBlinkType(), j_doc.GetAllocator());
553 j_entry.AddMember(
"beacon_light", actor->getBeaconMode(), j_doc.GetAllocator());
554 j_entry.AddMember(
"high_beams_on", actor->getHighBeamsVisible(), j_doc.GetAllocator());
555 j_entry.AddMember(
"fog_lights_on", actor->getFogLightsVisible(), j_doc.GetAllocator());
558 rapidjson::Value j_custom_lights(rapidjson::kArrayType);
561 j_custom_lights.PushBack(actor->getCustomLightVisible(i), j_doc.GetAllocator());
563 j_entry.AddMember(
"custom_lights", j_custom_lights, j_doc.GetAllocator());
566 if (actor->m_buoyance)
568 j_entry.AddMember(
"buoyance_sink", actor->m_buoyance->sink, j_doc.GetAllocator());
572 rapidjson::Value j_aeroengines(rapidjson::kArrayType);
573 for (
int i = 0; i < actor->ar_num_aeroengines; i++)
575 rapidjson::Value j_aeroengine(rapidjson::kObjectType);
576 j_aeroengine.AddMember(
"rpm", actor->ar_aeroengines[i]->getRPM(), j_doc.GetAllocator());
577 j_aeroengine.AddMember(
"reverse", actor->ar_aeroengines[i]->getReverse(), j_doc.GetAllocator());
578 j_aeroengine.AddMember(
"ignition", actor->ar_aeroengines[i]->getIgnition(), j_doc.GetAllocator());
579 j_aeroengine.AddMember(
"throttle", actor->ar_aeroengines[i]->getThrottle(), j_doc.GetAllocator());
580 j_aeroengines.PushBack(j_aeroengine, j_doc.GetAllocator());
582 j_entry.AddMember(
"aeroengines", j_aeroengines, j_doc.GetAllocator());
585 rapidjson::Value j_screwprops(rapidjson::kArrayType);
586 for (
int i = 0; i < actor->ar_num_screwprops; i++)
588 rapidjson::Value j_screwprop(rapidjson::kObjectType);
589 j_screwprop.AddMember(
"rudder", actor->ar_screwprops[i]->getRudder(), j_doc.GetAllocator());
590 j_screwprop.AddMember(
"throttle", actor->ar_screwprops[i]->getThrottle(), j_doc.GetAllocator());
591 j_screwprops.PushBack(j_screwprop, j_doc.GetAllocator());
593 j_entry.AddMember(
"screwprops", j_screwprops, j_doc.GetAllocator());
596 rapidjson::Value j_rotators(rapidjson::kArrayType);
597 for (
int i = 0; i < actor->ar_num_rotators; i++)
599 j_rotators.PushBack(actor->ar_rotators[i].angle, j_doc.GetAllocator());
601 j_entry.AddMember(
"rotators", j_rotators, j_doc.GetAllocator());
604 rapidjson::Value j_wheels(rapidjson::kArrayType);
605 for (
int i = 0; i < actor->ar_num_wheels; i++)
607 j_wheels.PushBack(actor->ar_wheels[i].wh_is_detached, j_doc.GetAllocator());
609 j_entry.AddMember(
"wheels", j_wheels, j_doc.GetAllocator());
612 rapidjson::Value j_wheel_diffs(rapidjson::kArrayType);
613 for (
int i = 0; i < actor->m_num_wheel_diffs; i++)
615 j_wheel_diffs.PushBack(actor->m_wheel_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
617 j_entry.AddMember(
"wheel_diffs", j_wheel_diffs, j_doc.GetAllocator());
620 rapidjson::Value j_axle_diffs(rapidjson::kArrayType);
621 for (
int i = 0; i < actor->m_num_axle_diffs; i++)
623 j_axle_diffs.PushBack(actor->m_axle_diffs[i]->GetActiveDiffType(), j_doc.GetAllocator());
625 j_entry.AddMember(
"axle_diffs", j_axle_diffs, j_doc.GetAllocator());
628 if (actor->m_transfer_case)
630 rapidjson::Value j_transfer_case(rapidjson::kObjectType);
631 j_transfer_case.AddMember(
"4WD", actor->m_transfer_case->tr_4wd_mode, j_doc.GetAllocator());
632 j_transfer_case.AddMember(
"GearRatio", actor->m_transfer_case->tr_gear_ratios[0], j_doc.GetAllocator());
633 j_entry.AddMember(
"transfercase", j_transfer_case, j_doc.GetAllocator());
637 rapidjson::Value j_commands(rapidjson::kArrayType);
640 rapidjson::Value j_command(rapidjson::kArrayType);
641 j_command.PushBack(actor->ar_command_key[i].commandValue, j_doc.GetAllocator());
642 j_command.PushBack(actor->ar_command_key[i].triggerInputValue, j_doc.GetAllocator());
644 rapidjson::Value j_command_beams(rapidjson::kArrayType);
645 for (
int j = 0; j < (int)actor->ar_command_key[i].beams.size(); j++)
647 rapidjson::Value j_cmb(rapidjson::kArrayType);
648 auto& beam = actor->ar_command_key[i].beams[j];
649 j_cmb.PushBack(beam.cmb_state->auto_moving_mode, j_doc.GetAllocator());
650 j_cmb.PushBack(beam.cmb_state->pressed_center_mode, j_doc.GetAllocator());
651 j_command_beams.PushBack(j_cmb, j_doc.GetAllocator());
653 j_command.PushBack(j_command_beams, j_doc.GetAllocator());
655 j_commands.PushBack(j_command, j_doc.GetAllocator());
657 j_entry.AddMember(
"commands", j_commands, j_doc.GetAllocator());
660 rapidjson::Value j_hooks(rapidjson::kArrayType);
661 for (
const auto& h : actor->ar_hooks)
663 rapidjson::Value j_hook(rapidjson::kObjectType);
664 int lock_node = h.hk_lock_node ? h.hk_lock_node->pos : -1;
665 int locked_actor = h.hk_locked_actor ? vector_index_lookup[h.hk_locked_actor->ar_vector_index] : -1;
666 j_hook.AddMember(
"locked", h.hk_locked, j_doc.GetAllocator());
667 j_hook.AddMember(
"lock_node", lock_node, j_doc.GetAllocator());
668 j_hook.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
669 j_hooks.PushBack(j_hook, j_doc.GetAllocator());
671 j_entry.AddMember(
"hooks", j_hooks, j_doc.GetAllocator());
674 rapidjson::Value j_ropes(rapidjson::kArrayType);
675 for (
const auto& r : actor->ar_ropes)
677 rapidjson::Value j_rope(rapidjson::kObjectType);
678 int locked_ropable = r.rp_locked_ropable ? r.rp_locked_ropable->pos : -1;
679 int locked_actor = r.rp_locked_actor ? vector_index_lookup[r.rp_locked_actor->ar_vector_index] : -1;
680 j_rope.AddMember(
"locked", r.rp_locked, j_doc.GetAllocator());
681 j_rope.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
682 j_rope.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
683 j_ropes.PushBack(j_rope, j_doc.GetAllocator());
685 j_entry.AddMember(
"ropes", j_ropes, j_doc.GetAllocator());
688 rapidjson::Value j_ties(rapidjson::kArrayType);
689 for (
const auto& t : actor->ar_ties)
691 rapidjson::Value j_tie(rapidjson::kObjectType);
692 int locked_ropable = t.ti_locked_ropable ? t.ti_locked_ropable->pos : -1;
693 int locked_actor = t.ti_locked_actor ? vector_index_lookup[t.ti_locked_actor->ar_vector_index] : -1;
694 j_tie.AddMember(
"tied", t.ti_tied, j_doc.GetAllocator());
695 j_tie.AddMember(
"tying", t.ti_tying, j_doc.GetAllocator());
696 j_tie.AddMember(
"locked_ropable", locked_ropable, j_doc.GetAllocator());
697 j_tie.AddMember(
"locked_actor", locked_actor, j_doc.GetAllocator());
698 j_ties.PushBack(j_tie, j_doc.GetAllocator());
700 j_entry.AddMember(
"ties", j_ties, j_doc.GetAllocator());
703 rapidjson::Value j_ropables(rapidjson::kArrayType);
704 for (
const auto& r : actor->ar_ropables)
706 rapidjson::Value j_ropable(rapidjson::kObjectType);
707 j_ropable.AddMember(
"attached_ties", r.attached_ties, j_doc.GetAllocator());
708 j_ropable.AddMember(
"attached_ropes", r.attached_ropes, j_doc.GetAllocator());
709 j_ropables.PushBack(j_ropable, j_doc.GetAllocator());
711 j_entry.AddMember(
"ropables", j_ropables, j_doc.GetAllocator());
713 j_entry.AddMember(
"slidenodes_locked", actor->m_slidenodes_locked, j_doc.GetAllocator());
716 rapidjson::Value j_nodes(rapidjson::kArrayType);
717 for (
int i = 0; i < actor->ar_num_nodes; i++)
719 rapidjson::Value j_node(rapidjson::kArrayType);
722 j_node.PushBack(actor->ar_nodes[i].AbsPosition.x, j_doc.GetAllocator());
723 j_node.PushBack(actor->ar_nodes[i].AbsPosition.y, j_doc.GetAllocator());
724 j_node.PushBack(actor->ar_nodes[i].AbsPosition.z, j_doc.GetAllocator());
727 j_node.PushBack(actor->ar_nodes[i].Velocity.x, j_doc.GetAllocator());
728 j_node.PushBack(actor->ar_nodes[i].Velocity.y, j_doc.GetAllocator());
729 j_node.PushBack(actor->ar_nodes[i].Velocity.z, j_doc.GetAllocator());
732 j_node.PushBack(actor->ar_initial_node_positions[i].x, j_doc.GetAllocator());
733 j_node.PushBack(actor->ar_initial_node_positions[i].y, j_doc.GetAllocator());
734 j_node.PushBack(actor->ar_initial_node_positions[i].z, j_doc.GetAllocator());
736 j_nodes.PushBack(j_node, j_doc.GetAllocator());
738 j_entry.AddMember(
"nodes", j_nodes, j_doc.GetAllocator());
741 rapidjson::Value j_beams(rapidjson::kArrayType);
742 for (
int i = 0; i < actor->ar_num_beams; i++)
744 rapidjson::Value j_beam(rapidjson::kArrayType);
746 j_beam.PushBack(actor->ar_beams[i].maxposstress, j_doc.GetAllocator());
747 j_beam.PushBack(actor->ar_beams[i].maxnegstress, j_doc.GetAllocator());
748 j_beam.PushBack(actor->ar_beams[i].minmaxposnegstress, j_doc.GetAllocator());
749 j_beam.PushBack(actor->ar_beams[i].strength, j_doc.GetAllocator());
750 j_beam.PushBack(actor->ar_beams[i].L, j_doc.GetAllocator());
751 j_beam.PushBack(actor->ar_beams[i].bm_broken, j_doc.GetAllocator());
752 j_beam.PushBack(actor->ar_beams[i].bm_disabled, j_doc.GetAllocator());
753 j_beam.PushBack(actor->ar_beams[i].bm_inter_actor, j_doc.GetAllocator());
755 j_beam.PushBack(locked_actor ? vector_index_lookup[locked_actor->
ar_vector_index] : -1, j_doc.GetAllocator());
757 j_beams.PushBack(j_beam, j_doc.GetAllocator());
759 j_entry.AddMember(
"beams", j_beams, j_doc.GetAllocator());
761 j_actors.PushBack(j_entry, j_doc.GetAllocator());
763 j_doc.AddMember(
"actors", j_actors, j_doc.GetAllocator());
770 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_ERROR,
_L(
"Error while saving scene"));
774 if (filename !=
"autosave.sav")
777 Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE,
_L(
"Scene saved"));
783 void ActorManager::RestoreSavedState(
ActorPtr actor, rapidjson::Value
const& j_entry)
789 if (j_entry[
"player_actor"].GetBool())
793 else if (j_entry[
"prev_player_actor"].GetBool())
800 int gear = j_entry[
"engine_gear"].GetInt();
801 float rpm = j_entry[
"engine_rpm"].GetFloat();
802 int automode = j_entry[
"engine_auto_mode"].GetInt();
803 int autoselect = j_entry[
"engine_auto_select"].GetInt();
804 bool running = j_entry[
"engine_is_running"].GetBool();
805 bool contact = j_entry[
"engine_has_contact"].GetBool();
815 actor->
alb_mode = j_entry[
"alb_mode"].GetBool();
816 actor->
tc_mode = j_entry[
"tc_mode"].GetBool();
817 actor->
cc_mode = j_entry[
"cc_mode"].GetBool();
842 actor->
setBeaconMode(j_entry.HasMember(
"beacon_light") ? j_entry[
"beacon_light"].GetBool() : j_entry[
"pp_beacon_light"].GetBool());
843 actor->
setHighBeamsVisible(j_entry.HasMember(
"high_beams_on") ? j_entry[
"high_beams_on"].GetBool() :
false);
844 actor->
setFogLightsVisible(j_entry.HasMember(
"fog_lights_on") ? j_entry[
"fog_lights_on"].GetBool() :
false);
847 if (j_entry.HasMember(
"custom_lights"))
849 auto flares = j_entry[
"custom_lights"].GetArray();
858 actor->
m_buoyance->sink = j_entry[
"buoyance_sink"].GetBool();
861 auto aeroengines = j_entry[
"aeroengines"].GetArray();
870 auto screwprops = j_entry[
"screwprops"].GetArray();
919 auto commands = j_entry[
"commands"].GetArray();
923 command_key.commandValue = commands[i][0].GetFloat();
924 command_key.triggerInputValue = commands[i][1].GetFloat();
925 auto command_beams = commands[i][2].GetArray();
926 for (
int j = 0; j < (int)command_key.beams.size(); j++)
928 command_key.beams[j].cmb_state->auto_moving_mode = command_beams[j][0].GetInt();
929 command_key.beams[j].cmb_state->pressed_center_mode = command_beams[j][1].GetBool();
933 auto nodes = j_entry[
"nodes"].GetArray();
934 for (rapidjson::SizeType i = 0; i <
nodes.Size(); i++)
936 auto data =
nodes[i].GetArray();
937 actor->
ar_nodes[i].
AbsPosition = Vector3(data[0].GetFloat(), data[1].GetFloat(), data[2].GetFloat());
939 actor->
ar_nodes[i].
Velocity = Vector3(data[3].GetFloat(), data[4].GetFloat(), data[5].GetFloat());
943 std::vector<ActorPtr> actors = this->GetLocalActors();
945 auto beams = j_entry[
"beams"].GetArray();
946 for (rapidjson::SizeType i = 0; i < beams.Size(); i++)
948 auto data = beams[i].GetArray();
953 actor->
ar_beams[i].
L = data[4].GetFloat();
957 int locked_actor = data[8].GetInt();
958 if (locked_actor != -1 &&
959 locked_actor < (
int)actors.size() &&
960 actors[locked_actor] !=
nullptr)
966 auto hooks = j_entry[
"hooks"].GetArray();
967 for (
int i = 0; i < actor->
ar_hooks.size(); i++)
969 int lock_node = hooks[i][
"lock_node"].GetInt();
970 int locked_actor = hooks[i][
"locked_actor"].GetInt();
971 if (lock_node != -1 &&
972 locked_actor != -1 &&
973 locked_actor < (
int)actors.size() &&
974 actors[locked_actor] !=
nullptr)
977 actor->
ar_hooks[i].hk_locked_actor = actors[locked_actor];
978 actor->
ar_hooks[i].hk_lock_node = &actors[locked_actor]->ar_nodes[lock_node];
979 if (actor->
ar_hooks[i].hk_beam->bm_inter_actor)
986 auto ropes = j_entry[
"ropes"].GetArray();
987 for (
int i = 0; i < actor->
ar_ropes.size(); i++)
989 int ropable = ropes[i][
"locked_ropable"].GetInt();
990 int locked_actor = ropes[i][
"locked_actor"].GetInt();
992 locked_actor != -1 &&
993 locked_actor < (
int)actors.size() &&
994 actors[locked_actor] !=
nullptr)
996 actor->
ar_ropes[i].rp_locked = ropes[i][
"locked"].GetInt();
997 actor->
ar_ropes[i].rp_locked_actor = actors[locked_actor];
998 actor->
ar_ropes[i].rp_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1002 auto ties = j_entry[
"ties"].GetArray();
1003 for (
int i = 0; i < actor->
ar_ties.size(); i++)
1005 int ropable = ties[i][
"locked_ropable"].GetInt();
1006 int locked_actor = ties[i][
"locked_actor"].GetInt();
1007 if (ropable != -1 &&
1008 locked_actor != -1 &&
1009 locked_actor < (
int)actors.size() &&
1010 actors[locked_actor] !=
nullptr)
1012 actor->
ar_ties[i].ti_tied = ties[i][
"tied"].GetBool();
1013 actor->
ar_ties[i].ti_tying = ties[i][
"tying"].GetBool();
1014 actor->
ar_ties[i].ti_locked_actor = actors[locked_actor];
1015 actor->
ar_ties[i].ti_locked_ropable = &actors[locked_actor]->ar_ropables[ropable];
1016 if (actor->
ar_ties[i].ti_beam->bm_inter_actor)
1018 actor->
ar_ties[i].ti_beam->p2 = actor->
ar_ties[i].ti_locked_ropable->node;
1023 auto ropables = j_entry[
"ropables"].GetArray();
1024 for (
int i = 0; i < actor->
ar_ropables.size(); i++)
1026 actor->
ar_ropables[i].attached_ties = ropables[i][
"attached_ties"].GetInt();
1027 actor->
ar_ropables[i].attached_ropes = ropables[i][
"attached_ropes"].GetInt();