71 #include <fmt/format.h>
72 #include "half/half.hpp"
96 this->DisjoinInterActorBeams();
99 ar_node_to_beam_connections.clear();
100 ar_node_to_node_connections.clear();
103 if (ar_dashboard !=
nullptr)
106 ar_dashboard =
nullptr;
116 for (
int i = 0; i < ar_num_soundsources; i++)
118 if (ar_soundsources[i].ssi)
121 ar_soundsources[i].ssi =
nullptr;
124 ar_num_soundsources = 0;
127 if (ar_engine !=
nullptr)
133 if (ar_autopilot !=
nullptr)
136 ar_autopilot =
nullptr;
139 if (m_fusealge_airfoil)
140 delete m_fusealge_airfoil;
141 m_fusealge_airfoil =
nullptr;
143 if (m_replay_handler)
144 delete m_replay_handler;
145 m_replay_handler =
nullptr;
147 ar_vehicle_ai =
nullptr;
150 if (m_deletion_scene_nodes.size() > 0)
152 for (
unsigned int i = 0; i < m_deletion_scene_nodes.size(); i++)
156 if (!m_deletion_scene_nodes[i])
158 m_deletion_scene_nodes[i]->removeAndDestroyAllChildren();
167 m_deletion_scene_nodes.clear();
170 if (m_deletion_entities.size() > 0)
172 for (
unsigned int i = 0; i < m_deletion_entities.size(); i++)
176 if (!m_deletion_entities[i])
178 m_deletion_entities[i]->detachAllObjectsFromBone();
187 m_deletion_entities.clear();
194 for (
int i = 0; i < ar_num_wings; i++)
200 delete ar_wings[i].fa;
201 if (ar_wings[i].cnode)
203 ar_wings[i].cnode->removeAndDestroyAllChildren();
215 for (
int i = 0; i < ar_num_aeroengines; i++)
217 if (ar_aeroengines[i])
218 delete ar_aeroengines[i];
222 for (
int i = 0; i < ar_num_screwprops; i++)
224 if (ar_screwprops[i])
226 delete ar_screwprops[i];
227 ar_screwprops[i] =
nullptr;
236 ar_airbrakes.clear();
239 for (
int i = 0; i < ar_num_wheels; ++i)
241 delete m_skid_trails[i];
242 m_skid_trails[i] =
nullptr;
246 for (
size_t i = 0; i < this->ar_flares.size(); i++)
250 if (ar_flares[i].snode)
252 ar_flares[i].snode->removeAndDestroyAllChildren();
255 if (ar_flares[i].bbs)
257 if (ar_flares[i].light)
266 this->ar_flares.clear();
269 for (std::vector<exhaust_t>::iterator it = exhausts.begin(); it != exhausts.end(); it++)
275 it->smokeNode->removeAndDestroyAllChildren();
280 it->smoker->removeAllAffectors();
281 it->smoker->removeAllEmitters();
293 for (
int i = 0; i < ar_num_custom_particles; i++)
297 if (ar_custom_particles[i].snode)
299 ar_custom_particles[i].snode->removeAndDestroyAllChildren();
302 if (ar_custom_particles[i].psys)
304 ar_custom_particles[i].psys->removeAllAffectors();
305 ar_custom_particles[i].psys->removeAllEmitters();
317 for (std::vector<RailGroup*>::iterator it = m_railgroups.begin(); it != m_railgroups.end(); it++)
321 m_railgroups.clear();
323 if (m_intra_point_col_detector)
325 delete m_intra_point_col_detector;
326 m_intra_point_col_detector =
nullptr;
329 if (m_inter_point_col_detector)
331 delete m_inter_point_col_detector;
332 m_inter_point_col_detector =
nullptr;
336 delete m_transfer_case;
338 for (
int i = 0; i < m_num_axle_diffs; ++i)
340 if (m_axle_diffs[i] !=
nullptr)
341 delete m_axle_diffs[i];
343 m_num_axle_diffs = 0;
345 for (
int i = 0; i < m_num_wheel_diffs; ++i)
347 if (m_wheel_diffs[i] !=
nullptr)
348 delete m_wheel_diffs[i];
350 m_num_wheel_diffs = 0;
354 m_wheel_node_count = 0;
359 delete[] ar_rotators;
364 ar_state = ActorState::DISPOSED;
369 void Actor::scaleTruck(
float value)
371 if (ar_state == ActorState::DISPOSED)
378 for (
int i = 0; i < ar_num_beams; i++)
381 ar_beams[i].d *= value;
382 ar_beams[i].L *= value;
383 ar_beams[i].refL *= value;
388 hbeam.hb_ref_length *= value;
389 hbeam.hb_speed *= value;
392 Vector3 refpos = ar_nodes[0].AbsPosition;
393 Vector3 relpos = ar_nodes[0].RelPosition;
394 for (
int i = 1; i < ar_num_nodes; i++)
396 ar_initial_node_positions[i] = refpos + (ar_initial_node_positions[i] - refpos) * value;
397 ar_nodes[i].AbsPosition = refpos + (ar_nodes[i].AbsPosition - refpos) * value;
398 ar_nodes[i].RelPosition = relpos + (ar_nodes[i].RelPosition - relpos) * value;
399 ar_nodes[i].Velocity *= value;
400 ar_nodes[i].Forces *= value;
401 ar_nodes[i].mass *= value;
403 updateSlideNodePositions();
405 m_gfx_actor->ScaleActor(relpos, value);
409 float Actor::getRotation()
411 if (ar_state == ActorState::DISPOSED)
414 Vector3 dir = getDirection();
416 return atan2(dir.dotProduct(Vector3::UNIT_X), dir.dotProduct(-Vector3::UNIT_Z));
419 Vector3 Actor::getDirection()
421 return ar_main_camera_dir_corr * this->GetCameraDir();
424 Vector3 Actor::getPosition()
426 return m_avg_node_position;
429 Ogre::Quaternion Actor::getOrientation()
431 Ogre::Vector3 localZ = ar_main_camera_dir_corr * -this->GetCameraDir();
432 Ogre::Vector3 localX = ar_main_camera_dir_corr * this->GetCameraRoll();
433 Ogre::Vector3 localY = localZ.crossProduct(localX);
434 return Ogre::Quaternion(localX, localY, localZ);
437 void Actor::pushNetwork(
char* data,
int size)
443 update.
node_data.resize(m_net_node_buf_size);
444 update.
wheel_data.resize(ar_num_wheels *
sizeof(
float));
457 memcpy(update.
node_data.data(), ptr, m_net_node_buf_size);
458 ptr += m_net_node_buf_size;
461 for (
int i = 0; i < ar_num_wheels; i++)
463 float wspeed = *(
float*)(ptr);
465 ptr +=
sizeof(float);
469 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
472 char byte = *(ptr + (i / 8));
473 char mask = char(1) << (7 - (i % 8));
474 m_prop_anim_key_states[i].anim_active = (
byte & mask);
479 if (!m_net_initialized)
487 strncpy(reg.
name, ar_filename.c_str(), 128);
496 text << info.
username <<
_L(
" content mismatch: ") << reg.name;
503 m_net_initialized =
true;
505 RoR::LogFormat(
"[RoR|Network] Stream mismatch, filename: '%s'", ar_filename.c_str());
510 if (!m_net_initialized)
514 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
515 if (oob->
time > rnow + 100)
521 m_net_updates.push_back(update);
522 #endif // USE_SOCKETW
525 void Actor::calcNetwork()
529 if (m_net_updates.size() < 2)
533 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
536 int index_offset = 0;
537 for (
int i = 0; i < m_net_updates.size() - 1; i++)
540 if (oob->
time > rnow)
547 char* netb1 = (
char*) m_net_updates[index_offset ].node_data.data();
548 char* netb2 = (
char*) m_net_updates[index_offset + 1].node_data.data();
549 float* net_rp1 = (
float*) m_net_updates[index_offset ].wheel_data.data();
550 float* net_rp2 = (
float*) m_net_updates[index_offset + 1].wheel_data.data();
552 float tratio = (float)(rnow - oob1->
time) / (float)(oob2->
time - oob1->
time);
556 m_net_updates.clear();
559 else if (tratio > 1.0f)
563 else if (index_offset == 0 && (m_net_updates.size() > 5 || (tratio < 0.125f && m_net_updates.size() > 2)))
568 half_float::half* halfb1 =
reinterpret_cast<half_float::half*
>(netb1 +
sizeof(float) * 3);
569 half_float::half* halfb2 =
reinterpret_cast<half_float::half*
>(netb2 +
sizeof(float) * 3);
570 Vector3 p1ref = Vector3::ZERO;
571 Vector3 p2ref = Vector3::ZERO;
572 Vector3 p1 = Vector3::ZERO;
573 Vector3 p2 = Vector3::ZERO;
575 for (
int i = 0; i < m_net_first_wheel_node; i++)
580 p1.x = ((
float*)netb1)[0];
581 p1.y = ((
float*)netb1)[1];
582 p1.z = ((
float*)netb1)[2];
585 p2.x = ((
float*)netb2)[0];
586 p2.y = ((
float*)netb2)[1];
587 p2.z = ((
float*)netb2)[2];
593 const int bufpos = (i - 1) * 3;
594 const Vector3 p1rel(halfb1[bufpos + 0], halfb1[bufpos + 1], halfb1[bufpos + 2]);
595 const Vector3 p2rel(halfb2[bufpos + 0], halfb2[bufpos + 1], halfb2[bufpos + 2]);
602 ar_nodes[i].AbsPosition = p1 + tratio * (p2 - p1);
603 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
604 ar_nodes[i].Velocity = (p2 - p1) * 1000.0f / (
float)(oob2->
time - oob1->
time);
607 for (
int i = 0; i < ar_num_wheels; i++)
609 float rp = net_rp1[i] + tratio * (net_rp2[i] - net_rp1[i]);
611 Vector3 axis = ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition;
613 Plane pplan = Plane(axis, ar_wheels[i].wh_axis_node_0->AbsPosition);
614 Vector3 ortho = -pplan.projectVector(ar_wheels[i].wh_near_attach_node->AbsPosition) - ar_wheels[i].wh_axis_node_0->AbsPosition;
615 Vector3 ray = ortho.crossProduct(axis);
617 ray *= ar_wheels[i].wh_radius;
618 float drp = Math::TWO_PI / (ar_wheels[i].wh_num_nodes / 2);
619 for (
int j = 0; j < ar_wheels[i].wh_num_nodes / 2; j++)
621 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
623 ar_wheels[i].wh_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
624 ar_wheels[i].wh_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_nodes[j * 2]->AbsPosition - ar_origin;
626 ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
627 ar_wheels[i].wh_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition - ar_origin;
630 ray *= ar_wheels[i].wh_rim_radius;
631 for (
int j = 0; j < ar_wheels[i].wh_num_rim_nodes / 2; j++)
633 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
635 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
636 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2]->AbsPosition - ar_origin;
638 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
639 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition - ar_origin;
642 this->UpdateBoundingBoxes();
643 this->calculateAveragePosition();
652 ar_wheel_speed = netwspeed;
662 if (ar_num_aeroengines > 0)
684 ar_engine->PushNetworkState(engspeed, engforce, engclutch, gear, running, contact, automode);
689 toggleCustomParticles();
695 this->setLightStateMask(oob1->
lightmask);
707 for (
int i = 0; i < index_offset; i++)
709 m_net_updates.pop_front();
712 m_net_initialized =
true;
715 void Actor::RecalculateNodeMasses(Real total)
718 for (
int i = 0; i < ar_num_nodes; i++)
720 if (!ar_nodes[i].nd_tyre_node)
722 if (!ar_nodes[i].nd_loaded_mass)
724 ar_nodes[i].mass = 0;
726 else if (!ar_nodes[i].nd_override_mass)
728 ar_nodes[i].mass = m_load_mass / (float)m_masscount;
734 for (
int i = 0; i < ar_num_beams; i++)
738 Real half_newlen = ar_beams[i].L / 2.0;
739 if (!ar_beams[i].p1->nd_tyre_node)
741 if (!ar_beams[i].p2->nd_tyre_node)
746 for (
int i = 0; i < ar_num_beams; i++)
750 Real half_mass = ar_beams[i].L * total / len / 2.0f;
751 if (!ar_beams[i].p1->nd_tyre_node)
752 ar_beams[i].p1->mass += half_mass;
753 if (!ar_beams[i].p2->nd_tyre_node)
754 ar_beams[i].p2->mass += half_mass;
758 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
760 it->rp_beam->p2->mass = 100.0f;
764 for (
int i = 0; i < this->ar_num_cinecams; ++i)
767 ar_nodes[ar_cinecam_node[i]].mass = m_definition->root_module->cinecam[i].node_mass;
771 for (
int i = 0; i < ar_num_nodes; i++)
773 if (!ar_nodes[i].nd_tyre_node &&
774 !(ar_minimass_skip_loaded_nodes && ar_nodes[i].nd_loaded_mass) &&
775 ar_nodes[i].mass < ar_minimass[i])
780 snprintf(buf, 300,
"Node '%d' mass (%f Kg) is too light. Resetting to 'minimass' (%f Kg)", i, ar_nodes[i].mass, ar_minimass[i]);
783 ar_nodes[i].mass = ar_minimass[i];
788 for (
int i = 0; i < ar_num_nodes; i++)
792 String msg =
"Node " +
TOSTRING(i) +
" : " +
TOSTRING((
int)ar_nodes[i].mass) +
" kg";
793 if (ar_nodes[i].nd_loaded_mass)
795 if (ar_nodes[i].nd_override_mass)
796 msg +=
" (overriden by node mass)";
798 msg +=
" (normal load node: " +
TOSTRING(m_load_mass) +
" kg / " +
TOSTRING(m_masscount) +
" nodes)";
802 m_total_mass += ar_nodes[i].mass;
804 LOG(
"TOTAL VEHICLE MASS: " +
TOSTRING((
int)m_total_mass) +
" kg");
807 float Actor::getTotalMass(
bool withLocked)
809 if (ar_state == ActorState::DISPOSED)
815 float mass = m_total_mass;
817 for (
ActorPtr& actor : ar_linked_actors)
819 mass += actor->m_total_mass;
825 void Actor::DetermineLinkedActors()
830 ar_linked_actors.clear();
833 std::map<ActorPtr, bool> lookup_table;
835 lookup_table.insert(std::pair<ActorPtr, bool>(
this,
false));
841 for (
auto it_actor = lookup_table.begin(); it_actor != lookup_table.end(); ++it_actor)
843 if (!it_actor->second)
848 auto actor_pair = inter_actor_link.second;
849 if (actor == actor_pair.first || actor == actor_pair.second)
851 auto other_actor = (actor != actor_pair.first) ? actor_pair.first : actor_pair.second;
852 auto ret = lookup_table.insert(std::pair<ActorPtr, bool>(other_actor,
false));
855 ar_linked_actors.push_back(other_actor);
860 it_actor->second =
true;
866 int Actor::getWheelNodeCount()
const
868 return m_wheel_node_count;
871 void Actor::calcNodeConnectivityGraph()
875 ar_node_to_node_connections.resize(ar_num_nodes, std::vector<int>());
876 ar_node_to_beam_connections.resize(ar_num_nodes, std::vector<int>());
878 for (i = 0; i < ar_num_beams; i++)
880 if (ar_beams[i].p1 != NULL && ar_beams[i].p2 != NULL && ar_beams[i].p1->pos >= 0 && ar_beams[i].p2->pos >= 0)
882 ar_node_to_node_connections[ar_beams[i].p1->pos].push_back(ar_beams[i].p2->pos);
883 ar_node_to_beam_connections[ar_beams[i].p1->pos].push_back(i);
884 ar_node_to_node_connections[ar_beams[i].p2->pos].push_back(ar_beams[i].p1->pos);
885 ar_node_to_beam_connections[ar_beams[i].p2->pos].push_back(i);
890 bool Actor::Intersects(
ActorPtr actor, Vector3 offset)
892 Vector3 bb_min = ar_bounding_box.getMinimum() + offset;
893 Vector3 bb_max = ar_bounding_box.getMaximum() + offset;
894 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
900 for (
int i = 0; i < ar_num_beams; i++)
902 if (!(ar_beams[i].p1->nd_contacter || ar_beams[i].p1->nd_contactable) ||
903 !(ar_beams[i].p2->nd_contacter || ar_beams[i].p2->nd_contactable))
906 Vector3 origin = ar_beams[i].p1->AbsPosition + offset;
907 Vector3 target = ar_beams[i].p2->AbsPosition + offset;
909 Ray ray(origin, target - origin);
918 auto result = Ogre::Math::intersects(ray, a, b, c);
919 if (result.first && result.second < 1.0f)
936 Ray ray(origin, target - origin);
938 for (
int j = 0; j < ar_num_collcabs; j++)
940 int index = ar_collcabs[j] * 3;
941 Vector3 a = ar_nodes[ar_cabs[index + 0]].AbsPosition + offset;
942 Vector3 b = ar_nodes[ar_cabs[index + 1]].AbsPosition + offset;
943 Vector3 c = ar_nodes[ar_cabs[index + 2]].AbsPosition + offset;
945 auto result = Ogre::Math::intersects(ray, a, b, c);
946 if (result.first && result.second < 1.0f)
956 Vector3 Actor::calculateCollisionOffset(Vector3 direction)
958 if (direction == Vector3::ZERO)
959 return Vector3::ZERO;
961 Real max_distance = direction.normalise();
964 Vector3 collision_offset = Vector3::ZERO;
966 while (collision_offset.length() < max_distance)
968 Vector3 bb_min = ar_bounding_box.getMinimum() + collision_offset;
969 Vector3 bb_max = ar_bounding_box.getMaximum() + collision_offset;
970 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
972 bool collision =
false;
978 if (!bb.intersects(actor->ar_bounding_box))
982 if (m_intra_point_col_detector)
984 for (
int i = 0; i < actor->ar_num_collcabs; i++)
986 int tmpv = actor->ar_collcabs[i] * 3;
987 node_t* no = &actor->ar_nodes[actor->ar_cabs[tmpv]];
988 node_t* na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]];
989 node_t* nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]];
991 m_intra_point_col_detector->query(no->
AbsPosition - collision_offset,
994 actor->ar_collision_range * 3.0f);
996 if (collision = !m_intra_point_col_detector->hit_list.empty())
1004 float proximity = std::max(.05f, std::sqrt(std::max(m_min_camera_radius, actor->m_min_camera_radius)) / 50.f);
1007 for (
int i = 0; i < ar_num_nodes; i++)
1009 if (!ar_nodes[i].nd_contacter && !ar_nodes[i].nd_contactable)
1012 Vector3 query_position = ar_nodes[i].AbsPosition + collision_offset;
1014 for (
int j = 0; j < actor->ar_num_nodes; j++)
1016 if (!actor->ar_nodes[j].nd_contacter && !actor->ar_nodes[j].nd_contactable)
1019 if (collision = query_position.squaredDistance(actor->ar_nodes[j].AbsPosition) < proximity)
1032 if (!collision && m_inter_point_col_detector)
1034 for (
int i = 0; i < ar_num_collcabs; i++)
1036 int tmpv = ar_collcabs[i] * 3;
1037 node_t* no = &ar_nodes[ar_cabs[tmpv]];
1038 node_t* na = &ar_nodes[ar_cabs[tmpv + 1]];
1039 node_t* nb = &ar_nodes[ar_cabs[tmpv + 2]];
1041 m_inter_point_col_detector->query(no->
AbsPosition + collision_offset,
1044 ar_collision_range * 3.0f);
1046 if (collision = !m_inter_point_col_detector->hit_list.empty())
1058 if (collision = this->Intersects(actor, collision_offset))
1066 collision_offset += direction * 0.05f;
1069 return collision_offset;
1072 void Actor::resolveCollisions(Ogre::Vector3 direction)
1074 if (m_intra_point_col_detector)
1075 m_intra_point_col_detector->UpdateIntraPoint(
true);
1077 if (m_inter_point_col_detector)
1078 m_inter_point_col_detector->UpdateInterPoint(
true);
1080 Vector3 offset = calculateCollisionOffset(direction);
1082 if (offset == Vector3::ZERO)
1086 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1088 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
false, this->getMinHeight() + offset.y);
1091 void Actor::resolveCollisions(
float max_distance,
bool consider_up)
1093 if (m_intra_point_col_detector)
1094 m_intra_point_col_detector->UpdateIntraPoint(
true);
1096 if (m_inter_point_col_detector)
1097 m_inter_point_col_detector->UpdateInterPoint(
true);
1099 Vector3 u = Vector3::UNIT_Y;
1100 Vector3 f = Vector3(getDirection().
x, 0.0f, getDirection().
z).normalisedCopy();
1101 Vector3 l = u.crossProduct(f);
1104 Vector3 left = calculateCollisionOffset(+l * max_distance);
1105 Vector3 right = calculateCollisionOffset(-l * left.length());
1106 Vector3 lateral = left.length() < right.length() * 1.1f ? left : right;
1108 Vector3 front = calculateCollisionOffset(+f * lateral.length());
1109 Vector3 back = calculateCollisionOffset(-f * front.length());
1110 Vector3 sagittal = front.length() < back.length() * 1.1f ? front : back;
1112 Vector3 offset = lateral.length() < sagittal.length() * 1.2f ? lateral : sagittal;
1116 Vector3 up = calculateCollisionOffset(+u * offset.length());
1117 if (up.length() * 1.2f < offset.length())
1121 if (offset == Vector3::ZERO)
1125 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1127 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
true, this->getMinHeight() + offset.y);
1130 void Actor::calculateAveragePosition()
1135 m_avg_node_position = ar_nodes[ar_custom_camera_node].AbsPosition;
1137 else if (ar_extern_camera_mode == ExtCameraMode::CINECAM && ar_num_cinecams > 0)
1140 m_avg_node_position = ar_nodes[ar_cinecam_node[0]].AbsPosition;
1142 else if (ar_extern_camera_mode == ExtCameraMode::NODE && ar_extern_camera_node !=
NODENUM_INVALID)
1145 m_avg_node_position = ar_nodes[ar_extern_camera_node].AbsPosition;
1150 Vector3 aposition = Vector3::ZERO;
1151 for (
int n = 0; n < ar_num_nodes; n++)
1153 aposition += ar_nodes[n].AbsPosition;
1155 m_avg_node_position = aposition / ar_num_nodes;
1165 void Actor::UpdateBoundingBoxes()
1168 ar_bounding_box = AxisAlignedBox::BOX_NULL;
1169 ar_predicted_bounding_box = AxisAlignedBox::BOX_NULL;
1170 ar_evboxes_bounding_box = AxisAlignedBox::BOX_NULL;
1171 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1173 ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1174 ar_predicted_coll_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1179 const float CABNODE_MAX_CAMDIST = 15.f;
1180 const Ogre::Vector3 mainCamPos = ar_nodes[ar_main_camera_node_pos].RelPosition;
1183 for (
int i = 0; i < ar_num_nodes; i++)
1185 Vector3 vel = ar_nodes[i].Velocity;
1186 Vector3 pos = ar_nodes[i].AbsPosition;
1187 int16_t cid = ar_nodes[i].nd_coll_bbox_id;
1189 ar_bounding_box.merge(pos);
1190 if (mainCamPos.squaredDistance(ar_nodes[i].RelPosition) < (CABNODE_MAX_CAMDIST*CABNODE_MAX_CAMDIST))
1192 ar_evboxes_bounding_box.merge(pos);
1194 ar_predicted_bounding_box.merge(pos);
1195 ar_predicted_bounding_box.merge(pos + vel);
1196 if (cid != node_t::INVALID_BBOX)
1198 ar_collision_bounding_boxes[cid].merge(pos);
1199 ar_predicted_coll_bounding_boxes[cid].merge(pos);
1200 ar_predicted_coll_bounding_boxes[cid].merge(pos + vel);
1207 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1214 void Actor::UpdatePhysicsOrigin()
1216 if (ar_nodes[0].RelPosition.squaredLength() > 10000.0)
1218 Vector3 offset = ar_nodes[0].RelPosition;
1219 ar_origin += offset;
1220 for (
int i = 0; i < ar_num_nodes; i++)
1222 ar_nodes[i].RelPosition -= offset;
1227 void Actor::ResetAngle(
float rot)
1230 Vector3 origin = ar_nodes[ar_main_camera_node_pos].AbsPosition;
1234 matrix.FromEulerAnglesXYZ(Radian(0), Radian(-rot + m_spawn_rotation), Radian(0));
1236 for (
int i = 0; i < ar_num_nodes; i++)
1239 ar_nodes[i].AbsPosition -= origin;
1240 ar_nodes[i].AbsPosition = matrix * ar_nodes[i].AbsPosition;
1241 ar_nodes[i].AbsPosition += origin;
1242 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - this->ar_origin;
1245 this->UpdateBoundingBoxes();
1246 calculateAveragePosition();
1249 void Actor::updateInitPosition()
1251 for (
int i = 0; i < ar_num_nodes; i++)
1253 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1257 void Actor::resetPosition(
float px,
float pz,
bool setInitPosition,
float miny)
1260 Vector3 offset = Vector3(px, ar_nodes[0].AbsPosition.y, pz) - ar_nodes[0].AbsPosition;
1261 for (
int i = 0; i < ar_num_nodes; i++)
1263 ar_nodes[i].AbsPosition += offset;
1264 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1268 float vertical_offset = miny - this->getMinHeight();
1271 vertical_offset += std::max(0.0f,
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight() - miny);
1273 for (
int i = 1; i < ar_num_nodes; i++)
1275 if (ar_nodes[i].nd_no_ground_contact)
1278 vertical_offset += std::max(0.0f, terrainHeight - (ar_nodes[i].AbsPosition.y + vertical_offset));
1280 for (
int i = 0; i < ar_num_nodes; i++)
1282 ar_nodes[i].AbsPosition.y += vertical_offset;
1283 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1287 float mesh_offset = 0.0f;
1288 for (
int i = 0; i < ar_num_nodes; i++)
1290 if (mesh_offset >= 1.0f)
1292 if (ar_nodes[i].nd_no_ground_contact)
1294 float offset = mesh_offset;
1295 while (offset < 1.0f)
1297 Vector3 query = ar_nodes[i].AbsPosition + Vector3(0.0f, offset, 0.0f);
1298 if (!
App::GetGameContext()->GetTerrain()->GetCollisions()->collisionCorrect(&query,
false))
1300 mesh_offset = offset;
1306 for (
int i = 0; i < ar_num_nodes; i++)
1308 ar_nodes[i].AbsPosition.y += mesh_offset;
1309 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1312 resetPosition(Vector3::ZERO, setInitPosition);
1315 void Actor::resetPosition(Ogre::Vector3 translation,
bool setInitPosition)
1318 if (translation != Vector3::ZERO)
1320 Vector3 offset = translation - ar_nodes[0].AbsPosition;
1321 for (
int i = 0; i < ar_num_nodes; i++)
1323 ar_nodes[i].AbsPosition += offset;
1324 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1328 if (setInitPosition)
1330 for (
int i = 0; i < ar_num_nodes; i++)
1332 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1336 this->UpdateBoundingBoxes();
1337 calculateAveragePosition();
1340 void Actor::mouseMove(
NodeNum_t node, Vector3 pos,
float force)
1342 m_mouse_grab_node = node;
1343 m_mouse_grab_move_force = force * std::pow(m_total_mass / 3000.0f, 0.75f);
1344 m_mouse_grab_pos = pos;
1347 void Actor::toggleWheelDiffMode()
1349 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1351 m_wheel_diffs[i]->ToggleDifferentialMode();
1355 void Actor::toggleAxleDiffMode()
1357 for (
int i = 0; i < m_num_axle_diffs; ++i)
1359 m_axle_diffs[i]->ToggleDifferentialMode();
1363 void Actor::displayAxleDiffMode()
1365 if (m_num_axle_diffs == 0)
1368 _L(
"No inter-axle differential installed on current vehicle!"),
"error.png");
1372 String message =
"";
1373 for (
int i = 0; i < m_num_axle_diffs; ++i)
1375 if (m_axle_diffs[i])
1380 int a1 = m_axle_diffs[i]->di_idx_1 + 1;
1381 int a2 = m_axle_diffs[i]->di_idx_2 + 1;
1383 message += m_axle_diffs[i]->GetDifferentialTypeName();
1387 "Inter-axle differentials:\n" + message,
"cog.png");
1391 void Actor::displayWheelDiffMode()
1393 if (m_num_wheel_diffs == 0)
1396 _L(
"No inter-wheel differential installed on current vehicle!"),
"error.png");
1400 String message =
"";
1401 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1403 if (m_wheel_diffs[i])
1408 message +=
_L(
"Axle ") +
TOSTRING(i + 1) +
": ";
1409 message += m_wheel_diffs[i]->GetDifferentialTypeName();
1413 "Inter-wheel differentials:\n" + message,
"cog.png");
1417 void Actor::displayTransferCaseMode()
1419 if (m_transfer_case)
1422 _L(
"Transfercase switched to: ") + this->getTransferCaseName(),
"cog.png");
1427 _L(
"No transfercase installed on current vehicle!"),
"error.png");
1431 void Actor::toggleTransferCaseMode()
1433 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_ax_2 < 0 || !m_transfer_case->tr_2wd)
1436 if (m_transfer_case->tr_4wd_mode && !m_transfer_case->tr_2wd_lo)
1438 for (
int i = 0; i < m_transfer_case->tr_gear_ratios.size(); i++)
1440 this->toggleTransferCaseGearRatio();
1441 if (m_transfer_case->tr_gear_ratios[0] == 1.0f)
1446 m_transfer_case->tr_4wd_mode = !m_transfer_case->tr_4wd_mode;
1448 if (m_transfer_case->tr_4wd_mode)
1450 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
true;
1451 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
true;
1452 m_num_proped_wheels += 2;
1456 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
false;
1457 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
false;
1458 m_num_proped_wheels -= 2;
1462 void Actor::toggleTransferCaseGearRatio()
1464 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_gear_ratios.size() < 2)
1467 if (m_transfer_case->tr_4wd_mode || m_transfer_case->tr_2wd_lo)
1469 auto gear_ratios = &m_transfer_case->tr_gear_ratios;
1470 std::rotate(gear_ratios->begin(), gear_ratios->begin() + 1, gear_ratios->end());
1472 ar_engine->SetTCaseRatio(m_transfer_case->tr_gear_ratios[0]);
1476 String Actor::getTransferCaseName()
1479 if (m_transfer_case)
1481 name += m_transfer_case->tr_4wd_mode ?
"4WD " :
"2WD ";
1482 if (m_transfer_case->tr_gear_ratios[0] > 1.0f)
1483 name +=
"Lo (" +
TOSTRING(m_transfer_case->tr_gear_ratios[0]) +
":1)";
1490 Ogre::Vector3 Actor::getRotationCenter()
1492 Vector3 sum = Vector3::ZERO;
1493 std::vector<Vector3> positions;
1494 for (
int i = 0; i < ar_num_nodes; i++)
1496 Vector3 pos = ar_nodes[i].AbsPosition;
1497 const auto it = std::find_if(positions.begin(), positions.end(),
1498 [pos](
const Vector3 ref) { return pos.positionEquals(ref, 0.01f); });
1499 if (it == positions.end())
1502 positions.push_back(pos);
1505 return sum / positions.size();
1508 float Actor::getMinHeight(
bool skip_virtual_nodes)
1510 float height = std::numeric_limits<float>::max();
1511 for (
int i = 0; i < ar_num_nodes; i++)
1513 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1515 height = std::min(ar_nodes[i].AbsPosition.y, height);
1518 return (!skip_virtual_nodes || height < std::numeric_limits<float>::max()) ? height : getMinHeight(
false);
1521 float Actor::getMaxHeight(
bool skip_virtual_nodes)
1523 float height = std::numeric_limits<float>::min();
1524 for (
int i = 0; i < ar_num_nodes; i++)
1526 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1528 height = std::max(height, ar_nodes[i].AbsPosition.y);
1531 return (!skip_virtual_nodes || height > std::numeric_limits<float>::min()) ? height : getMaxHeight(
false);
1534 float Actor::getHeightAboveGround(
bool skip_virtual_nodes)
1536 float agl = std::numeric_limits<float>::max();
1537 for (
int i = 0; i < ar_num_nodes; i++)
1539 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1541 Vector3 pos = ar_nodes[i].AbsPosition;
1545 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGround(
false);
1548 float Actor::getHeightAboveGroundBelow(
float height,
bool skip_virtual_nodes)
1550 float agl = std::numeric_limits<float>::max();
1551 for (
int i = 0; i < ar_num_nodes; i++)
1553 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1555 Vector3 pos = ar_nodes[i].AbsPosition;
1559 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGroundBelow(height,
false);
1562 void Actor::reset(
bool keep_position)
1564 if (ar_state == ActorState::DISPOSED)
1569 rq->
amr_type = (keep_position) ? ActorModifyRequest::Type::RESET_ON_SPOT : ActorModifyRequest::Type::RESET_ON_INIT_POS;
1573 void Actor::SoftReset()
1577 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1581 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1586 Vector3 translation = -agl * Vector3::UNIT_Y;
1587 this->resetPosition(ar_nodes[0].AbsPosition + translation,
false);
1588 for (
ActorPtr& actor : ar_linked_actors)
1590 actor->resetPosition(actor->ar_nodes[0].AbsPosition + translation,
false);
1594 m_ongoing_reset =
true;
1597 void Actor::SyncReset(
bool reset_position)
1601 m_reset_timer.reset();
1603 m_camera_local_gforces_cur = Vector3::ZERO;
1604 m_camera_local_gforces_max = Vector3::ZERO;
1606 ar_hydro_dir_state = 0.0;
1607 ar_hydro_aileron_state = 0.0;
1608 ar_hydro_rudder_state = 0.0;
1609 ar_hydro_elevator_state = 0.0;
1610 ar_hydro_dir_wheel_display = 0.0;
1612 ar_fusedrag = Vector3::ZERO;
1614 ar_parking_brake =
false;
1615 ar_trailer_parking_brake =
false;
1616 ar_avg_wheel_speed = 0.0f;
1617 ar_wheel_speed = 0.0f;
1618 ar_wheel_spin = 0.0f;
1621 ar_origin = Vector3::ZERO;
1622 float cur_rot = getRotation();
1623 Vector3 cur_position = ar_nodes[0].AbsPosition;
1625 this->DisjoinInterActorBeams();
1627 for (
int i = 0; i < ar_num_nodes; i++)
1629 ar_nodes[i].AbsPosition = ar_initial_node_positions[i];
1630 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1631 ar_nodes[i].Velocity = Vector3::ZERO;
1632 ar_nodes[i].Forces = Vector3::ZERO;
1635 for (
int i = 0; i < ar_num_beams; i++)
1637 ar_beams[i].maxposstress = ar_beams[i].default_beam_deform;
1638 ar_beams[i].maxnegstress = -ar_beams[i].default_beam_deform;
1639 ar_beams[i].minmaxposnegstress = ar_beams[i].default_beam_deform;
1640 ar_beams[i].strength = ar_beams[i].initial_beam_strength;
1641 ar_beams[i].L = ar_beams[i].refL;
1642 ar_beams[i].stress = 0.0;
1643 ar_beams[i].bm_broken =
false;
1644 ar_beams[i].bm_disabled =
false;
1647 this->applyNodeBeamScales();
1651 for (
auto& h : ar_hooks)
1653 h.hk_beam->bm_disabled =
true;
1656 for (
auto& t : ar_ties)
1658 t.ti_locked_ropable =
nullptr;
1659 t.ti_beam->bm_disabled =
true;
1664 for (
auto& r : ar_ropables)
1666 r.attached_ties = 0;
1667 r.attached_ropes = 0;
1670 for (
int i = 0; i < ar_num_wheels; i++)
1672 ar_wheels[i].wh_speed = 0.0;
1673 ar_wheels[i].wh_torque = 0.0;
1674 ar_wheels[i].wh_avg_speed = 0.0;
1675 ar_wheels[i].wh_is_detached =
false;
1682 ar_engine->StartEngine();
1684 ar_engine->SetWheelSpin(0.0f);
1687 int num_axle_diffs = (m_transfer_case && m_transfer_case->tr_4wd_mode) ? m_num_axle_diffs + 1 : m_num_axle_diffs;
1688 for (
int i = 0; i < num_axle_diffs; i++)
1689 m_axle_diffs[i]->di_delta_rotation = 0.0f;
1690 for (
int i = 0; i < m_num_wheel_diffs; i++)
1691 m_wheel_diffs[i]->di_delta_rotation = 0.0f;
1692 for (
int i = 0; i < ar_num_aeroengines; i++)
1693 ar_aeroengines[i]->reset();
1694 for (
int i = 0; i < ar_num_screwprops; i++)
1695 ar_screwprops[i]->reset();
1696 for (
int i = 0; i < ar_num_rotators; i++)
1697 ar_rotators[i].angle = 0.0;
1698 for (
int i = 0; i < ar_num_wings; i++)
1699 ar_wings[i].fa->broken =
false;
1701 this->ar_autopilot->reset();
1703 m_buoyance->sink =
false;
1707 hydrobeam.hb_inertia.ResetCmdKeyDelay();
1710 this->GetGfxActor()->ResetFlexbodies();
1713 if (!reset_position)
1715 this->ResetAngle(cur_rot);
1716 this->resetPosition(cur_position,
false);
1717 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1720 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1724 this->resetPosition(ar_nodes[0].AbsPosition - agl * Vector3::UNIT_Y,
false);
1729 this->UpdateBoundingBoxes();
1730 this->calculateAveragePosition();
1735 ar_command_key[i].commandValue = 0.0;
1736 ar_command_key[i].triggerInputValue = 0.0f;
1737 ar_command_key[i].playerInputValue = 0.0f;
1738 for (
auto& b : ar_command_key[i].beams)
1740 b.cmb_state->auto_moving_mode = 0;
1741 b.cmb_state->pressed_center_mode =
false;
1745 this->resetSlideNodes();
1746 if (m_slidenodes_locked)
1748 this->toggleSlideNodeLock();
1751 m_ongoing_reset =
true;
1754 void Actor::applyNodeBeamScales()
1756 for (
int i = 0; i < ar_num_nodes; i++)
1758 ar_nodes[i].mass = ar_initial_node_masses[i] * ar_nb_mass_scale;
1761 m_total_mass = ar_initial_total_mass * ar_nb_mass_scale;
1763 for (
int i = 0; i < ar_num_beams; i++)
1765 if ((ar_beams[i].p1->nd_tyre_node || ar_beams[i].p1->nd_rim_node) ||
1766 (ar_beams[i].p2->nd_tyre_node || ar_beams[i].p2->nd_rim_node))
1768 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_wheels_scale.first;
1769 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_wheels_scale.second;
1771 else if (ar_beams[i].bounded ==
SHOCK1 || ar_beams[i].bounded ==
SHOCK2 || ar_beams[i].bounded ==
SHOCK3)
1773 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_shocks_scale.first;;
1774 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_shocks_scale.second;
1778 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_beams_scale.first;
1779 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_beams_scale.second;
1784 void Actor::ForceFeedbackStep(
int steps)
1786 m_force_sensors.out_body_forces = m_force_sensors.accu_body_forces / steps;
1787 if (!ar_hydros.empty())
1789 m_force_sensors.out_hydros_forces = (m_force_sensors.accu_hydros_forces / steps) / ar_hydros.size();
1793 void Actor::HandleAngelScriptEvents(
float dt)
1795 #ifdef USE_ANGELSCRIPT
1797 if (m_water_contact && !m_water_contact_old)
1799 m_water_contact_old = m_water_contact;
1802 #endif // USE_ANGELSCRIPT
1805 void Actor::searchBeamDefaults()
1809 auto old_beams_scale = ar_nb_beams_scale;
1810 auto old_shocks_scale = ar_nb_shocks_scale;
1811 auto old_wheels_scale = ar_nb_wheels_scale;
1813 if (ar_nb_initialized)
1815 ar_nb_beams_scale.first = Math::RangeRandom(ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1816 ar_nb_beams_scale.second = Math::RangeRandom(ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1817 ar_nb_shocks_scale.first = Math::RangeRandom(ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1818 ar_nb_shocks_scale.second = Math::RangeRandom(ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1819 ar_nb_wheels_scale.first = Math::RangeRandom(ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1820 ar_nb_wheels_scale.second = Math::RangeRandom(ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1824 ar_nb_beams_scale.first = Math::Clamp(1.0f, ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1825 ar_nb_beams_scale.second = Math::Clamp(1.0f, ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1826 ar_nb_shocks_scale.first = Math::Clamp(1.0f, ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1827 ar_nb_shocks_scale.second = Math::Clamp(1.0f, ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1828 ar_nb_wheels_scale.first = Math::Clamp(1.0f, ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1829 ar_nb_wheels_scale.second = Math::Clamp(1.0f, ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1830 ar_nb_reference = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1831 ar_nb_optimum = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1834 this->applyNodeBeamScales();
1836 m_ongoing_reset =
false;
1837 this->CalcForcesEulerPrepare(
true);
1838 for (
int i = 0; i < ar_nb_skip_steps; i++)
1840 this->CalcForcesEulerCompute(i == 0, ar_nb_skip_steps);
1841 if (m_ongoing_reset)
1844 m_ongoing_reset =
true;
1846 float sum_movement = 0.0f;
1847 float movement = 0.0f;
1848 float sum_velocity = 0.0f;
1849 float velocity = 0.0f;
1850 float sum_stress = 0.0f;
1851 float stress = 0.0f;
1853 for (
int k = 0; k < ar_nb_measure_steps; k++)
1855 this->CalcForcesEulerCompute(
false, ar_nb_measure_steps);
1856 for (
int i = 0; i < ar_num_nodes; i++)
1858 float v = ar_nodes[i].Velocity.length();
1859 sum_movement += v / (float)ar_nb_measure_steps;
1860 movement = std::max(movement, v);
1862 for (
int i = 0; i < ar_num_beams; i++)
1864 Vector3 dis = (ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition).normalisedCopy();
1865 float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis);
1866 sum_velocity += std::abs(v) / (float)ar_nb_measure_steps;
1867 velocity = std::max(velocity, std::abs(v));
1868 sum_stress += std::abs(ar_beams[i].stress) / (float)ar_nb_measure_steps;
1869 stress = std::max(stress, std::abs(ar_beams[i].stress));
1870 if (k == 0 && ar_beams[i].bm_broken)
1875 if (sum_broken > ar_nb_reference[6] ||
1876 stress > ar_nb_reference[0] || velocity > ar_nb_reference[2] || movement > ar_nb_optimum[4] ||
1877 sum_stress > ar_nb_reference[1] || sum_velocity > ar_nb_reference[3] || sum_movement > ar_nb_optimum[5] * 2.f)
1879 ar_nb_beams_scale = old_beams_scale;
1880 ar_nb_shocks_scale = old_shocks_scale;
1881 ar_nb_wheels_scale = old_wheels_scale;
1888 ar_nb_optimum = {stress, sum_stress, velocity, sum_velocity, movement, sum_movement, (float)sum_broken};
1889 if (!ar_nb_initialized)
1891 ar_nb_reference = ar_nb_optimum;
1893 ar_nb_initialized =
true;
1896 void Actor::HandleInputEvents(
float dt)
1898 if (!m_ongoing_reset)
1901 if (m_anglesnap_request > 0)
1903 float rotation = Radian(getRotation()).valueDegrees();
1904 float target_rotation = std::round(rotation / m_anglesnap_request) * m_anglesnap_request;
1905 m_rotation_request = -Degree(target_rotation - rotation).valueRadians();
1906 m_rotation_request_center = getRotationCenter();
1907 m_anglesnap_request = 0;
1910 if (m_rotation_request != 0.0f)
1912 Quaternion rot = Quaternion(Radian(m_rotation_request), Vector3::UNIT_Y);
1914 for (
int i = 0; i < ar_num_nodes; i++)
1916 ar_nodes[i].AbsPosition -= m_rotation_request_center;
1917 ar_nodes[i].AbsPosition = rot * ar_nodes[i].AbsPosition;
1918 ar_nodes[i].AbsPosition += m_rotation_request_center;
1919 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1920 ar_nodes[i].Velocity = rot * ar_nodes[i].Velocity;
1921 ar_nodes[i].Forces = rot * ar_nodes[i].Forces;
1924 m_rotation_request = 0.0f;
1925 this->UpdateBoundingBoxes();
1926 calculateAveragePosition();
1929 if (m_translation_request != Vector3::ZERO)
1931 for (
int i = 0; i < ar_num_nodes; i++)
1933 ar_nodes[i].AbsPosition += m_translation_request;
1934 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1937 m_translation_request = Vector3::ZERO;
1938 UpdateBoundingBoxes();
1939 calculateAveragePosition();
1943 void Actor::sendStreamSetup()
1954 Ogre::StringUtil::splitFilename(m_used_actor_entry->resource_bundle_path, bname, bpath);
1955 std::string bq_filename =
fmt::format(
"{}:{}", bname, ar_filename);
1956 strncpy(reg.
name, bq_filename.c_str(), 128);
1959 if (m_used_skin_entry !=
nullptr)
1961 strncpy(reg.
skin, m_used_skin_entry->dname.c_str(), 60);
1967 #endif // USE_SOCKETW
1973 void Actor::sendStreamData()
1977 if (ar_net_timer.getMilliseconds() - ar_net_last_update_time < 100)
1980 ar_net_last_update_time = ar_net_timer.getMilliseconds();
1991 unsigned int packet_len = 0;
2008 if (ar_engine->hasContact())
2010 if (ar_engine->isRunning())
2013 switch (ar_engine->GetAutoShiftMode())
2027 if (ar_num_aeroengines > 0)
2029 float rpm = ar_aeroengines[0]->getRPM();
2034 send_oob->
brake = ar_brake;
2039 if (getCustomParticleMode())
2042 if (ar_parking_brake)
2044 if (m_tractioncontrol)
2046 if (m_antilockbrake)
2060 float* send_nodes = (
float *)ptr;
2061 packet_len += m_net_total_buffer_size;
2067 Vector3& refpos = ar_nodes[0].AbsPosition;
2068 send_nodes[0] = refpos.x;
2069 send_nodes[1] = refpos.y;
2070 send_nodes[2] = refpos.z;
2072 ptr +=
sizeof(float) * 3;
2075 half_float::half* sbuf = (half_float::half*)ptr;
2076 for (i = 1; i < m_net_first_wheel_node; i++)
2078 Ogre::Vector3 relpos = ar_nodes[i].AbsPosition - ar_nodes[0].AbsPosition;
2079 sbuf[(i-1) * 3 + 0] =
static_cast<half_float::half
>(relpos.x);
2080 sbuf[(i-1) * 3 + 1] =
static_cast<half_float::half
>(relpos.y);
2081 sbuf[(i-1) * 3 + 2] =
static_cast<half_float::half
>(relpos.z);
2083 ptr +=
sizeof(half_float::half) * 3;
2087 float* wfbuf = (
float*)ptr;
2088 for (i = 0; i < ar_num_wheels; i++)
2090 wfbuf[i] = ar_wheels[i].wh_net_rp;
2092 ptr += ar_num_wheels *
sizeof(float);
2095 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
2097 if (m_prop_anim_key_states[i].anim_active)
2100 char& dst_byte = *(ptr + (i / 8));
2101 char mask = ((char)m_prop_anim_key_states[i].anim_active) << (7 - (i % 8));
2111 void Actor::CalcAnimators(
hydrobeam_t const& hydrobeam,
float &cstate,
int &div)
2118 for (spi = 0; spi < ar_num_screwprops; spi++)
2119 if (ar_screwprops[spi])
2120 ctmp += ar_screwprops[spi]->getRudder();
2133 for (spi = 0; spi < ar_num_screwprops; spi++)
2134 if (ar_screwprops[spi])
2135 ctmp += ar_screwprops[spi]->getThrottle();
2146 if (m_num_wheel_diffs && m_wheel_diffs[0])
2148 String name = m_wheel_diffs[0]->GetDifferentialTypeName();
2151 if (name ==
"Split")
2153 if (name ==
"Locked")
2165 float heading = getRotation();
2167 cstate = (heading * 57.29578f) / 360.0f;
2174 float torque = ar_engine->GetCrankFactor();
2177 if (torque >= ar_anim_previous_crank)
2178 cstate -= torque / 10.0f;
2182 if (cstate <= -1.0f)
2184 ar_anim_previous_crank = torque;
2192 int shifter = ar_engine->GetGear();
2193 if (shifter > m_previous_gear)
2196 ar_anim_shift_timer = 0.2f;
2198 if (shifter < m_previous_gear)
2201 ar_anim_shift_timer = -0.2f;
2203 m_previous_gear = shifter;
2205 if (ar_anim_shift_timer > 0.0f)
2209 if (ar_anim_shift_timer < 0.0f)
2210 ar_anim_shift_timer = 0.0f;
2212 if (ar_anim_shift_timer < 0.0f)
2216 if (ar_anim_shift_timer > 0.0f)
2217 ar_anim_shift_timer = 0.0f;
2226 int shifter = ar_engine->GetGear();
2231 else if (shifter < 0)
2237 cstate -= int((shifter - 1.0) / 2.0);
2245 int shifter = ar_engine->GetGear();
2253 cstate = shifter % 2;
2261 int shifter = ar_engine->GetGear();
2262 int numgears = ar_engine->getNumGears();
2263 cstate -= (shifter + 2.0) / (numgears + 2.0);
2270 float pbrake = ar_parking_brake;
2278 float speedo = ar_wheel_speed / ar_guisettings_speedo_max_kph;
2279 cstate -= speedo * 3.0f;
2286 float tacho = ar_engine->GetEngineRpm() / ar_engine->getMaxRPM();
2294 float turbo = ar_engine->GetTurboPsi() * 3.34;
2295 cstate -= turbo / 67.0f;
2309 float accel = ar_engine->GetAcceleration();
2310 cstate -= accel + 0.06f;
2318 float clutch = ar_engine->GetClutch();
2319 cstate -= fabs(1.0f - clutch);
2330 float pcent = ar_aeroengines[aenum]->getRPMpc();
2332 angle = -5.0 + pcent * 1.9167;
2333 else if (pcent < 110.0)
2334 angle = 110.0 + (pcent - 60.0) * 4.075;
2337 cstate -= angle / 314.0f;
2342 float throttle = ar_aeroengines[aenum]->getThrottle();
2348 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2356 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2359 cstate = tp->
pitch / 120.0f;
2365 if (!ar_aeroengines[aenum]->getIgnition())
2369 if (ar_aeroengines[aenum]->isFailed())
2378 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438;
2379 float altitude = ar_nodes[0].AbsPosition.y;
2380 float sea_level_pressure = 101325;
2381 float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947);
2382 float airdensity = airpressure * 0.0000120896;
2383 float kt = ground_speed_kt * sqrt(airdensity / 1.225);
2384 cstate -= kt / 100.0f;
2391 float vvi = ar_nodes[0].Velocity.y * 196.85;
2393 cstate -= vvi / 6000.0f;
2396 if (cstate <= -1.0f)
2407 float altimeter = (ar_nodes[0].AbsPosition.y * 1.1811) / 360.0f;
2408 int alti_int = int(altimeter);
2409 float alti_mod = (altimeter - alti_int);
2416 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 3600.0f;
2417 int alti_int = int(alti);
2418 float alti_mod = (alti - alti_int);
2420 if (cstate <= -1.0f)
2427 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 36000.0f;
2429 if (cstate <= -1.0f)
2439 if (ar_num_wings > 4)
2440 aoa = (ar_wings[4].fa->aoa) / 25.0f;
2441 if ((ar_nodes[0].Velocity.length() * 1.9438) < 10.0f)
2444 if (cstate <= -1.0f)
2454 Vector3 rollv = this->GetCameraRoll();
2455 Vector3 dirv = this->GetCameraDir();
2456 Vector3 upv = dirv.crossProduct(-rollv);
2457 float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y));
2459 rollangle = Math::RadiansToDegrees(rollangle);
2462 rollangle = 180.0f - rollangle;
2463 cstate = rollangle / 180.0f;
2467 cstate = cstate - 2.0f;
2474 Vector3 dirv = this->GetCameraDir();
2475 float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y));
2477 cstate = (Math::RadiansToDegrees(pitchangle) / 90.0f);
2484 float airbrake = ar_airbrake_intensity;
2486 cstate -= airbrake / 5.0f;
2500 void Actor::CalcCabCollisions()
2502 for (
int i = 0; i < ar_num_nodes; i++)
2504 ar_nodes[i].nd_has_mesh_contact =
false;
2506 if (m_intra_point_col_detector !=
nullptr)
2508 m_intra_point_col_detector->UpdateIntraPoint();
2510 *m_intra_point_col_detector,
2514 ar_intra_collcabrate,
2517 *ar_submesh_ground_model);
2521 void Actor::CalcShocks2(
int i, Real difftoBeamL, Real& k, Real& d, Real v)
2525 k = ar_beams[i].shock->springout;
2526 d = ar_beams[i].shock->dampout;
2528 float logafactor = 1.0f;
2529 if (ar_beams[i].longbound != 0.0f)
2531 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2532 logafactor = std::min(logafactor * logafactor, 1.0f);
2534 k += ar_beams[i].shock->sprogout * k * logafactor;
2535 d += ar_beams[i].shock->dprogout * d * logafactor;
2539 k = ar_beams[i].shock->springin;
2540 d = ar_beams[i].shock->dampin;
2542 float logafactor = 1.0f;
2543 if (ar_beams[i].shortbound != 0.0f)
2545 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2546 logafactor = std::min(logafactor * logafactor, 1.0f);
2548 k += ar_beams[i].shock->sprogin * k * logafactor;
2549 d += ar_beams[i].shock->dprogin * d * logafactor;
2554 float beamsLep = ar_beams[i].L * 0.8f;
2555 float longboundprelimit = ar_beams[i].longbound * beamsLep;
2556 float shortboundprelimit = -ar_beams[i].shortbound * beamsLep;
2557 if (difftoBeamL > longboundprelimit)
2560 k = ar_beams[i].shock->springout;
2561 d = ar_beams[i].shock->dampout;
2563 float logafactor = 1.0f;
2564 if (ar_beams[i].longbound != 0.0f)
2566 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2567 logafactor = std::min(logafactor * logafactor, 1.0f);
2569 k += ar_beams[i].shock->sprogout * k * logafactor;
2570 d += ar_beams[i].shock->dprogout * d * logafactor;
2573 if (ar_beams[i].longbound != 0.0f)
2575 logafactor = ((difftoBeamL - longboundprelimit) * 5.0f) / (ar_beams[i].longbound * ar_beams[i].L);
2576 logafactor = std::min(logafactor * logafactor, 1.0f);
2578 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2579 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2583 k = ar_beams[i].shock->springin;
2584 d = ar_beams[i].shock->dampin;
2587 else if (difftoBeamL < shortboundprelimit)
2590 k = ar_beams[i].shock->springin;
2591 d = ar_beams[i].shock->dampin;
2593 float logafactor = 1.0f;
2594 if (ar_beams[i].shortbound != 0.0f)
2596 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2597 logafactor = std::min(logafactor * logafactor, 1.0f);
2599 k += ar_beams[i].shock->sprogin * k * logafactor;
2600 d += ar_beams[i].shock->dprogin * d * logafactor;
2603 if (ar_beams[i].shortbound != 0.0f)
2605 logafactor = ((difftoBeamL - shortboundprelimit) * 5.0f) / (ar_beams[i].shortbound * ar_beams[i].L);
2606 logafactor = std::min(logafactor * logafactor, 1.0f);
2608 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2609 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2613 k = ar_beams[i].shock->springout;
2614 d = ar_beams[i].shock->dampout;
2617 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2620 k = std::max(k, ar_beams[i].shock->sbd_spring);
2621 d = std::max(d, ar_beams[i].shock->sbd_damp);
2624 else if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2627 k = ar_beams[i].shock->sbd_spring;
2628 d = ar_beams[i].shock->sbd_damp;
2632 void Actor::CalcShocks3(
int i, Real difftoBeamL, Real &k, Real& d, Real v)
2634 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2636 float interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L;
2637 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2638 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2640 else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2642 float interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L;
2643 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2644 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2648 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2649 k = ar_beams[i].shock->springout;
2650 d = ar_beams[i].shock->dampout * ar_beams[i].shock->dslowout * std::min(v, ar_beams[i].shock->splitout) +
2651 ar_beams[i].shock->dampout * ar_beams[i].shock->dfastout * std::max(0.0f, v - ar_beams[i].shock->splitout);
2656 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2657 k = ar_beams[i].shock->springin;
2658 d = ar_beams[i].shock->dampin * ar_beams[i].shock->dslowin * std::min(v, ar_beams[i].shock->splitin ) +
2659 ar_beams[i].shock->dampin * ar_beams[i].shock->dfastin * std::max(0.0f, v - ar_beams[i].shock->splitin );
2664 void Actor::CalcTriggers(
int i, Real difftoBeamL,
bool trigger_hooks)
2670 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2672 ar_beams[i].shock->trigger_switch_state -= dt;
2673 if (ar_beams[i].shock->trigger_switch_state <= 0.0f)
2674 ar_beams[i].shock->trigger_switch_state = 0.0f;
2677 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2681 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 1)
2683 LOG(
" Trigger disabled. Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2684 ar_beams[i].shock->last_debug_state = 1;
2686 ar_beams[scount].shock->trigger_enabled =
false;
2692 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2696 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 9)
2698 LOG(
" Trigger enabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2699 ar_beams[i].shock->last_debug_state = 9;
2701 ar_beams[scount].shock->trigger_enabled =
true;
2707 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
false;
2708 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 2)
2710 LOG(
" F-key trigger block released. Blocker BeamID " +
TOSTRING(i) +
" Released F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2711 ar_beams[i].shock->last_debug_state = 2;
2716 if (!ar_beams[i].shock->trigger_switch_state)
2718 for (
int scount = 0; scount < ar_num_shocks; scount++)
2720 int short1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2721 int short2 = ar_beams[i].shock->trigger_cmdshort;
2722 int long1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2723 int long2 = ar_beams[i].shock->trigger_cmdlong;
2724 int tmpi = ar_beams[ar_shocks[scount].beamid].shock->beamid;
2725 if (((short1 == short2 && long1 == long2) || (short1 == long2 && long1 == short2)) && i != tmpi)
2727 int tmpcmdkey = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2728 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2729 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort = tmpcmdkey;
2730 ar_beams[i].shock->trigger_switch_state = ar_beams[i].shock->trigger_boundary_t;
2731 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 3)
2733 LOG(
" Trigger F-key commands switched. Switch BeamID " +
TOSTRING(i)+
" switched commands of Trigger BeamID " +
TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->beamid) +
" to cmdShort: F" +
TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort) +
", cmdlong: F" +
TOSTRING(ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong));
2734 ar_beams[i].shock->last_debug_state = 3;
2742 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2751 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2764 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2772 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), 1.0f);
2777 if (!ar_command_key[ar_beams[i].shock->trigger_cmdlong].trigger_cmdkeyblock_state)
2780 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2782 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = 1;
2783 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 4)
2785 LOG(
" Trigger Longbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdlong));
2786 ar_beams[i].shock->last_debug_state = 4;
2800 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2813 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2823 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2828 if (!ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2831 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 0;
2833 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2835 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 5)
2837 LOG(
" Trigger Shortbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2838 ar_beams[i].shock->last_debug_state = 5;
2849 if (ar_beams[i].longbound - ar_beams[i].shortbound > 0.0f)
2851 float diffPercentage = difftoBeamL / ar_beams[i].L;
2852 float triggerValue = (diffPercentage - ar_beams[i].shortbound) / (ar_beams[i].longbound - ar_beams[i].shortbound);
2854 triggerValue = std::max(0.0f, triggerValue);
2855 triggerValue = std::min(triggerValue, 1.0f);
2859 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2864 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = triggerValue;
2865 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = triggerValue;
2871 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2875 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 6)
2877 LOG(
" Trigger enabled. Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2878 ar_beams[i].shock->last_debug_state = 6;
2880 ar_beams[scount].shock->trigger_enabled =
true;
2886 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2890 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 10)
2892 LOG(
" Trigger disabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2893 ar_beams[i].shock->last_debug_state = 10;
2895 ar_beams[scount].shock->trigger_enabled =
false;
2901 ar_beams[i].shock->trigger_switch_state = 0.0f;
2902 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 7)
2904 LOG(
" Trigger switch reset. Switch BeamID " +
TOSTRING(i));
2905 ar_beams[i].shock->last_debug_state = 7;
2908 else if ((ar_beams[i].shock->flags &
SHOCK_FLAG_TRG_CMD_BLOCKER) && !ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2910 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
true;
2911 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 8)
2913 LOG(
" F-key trigger blocked. Blocker BeamID " +
TOSTRING(i) +
" Blocked F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2914 ar_beams[i].shock->last_debug_state = 8;
2921 void Actor::setAirbrakeIntensity(
float intensity)
2923 ar_airbrake_intensity = intensity;
2926 ab->updatePosition((
float)ar_airbrake_intensity / 5.0);
2931 void Actor::updateSkidmarks()
2933 for (
int i = 0; i < ar_num_wheels; i++)
2935 if (!m_skid_trails[i])
2938 for (
int j = 0; j < ar_wheels[i].wh_num_nodes; j++)
2940 auto n = ar_wheels[i].wh_nodes[j];
2941 if (!n || !n->nd_has_ground_contact || n->nd_last_collision_gm ==
nullptr ||
2942 n->nd_last_collision_gm->fx_type != Collisions::FX_HARD)
2946 if (n->nd_avg_collision_slip > 6.f && n->nd_last_collision_slip.squaredLength() > 9.f)
2948 m_skid_trails[i]->update(n->AbsPosition, j, n->nd_avg_collision_slip, n->nd_last_collision_gm->name);
2955 void Actor::prepareInside(
bool inside)
2963 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2964 seatmat->setDepthWriteEnabled(
false);
2965 seatmat->setSceneBlending(SBT_TRANSPARENT_ALPHA);
2971 ar_dashboard->setVisible(
false);
2977 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2978 seatmat->setDepthWriteEnabled(
true);
2979 seatmat->setSceneBlending(SBT_REPLACE);
2990 m_gfx_actor->SetCastShadows(!inside);
2994 void Actor::toggleHeadlights()
2998 if (ar_state == ActorState::LOCAL_SIMULATED &&
this == player_actor.
GetRef() && ar_forward_commands)
3002 if (actor->ar_state == ActorState::LOCAL_SIMULATED &&
this != actor.GetRef() && actor->ar_import_commands)
3011 m_gfx_actor->SetCabLightsActive(this->getHeadlightsVisible());
3016 void Actor::forceAllFlaresOff()
3018 for (
size_t i = 0; i < ar_flares.size(); i++)
3020 ar_flares[i].snode->setVisible(
false);
3024 void Actor::updateFlareStates(
float dt)
3026 if (m_flares_mode == GfxFlaresMode::NONE) {
return; }
3028 for (
size_t i = 0; i < this->ar_flares.size(); i++)
3031 if (ar_flares[i].blinkdelay != 0)
3033 ar_flares[i].blinkdelay_curr -= dt;
3034 if (ar_flares[i].blinkdelay_curr <= 0)
3036 ar_flares[i].blinkdelay_curr = ar_flares[i].blinkdelay;
3037 ar_flares[i].blinkdelay_state = !ar_flares[i].blinkdelay_state;
3042 ar_flares[i].blinkdelay_state =
true;
3046 bool isvisible =
false;
3047 switch (ar_flares[i].fl_type)
3058 case FlareType::DASHBOARD: isvisible = ar_dashboard->_getBool(ar_flares[i].dashboard_link);
break;
3059 case FlareType::USER: isvisible = this->getCustomLightVisible(ar_flares[i].controlnumber);
break;
3063 isvisible = isvisible && ar_flares[i].blinkdelay_state;
3066 switch (ar_flares[i].fl_type)
3068 case FlareType::BLINKER_LEFT: m_blinker_left_lit = isvisible;
break;
3069 case FlareType::BLINKER_RIGHT: m_blinker_right_lit = isvisible;
break;
3074 if (ar_flares[i].uses_inertia)
3076 ar_flares[i].intensity = ar_flares[i].inertia.CalcSimpleDelay(isvisible, dt);
3080 ar_flares[i].intensity = (float)isvisible;
3087 if (this->getBlinkType() == blink)
3090 setBlinkType(blink);
3095 if (ar_state == ActorState::DISPOSED)
3127 void Actor::autoBlinkReset()
3132 if (this->getBlinkType() ==
BLINK_LEFT && ar_hydro_dir_state < -blink_lock_range)
3135 m_blinker_autoreset =
true;
3138 if (this->getBlinkType() ==
BLINK_LEFT && m_blinker_autoreset && ar_hydro_dir_state > -blink_lock_range)
3142 m_blinker_autoreset =
false;
3146 if (this->getBlinkType() ==
BLINK_RIGHT && ar_hydro_dir_state > blink_lock_range)
3147 m_blinker_autoreset =
true;
3149 if (this->getBlinkType() ==
BLINK_RIGHT && m_blinker_autoreset && ar_hydro_dir_state < blink_lock_range)
3152 m_blinker_autoreset =
false;
3162 this->toggleHeadlights();
3164 this->beaconsToggle();
3173 this->setBlinkType(btype);
3176 m_lightmask = lightmask;
3179 void Actor::toggleCustomParticles()
3181 if (ar_state == ActorState::DISPOSED)
3184 m_custom_particles_enabled = !m_custom_particles_enabled;
3185 for (
int i = 0; i < ar_num_custom_particles; i++)
3187 ar_custom_particles[i].active = !ar_custom_particles[i].active;
3188 for (
int j = 0; j < ar_custom_particles[i].psys->getNumEmitters(); j++)
3190 ar_custom_particles[i].psys->getEmitter(j)->setEnabled(ar_custom_particles[i].active);
3198 void Actor::updateSoundSources()
3203 for (
int i = 0; i < ar_num_soundsources; i++)
3206 ar_soundsources[i].ssi->setPosition(ar_nodes[ar_soundsources[i].nodenum].AbsPosition);
3207 ar_soundsources[i].ssi->setVelocity(ar_nodes[ar_soundsources[i].nodenum].Velocity);
3215 void Actor::updateVisual(
float dt)
3217 Vector3 ref(Vector3::UNIT_Y);
3219 updateSoundSources();
3223 if (ar_driveable ==
AIRPLANE && ar_state != ActorState::LOCAL_SLEEPING)
3226 m_avionic_chatter_timer -= dt;
3227 if (m_avionic_chatter_timer < 0)
3230 m_avionic_chatter_timer = Math::RangeRandom(11, 30);
3237 if (ar_engine && exhausts.size() > 0)
3239 std::vector<exhaust_t>::iterator it;
3240 for (it = exhausts.begin(); it != exhausts.end(); it++)
3244 Vector3 dir = ar_nodes[it->emitterNode].AbsPosition - ar_nodes[it->directionNode].AbsPosition;
3246 ParticleEmitter* emit = it->smoker->getEmitter(0);
3247 it->smokeNode->setPosition(ar_nodes[it->emitterNode].AbsPosition);
3248 emit->setDirection(dir);
3249 if (!m_disable_smoke && ar_engine->GetSmoke() != -1.0)
3251 emit->setEnabled(
true);
3252 emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.02 + ar_engine->GetSmoke() * 0.06));
3253 emit->setTimeToLive((0.02 + ar_engine->GetSmoke() * 0.06) / 0.04);
3257 emit->setEnabled(
false);
3259 emit->setParticleVelocity(1.0 + ar_engine->GetSmoke() * 2.0, 2.0 + ar_engine->GetSmoke() * 3.0);
3264 float autoaileron = 0;
3265 float autorudder = 0;
3266 float autoelevator = 0;
3269 ar_autopilot->UpdateIls(
App::GetGameContext()->GetTerrain()->getObjectManager()->GetLocalizers());
3270 autoaileron = ar_autopilot->getAilerons();
3271 autorudder = ar_autopilot->getRudder();
3272 autoelevator = ar_autopilot->getElevator();
3273 ar_autopilot->gpws_update(ar_posnode_spawn_height);
3275 autoaileron += ar_aileron;
3276 autorudder += ar_rudder;
3277 autoelevator += ar_elevator;
3278 if (autoaileron < -1.0)
3280 if (autoaileron > 1.0)
3282 if (autorudder < -1.0)
3284 if (autorudder > 1.0)
3286 if (autoelevator < -1.0)
3287 autoelevator = -1.0;
3288 if (autoelevator > 1.0)
3290 for (
int i = 0; i < ar_num_wings; i++)
3292 if (ar_wings[i].fa->type ==
'a')
3293 ar_wings[i].fa->setControlDeflection(autoaileron);
3294 if (ar_wings[i].fa->type ==
'b')
3295 ar_wings[i].fa->setControlDeflection(-autoaileron);
3296 if (ar_wings[i].fa->type ==
'r')
3297 ar_wings[i].fa->setControlDeflection(autorudder);
3298 if (ar_wings[i].fa->type ==
'e' || ar_wings[i].fa->type ==
'S' || ar_wings[i].fa->type ==
'T')
3299 ar_wings[i].fa->setControlDeflection(autoelevator);
3300 if (ar_wings[i].fa->type ==
'f')
3301 ar_wings[i].fa->setControlDeflection(
FLAP_ANGLES[ar_aerial_flap]);
3302 if (ar_wings[i].fa->type ==
'c' || ar_wings[i].fa->type ==
'V')
3303 ar_wings[i].fa->setControlDeflection((autoaileron + autoelevator) / 2.0);
3304 if (ar_wings[i].fa->type ==
'd' || ar_wings[i].fa->type ==
'U')
3305 ar_wings[i].fa->setControlDeflection((-autoaileron + autoelevator) / 2.0);
3306 if (ar_wings[i].fa->type ==
'g')
3307 ar_wings[i].fa->setControlDeflection((autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3308 if (ar_wings[i].fa->type ==
'h')
3309 ar_wings[i].fa->setControlDeflection((-autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3310 if (ar_wings[i].fa->type ==
'i')
3311 ar_wings[i].fa->setControlDeflection((-autoelevator + autorudder) / 2.0);
3312 if (ar_wings[i].fa->type ==
'j')
3313 ar_wings[i].fa->setControlDeflection((autoelevator + autorudder) / 2.0);
3314 ar_wings[i].fa->updateVerticesPhysics();
3317 ar_hydro_aileron_command = autoaileron;
3318 ar_hydro_rudder_command = autorudder;
3319 ar_hydro_elevator_command = autoelevator;
3327 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3329 if (pos == ar_inter_beams.end())
3331 ar_inter_beams.push_back(beam);
3336 std::pair<ActorPtr, ActorPtr> actor_pair(
this, other);
3340 if (linked_before != linked_now)
3343 this->DetermineLinkedActors();
3344 for (
ActorPtr& actor : this->ar_linked_actors)
3345 actor->DetermineLinkedActors();
3352 for (
ActorPtr& actor : this->ar_linked_actors)
3369 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3371 if (pos != ar_inter_beams.end())
3373 ar_inter_beams.erase(pos);
3385 if (linked_before != linked_now)
3388 this->DetermineLinkedActors();
3389 for (
ActorPtr& actor : this->ar_linked_actors)
3390 actor->DetermineLinkedActors();
3410 void Actor::DisjoinInterActorBeams()
3418 this->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET);
3419 this->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET);
3420 this->tieToggle(-1, ActorLinkingRequestType::TIE_RESET);
3425 if (other_actor->ar_state != ActorState::LOCAL_SIMULATED)
3429 other_actor->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET,
NODENUM_INVALID, ar_instance_id);
3430 other_actor->tieToggle(-1, ActorLinkingRequestType::TIE_RESET, ar_instance_id);
3431 other_actor->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET, ar_instance_id);
3440 bool istied =
false;
3442 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3445 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3449 if (mode == ActorLinkingRequestType::TIE_RESET
3450 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->ti_locked_actor && it->ti_locked_actor->ar_instance_id != forceunlock_filter)
3458 istied = !it->ti_beam->bm_disabled;
3461 it->ti_tied =
false;
3462 it->ti_tying =
false;
3463 if (it->ti_locked_ropable)
3464 it->ti_locked_ropable->attached_ties--;
3466 it->ti_beam->p2 = &ar_nodes[0];
3467 it->ti_beam->bm_inter_actor =
false;
3468 it->ti_beam->bm_disabled =
true;
3469 if (it->ti_locked_actor !=
this)
3471 this->RemoveInterActorBeam(it->ti_beam, mode);
3473 it->ti_locked_actor =
nullptr;
3478 if (!istied && mode == ActorLinkingRequestType::TIE_TOGGLE)
3480 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3483 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3489 float mindist = it->ti_beam->refL;
3490 node_t* nearest_node = 0;
3496 if (actor->ar_state == ActorState::LOCAL_SLEEPING ||
3497 (actor ==
this && it->ti_no_self_lock))
3503 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3506 if (!itr->multilock && itr->attached_ties > 0)
3510 if (
this == actor.GetRef() && itr->node->pos == it->ti_beam->p1->pos)
3514 float dist = (it->ti_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3518 nearest_node = itr->node;
3519 nearest_actor = actor;
3520 locktedto = &(*itr);
3528 it->ti_beam->bm_disabled =
false;
3530 it->ti_locked_actor = nearest_actor;
3531 it->ti_beam->p2 = nearest_node;
3532 it->ti_beam->bm_inter_actor = nearest_actor !=
this;
3533 it->ti_beam->stress = 0;
3534 it->ti_beam->L = it->ti_beam->refL;
3536 it->ti_tying =
true;
3537 it->ti_locked_ropable = locktedto;
3539 if (it->ti_beam->bm_inter_actor)
3541 this->AddInterActorBeam(it->ti_beam, nearest_actor, mode);
3557 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
3560 if (group != -1 && (it->rp_group != -1 && it->rp_group != group))
3564 if (mode == ActorLinkingRequestType::ROPE_RESET
3565 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->rp_locked_actor && it->rp_locked_actor->ar_instance_id != forceunlock_filter)
3575 if (it->rp_locked_ropable)
3576 it->rp_locked_ropable->attached_ropes--;
3577 if (it->rp_locked_actor !=
this)
3579 this->RemoveInterActorBeam(it->rp_beam, mode);
3581 it->rp_locked_actor =
nullptr;
3582 it->rp_locked_ropable =
nullptr;
3584 else if (mode == ActorLinkingRequestType::ROPE_TOGGLE)
3588 float mindist = it->rp_beam->L;
3594 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3597 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3600 if (!itr->multilock && itr->attached_ropes > 0)
3604 float dist = (it->rp_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3608 nearest_actor = actor;
3618 it->rp_locked_ropable = rop;
3620 if (nearest_actor !=
this)
3622 this->AddInterActorBeam(it->rp_beam, nearest_actor, mode);
3631 ROR_ASSERT(mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK
3632 || mode == ActorLinkingRequestType::HOOK_TOGGLE || mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE
3633 || mode == ActorLinkingRequestType::HOOK_RESET);
3636 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3638 if (mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE && it->hk_hook_node->pos != mousenode)
3643 if (mode == ActorLinkingRequestType::HOOK_TOGGLE && group == -1)
3646 if (it->hk_group <= -2)
3649 if (mode == ActorLinkingRequestType::HOOK_LOCK && group == -2)
3652 if (it->hk_group >= -1 || !it->hk_autolock)
3655 if (mode == ActorLinkingRequestType::HOOK_UNLOCK && group == -2)
3658 if (it->hk_group >= -1 || !it->hk_autolock)
3661 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group <= -3)
3664 if (it->hk_group != group)
3667 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group >= -1)
3671 if (mode == ActorLinkingRequestType::HOOK_LOCK && it->hk_timer > 0.0f)
3678 if (mode == ActorLinkingRequestType::HOOK_RESET
3679 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->hk_locked_actor && it->hk_locked_actor->ar_instance_id != forceunlock_filter)
3684 ActorPtr prev_locked_actor = it->hk_locked_actor;
3687 if ((mode != ActorLinkingRequestType::HOOK_UNLOCK && mode != ActorLinkingRequestType::HOOK_RESET) && it->hk_locked ==
UNLOCKED)
3691 float mindist = it->hk_lockrange;
3692 float distance = 100000000.0f;
3696 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3698 if (
this == actor.GetRef() && !it->hk_selflock)
3701 node_t* nearest_node =
nullptr;
3702 for (
int i = 0; i < actor->ar_num_nodes; i++)
3705 if (actor->ar_nodes[i].nd_lockgroup == 9999)
3709 if (
this == actor.GetRef() && i == it->hk_hook_node->pos)
3713 if (it->hk_lockgroup != -1 && it->hk_lockgroup != actor->ar_nodes[i].nd_lockgroup)
3717 float n2n_distance = (it->hk_hook_node->AbsPosition - actor->ar_nodes[i].AbsPosition).length();
3718 if (n2n_distance < mindist)
3720 if (distance >= n2n_distance)
3723 distance = n2n_distance;
3724 nearest_node = &actor->ar_nodes[i];
3731 it->hk_lock_node = nearest_node;
3732 it->hk_locked_actor = actor;
3735 if (it->hk_beam->bm_disabled)
3737 it->hk_beam->p2 = it->hk_lock_node;
3738 it->hk_beam->bm_inter_actor = (it->hk_locked_actor !=
nullptr);
3739 it->hk_beam->L = (it->hk_hook_node->AbsPosition - it->hk_lock_node->AbsPosition).length();
3740 it->hk_beam->bm_disabled =
false;
3741 this->AddInterActorBeam(it->hk_beam, it->hk_locked_actor, mode);
3747 else if ((it->hk_locked ==
LOCKED || it->hk_locked ==
PRELOCK) && (mode != ActorLinkingRequestType::HOOK_LOCK || !it->hk_beam->bm_inter_actor))
3751 this->RemoveInterActorBeam(it->hk_beam, mode);
3752 if (it->hk_group <= -2)
3754 it->hk_timer = it->hk_timer_preset;
3756 it->hk_lock_node = 0;
3757 it->hk_locked_actor = 0;
3759 it->hk_beam->p2 = &ar_nodes[0];
3760 it->hk_beam->bm_inter_actor =
false;
3761 it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length();
3762 it->hk_beam->bm_disabled =
true;
3767 void Actor::parkingbrakeToggle()
3769 if (ar_state == ActorState::DISPOSED)
3772 ar_parking_brake = !ar_parking_brake;
3774 if (ar_parking_brake)
3782 void Actor::antilockbrakeToggle()
3784 if (ar_state == ActorState::DISPOSED)
3788 alb_mode = !alb_mode;
3791 void Actor::tractioncontrolToggle()
3793 if (ar_state == ActorState::DISPOSED)
3800 void Actor::beaconsToggle()
3802 if (ar_state == ActorState::DISPOSED)
3805 if (m_flares_mode == GfxFlaresMode::NONE)
3816 void Actor::muteAllSounds()
3819 if (ar_state == ActorState::DISPOSED)
3822 for (
int i = 0; i < ar_num_soundsources; i++)
3824 if (ar_soundsources[i].ssi)
3825 ar_soundsources[i].ssi->setEnabled(
false);
3827 #endif // USE_OPENAL
3830 void Actor::unmuteAllSounds()
3833 if (ar_state == ActorState::DISPOSED)
3836 for (
int i = 0; i < ar_num_soundsources; i++)
3838 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3839 ar_soundsources[i].ssi->setEnabled(enabled);
3841 #endif // USE_OPENAL
3844 void Actor::NotifyActorCameraChanged()
3848 if (ar_state == ActorState::DISPOSED)
3851 for (
int i = 0; i < ar_num_soundsources; i++)
3853 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3854 ar_soundsources[i].ssi->setEnabled(enabled);
3856 #endif // USE_OPENAL
3864 int Actor::GetNumActiveConnectedBeams(
int nodeid)
3866 int totallivebeams = 0;
3867 for (
unsigned int ni = 0; ni < ar_node_to_beam_connections[nodeid].size(); ++ni)
3869 if (!ar_beams[ar_node_to_beam_connections[nodeid][ni]].bm_disabled && !ar_beams[ar_node_to_beam_connections[nodeid][ni]].bounded)
3872 return totallivebeams;
3875 bool Actor::isTied()
3877 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3883 bool Actor::isLocked()
3885 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3886 if (it->hk_locked ==
LOCKED)
3891 void Actor::updateDashBoards(
float dt)
3902 int gear = ar_engine->GetGear();
3905 int numGears = (int)ar_engine->getNumGears();
3908 String str = String();
3921 int cg = ar_engine->getAutoShift();
3922 if (cg != EngineSim::MANUALMODE)
3924 str = ((cg == EngineSim::REAR) ?
"#ffffff" :
"#868686") + String(
"R\n");
3925 str += ((cg == EngineSim::NEUTRAL) ?
"#ff0012" :
"#8a000a") + String(
"N\n");
3926 str += ((cg == EngineSim::DRIVE) ?
"#12ff00" :
"#248c00") + String(
"D\n");
3927 str += ((cg == EngineSim::TWO) ?
"#ffffff" :
"#868686") + String(
"2\n");
3928 str += ((cg == EngineSim::ONE) ?
"#ffffff" :
"#868686") + String(
"1");
3933 str =
"#b8b8b8M\na\nn\nu";
3938 int autoGear = ar_engine->getAutoShift();
3942 float clutch = ar_engine->GetClutch();
3946 float acc = ar_engine->GetAcceleration();
3950 float rpm = ar_engine->GetEngineRpm();
3954 float turbo = ar_engine->GetTurboPsi() * 3.34f;
3958 bool ign = (ar_engine->hasContact() && !ar_engine->isRunning());
3962 bool batt = (ar_engine->hasContact() && !ar_engine->isRunning());
3966 bool cw = (fabs(ar_engine->GetTorque()) >= ar_engine->GetClutchForce() * 10.0f);
3971 ar_dashboard->setFloat(
DD_BRAKE, ar_brake);
3973 Vector3 cam_dir = this->GetCameraDir();
3974 Vector3 cam_roll = this->GetCameraRoll();
3977 float velocity = ar_nodes[0].Velocity.length();
3978 if (cam_dir != Vector3::ZERO)
3980 velocity = cam_dir.dotProduct(ar_nodes[0].Velocity);
3984 float cur_speed_kph = ar_wheel_speed * 3.6f;
3985 float smooth_kph = (cur_speed_kph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_KPH) * 0.7);
3989 float cur_speed_mph = ar_wheel_speed * 2.23693629f;
3990 float smooth_mph = (cur_speed_mph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_MPH) * 0.7);
3994 if (cam_roll != Vector3::ZERO)
3996 float angle = asin(cam_roll.dotProduct(Vector3::UNIT_Y));
4002 float f = Radian(angle).valueDegrees();
4003 ar_dashboard->setFloat(
DD_ROLL, f);
4007 if (this->ar_has_active_shocks)
4010 float roll_corr = - m_stabilizer_shock_ratio * 10.0f;
4013 bool corr_active = (m_stabilizer_shock_request > 0);
4018 if (cam_dir != Vector3::ZERO)
4020 float angle = asin(cam_dir.dotProduct(Vector3::UNIT_Y));
4026 float f = Radian(angle).valueDegrees();
4027 ar_dashboard->setFloat(
DD_PITCH, f);
4034 bool locked = isLocked();
4035 ar_dashboard->setBool(
DD_LOCKED, locked);
4038 bool low_pres = !ar_engine_hydraulics_ready;
4046 int dash_tc_mode = 1;
4049 if (m_tractioncontrol)
4060 int dash_alb_mode = 1;
4063 if (m_antilockbrake)
4075 if (fabs(ar_command_key[0].commandValue) > 0.000001f)
4083 if (ar_num_screwprops)
4088 float throttle = ar_screwprops[i]->getThrottle();
4091 float steering = ar_screwprops[i]->getRudder();
4096 float depth = this->getHeightAboveGround();
4100 Vector3 hdir = this->GetCameraDir();
4101 float knots = hdir.dotProduct(ar_nodes[ar_main_camera_node_pos].Velocity) * 1.9438f;
4106 if (ar_num_aeroengines)
4110 float throttle = ar_aeroengines[i]->getThrottle();
4113 bool failed = ar_aeroengines[i]->isFailed();
4116 float pcent = ar_aeroengines[i]->getRPMpc();
4124 for (
int i = 0; i < ar_num_wings && i <
DD_MAX_WING; i++)
4127 float aoa = ar_wings[i].fa->aoa;
4133 if (ar_num_wings || ar_num_aeroengines)
4137 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438f;
4140 float altitude = ar_nodes[0].AbsPosition.y;
4142 float sea_level_pressure = 101325;
4144 float airpressure = sea_level_pressure * pow(1.0f - 0.0065f * altitude / 288.15f, 5.24947f);
4145 float airdensity = airpressure * 0.0000120896f;
4147 float knots = ground_speed_kt * sqrt(airdensity / 1.225f);
4153 float alt = ar_nodes[0].AbsPosition.y * 1.1811f;
4157 sprintf(altc,
"%03u", (
int)(ar_nodes[0].AbsPosition.y / 30.48f));
4166 if (!m_hud_features_ok)
4168 bool hasEngine = (ar_engine !=
nullptr);
4169 bool hasturbo =
false;
4170 bool autogearVisible =
false;
4174 hasturbo = ar_engine->HasTurbo();
4175 autogearVisible = (ar_engine->getAutoShift() != EngineSim::MANUALMODE);
4191 ar_dashboard->setEnabled(
DD_TIES_MODE, !ar_ties.empty());
4192 ar_dashboard->setEnabled(
DD_LOCKED, !ar_hooks.empty());
4196 ar_dashboard->updateFeatures();
4197 m_hud_features_ok =
true;
4223 ar_dashboard->setBool(
DD_SIGNAL_WARNING, m_blinker_right_lit && m_blinker_left_lit);
4232 Vector3 rollv=curr_truck->ar_nodes[curr_truck->ar_camera_node_pos[0]].RelPosition-curr_truck->ar_nodes[curr_truck->ar_camera_node_roll[0]].RelPosition;
4234 float rollangle=asin(rollv.dotProduct(Vector3::UNIT_Y));
4237 Vector3 dirv=curr_truck->ar_nodes[curr_truck->ar_camera_node_pos[0]].RelPosition-curr_truck->ar_nodes[curr_truck->ar_camera_node_dir[0]].RelPosition;
4239 float pitchangle=asin(dirv.dotProduct(Vector3::UNIT_Y));
4240 Vector3 upv=dirv.crossProduct(-rollv);
4241 if (upv.y<0) rollangle=3.14159-rollangle;
4247 Vector3 idir=curr_truck->ar_nodes[curr_truck->ar_camera_node_pos[0]].RelPosition-curr_truck->ar_nodes[curr_truck->ar_camera_node_dir[0]].RelPosition;
4249 float dirangle=atan2(idir.dotProduct(Vector3::UNIT_X), idir.dotProduct(-Vector3::UNIT_Z));
4251 if (curr_truck->autopilot)
4256 curr_truck->autopilot->getRadioFix(localizers, free_localizer, &vdev, &hdev);
4257 if (hdev>15) hdev=15;
4258 if (hdev<-15) hdev=-15;
4260 if (vdev>15) vdev=15;
4261 if (vdev<-15) vdev=-15;
4266 float vvi=curr_truck->ar_nodes[0].Velocity.y*196.85;
4267 if (vvi<1000.0 && vvi>-1000.0) angle=vvi*0.047;
4268 if (vvi>1000.0 && vvi<6000.0) angle=47.0+(vvi-1000.0)*0.01175;
4269 if (vvi>6000.0) angle=105.75;
4270 if (vvi<-1000.0 && vvi>-6000.0) angle=-47.0+(vvi+1000.0)*0.01175;
4271 if (vvi<-6000.0) angle=-105.75;
4275 if (curr_truck->aeroengines[0]->getType() == AeroEngineType::AE_XPROP)
4282 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4283 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4288 if (ftp>1 && curr_truck->aeroengines[1]->getType() == AeroEngineType::AE_XPROP)
4295 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4296 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4301 if (ftp>2 && curr_truck->aeroengines[2]->getType() == AeroEngineType::AE_XPROP)
4308 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4309 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4314 if (ftp>3 && curr_truck->aeroengines[3]->getType() == AeroEngineType::AE_XPROP)
4321 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4322 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4335 ar_dashboard->
update(dt);
4338 void Actor::calculateLocalGForces()
4340 Vector3 cam_dir = this->GetCameraDir();
4341 Vector3 cam_roll = this->GetCameraRoll();
4342 Vector3 cam_up = cam_dir.crossProduct(cam_roll);
4346 float vertacc = m_camera_gforces.dotProduct(cam_up) + gravity;
4347 float longacc = m_camera_gforces.dotProduct(cam_dir);
4348 float latacc = m_camera_gforces.dotProduct(cam_roll);
4350 m_camera_local_gforces_cur = Vector3(vertacc, longacc, latacc) / gravity;
4353 if (m_reset_timer.getMilliseconds() > 500)
4355 m_camera_local_gforces_max.makeCeil(-m_camera_local_gforces_cur);
4356 m_camera_local_gforces_max.makeCeil(+m_camera_local_gforces_cur);
4372 ar_brake = triggerValue;
4396 unsigned int vector_index,
4401 : ar_nb_optimum(7, std::numeric_limits<float>::max())
4402 , ar_nb_reference(7, std::numeric_limits<float>::max())
4403 , m_tyre_pressure(this)
4404 , ar_nb_beams_scale(std::make_pair(1.0f, 1.0f))
4405 , ar_nb_shocks_scale(std::make_pair(1.0f, 1.0f))
4406 , ar_nb_wheels_scale(std::make_pair(1.0f, 1.0f))
4407 , ar_nb_beams_k_interval(std::make_pair(0.1f, 2.0f))
4408 , ar_nb_beams_d_interval(std::make_pair(0.1f, 2.0f))
4409 , ar_nb_shocks_k_interval(std::make_pair(0.1f, 8.0f))
4410 , ar_nb_shocks_d_interval(std::make_pair(0.1f, 8.0f))
4411 , ar_nb_wheels_k_interval(std::make_pair(1.0f, 1.0f))
4412 , ar_nb_wheels_d_interval(std::make_pair(1.0f, 1.0f))
4415 , m_avg_node_position_prev(rq.asr_position)
4417 , m_avg_node_position(rq.asr_position)
4418 , ar_instance_id(actor_id)
4419 , ar_vector_index(vector_index)
4420 , m_avg_proped_wheel_radius(0.2f)
4421 , ar_filename(rq.asr_cache_entry->fname)
4422 , m_section_config(rq.asr_config)
4423 , m_used_actor_entry(rq.asr_cache_entry)
4424 , m_used_skin_entry(rq.asr_skin_entry)
4425 , m_working_tuneup_def(rq.asr_working_tuneup)
4428 , ar_update_physics(false)
4429 , ar_disable_aerodyn_turbulent_drag(false)
4430 , ar_engine_hydraulics_ready(true)
4431 , ar_guisettings_use_engine_max_rpm(false)
4432 , ar_hydro_speed_coupling(false)
4433 , ar_collision_relevant(false)
4434 , ar_is_police(false)
4435 , ar_rescuer_flag(false)
4436 , ar_forward_commands(false)
4437 , ar_import_commands(false)
4438 , ar_toggle_ropes(false)
4439 , ar_toggle_ties(false)
4440 , ar_physics_paused(false)
4443 , m_hud_features_ok(false)
4444 , m_slidenodes_locked(false)
4445 , m_net_initialized(false)
4446 , m_water_contact(false)
4447 , m_water_contact_old(false)
4448 , m_has_command_beams(false)
4449 , m_custom_particles_enabled(false)
4450 , m_beam_break_debug_enabled(false)
4451 , m_beam_deform_debug_enabled(false)
4452 , m_trigger_debug_enabled(false)
4453 , m_disable_default_sounds(false)
4454 , m_disable_smoke(false)
4529 for (
int i = 0; i <
ar_flares.size(); i++)
4531 if (
ar_flares[i].controlnumber == number)
4540 for (
int i = 0; i <
ar_flares.size(); i++)
4580 return Ogre::MaterialPtr();
4585 std::vector<std::string> names;
4588 names.push_back(it->first);
4601 return Ogre::Vector3::ZERO;
4632 std::stringstream buf;
4634 buf <<
"[nodes]" << std::endl;
4644 <<
", loaded:" << (int)(
ar_nodes[i].nd_loaded_mass)
4646 <<
" wheel_rim:" << (int)
ar_nodes[i].nd_rim_node
4648 <<
" (set_node_defaults)"
4662 buf <<
"[beams]" << std::endl;
4666 <<
" " << std::setw(4) << i
4670 <<
" (set_beam_defaults/scale)"
4671 <<
" spring:" << std::setw(8) <<
ar_beams[i].
k
4672 <<
", damp:" << std::setw(8) <<
ar_beams[i].
d
4682 Ogre::DataStreamPtr outStream = Ogre::ResourceGroupManager::getSingleton().createResource(fileName,
RGN_LOGS,
true);
4683 std::string text = buf.str();
4684 outStream->write(text.c_str(), text.length());
4692 if (state.eventlock_present)
4695 if (ev_active && (ev_active != state.event_active_prev))
4697 state.anim_active = !state.anim_active;
4703 state.anim_active = ev_active;
4705 state.event_active_prev = ev_active;