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_autopilot !=
nullptr)
130 ar_autopilot =
nullptr;
133 if (m_fusealge_airfoil)
134 delete m_fusealge_airfoil;
135 m_fusealge_airfoil =
nullptr;
137 if (m_replay_handler)
138 delete m_replay_handler;
139 m_replay_handler =
nullptr;
142 ar_vehicle_ai =
nullptr;
145 if (m_deletion_scene_nodes.size() > 0)
147 for (
unsigned int i = 0; i < m_deletion_scene_nodes.size(); i++)
151 if (!m_deletion_scene_nodes[i])
153 m_deletion_scene_nodes[i]->removeAndDestroyAllChildren();
162 m_deletion_scene_nodes.clear();
165 if (m_deletion_entities.size() > 0)
167 for (
unsigned int i = 0; i < m_deletion_entities.size(); i++)
171 if (!m_deletion_entities[i])
173 m_deletion_entities[i]->detachAllObjectsFromBone();
182 m_deletion_entities.clear();
189 for (
int i = 0; i < ar_num_wings; i++)
195 delete ar_wings[i].fa;
196 if (ar_wings[i].cnode)
198 ar_wings[i].cnode->removeAndDestroyAllChildren();
210 for (
int i = 0; i < ar_num_aeroengines; i++)
212 if (ar_aeroengines[i])
213 delete ar_aeroengines[i];
217 for (
int i = 0; i < ar_num_screwprops; i++)
219 if (ar_screwprops[i])
221 delete ar_screwprops[i];
222 ar_screwprops[i] =
nullptr;
231 ar_airbrakes.clear();
234 for (
int i = 0; i < ar_num_wheels; ++i)
236 delete m_skid_trails[i];
237 m_skid_trails[i] =
nullptr;
241 for (
size_t i = 0; i < this->ar_flares.size(); i++)
245 if (ar_flares[i].snode)
247 ar_flares[i].snode->removeAndDestroyAllChildren();
250 if (ar_flares[i].bbs)
252 if (ar_flares[i].light)
261 this->ar_flares.clear();
264 for (std::vector<RailGroup*>::iterator it = m_railgroups.begin(); it != m_railgroups.end(); it++)
268 m_railgroups.clear();
270 if (m_intra_point_col_detector)
272 delete m_intra_point_col_detector;
273 m_intra_point_col_detector =
nullptr;
276 if (m_inter_point_col_detector)
278 delete m_inter_point_col_detector;
279 m_inter_point_col_detector =
nullptr;
283 delete m_transfer_case;
285 for (
int i = 0; i < m_num_axle_diffs; ++i)
287 if (m_axle_diffs[i] !=
nullptr)
288 delete m_axle_diffs[i];
290 m_num_axle_diffs = 0;
292 for (
int i = 0; i < m_num_wheel_diffs; ++i)
294 if (m_wheel_diffs[i] !=
nullptr)
295 delete m_wheel_diffs[i];
297 m_num_wheel_diffs = 0;
301 m_wheel_node_count = 0;
306 delete[] ar_rotators;
311 ar_state = ActorState::DISPOSED;
316 void Actor::scaleTruck(
float value)
318 if (ar_state == ActorState::DISPOSED)
325 for (
int i = 0; i < ar_num_beams; i++)
328 ar_beams[i].d *= value;
329 ar_beams[i].L *= value;
330 ar_beams[i].refL *= value;
335 hbeam.hb_ref_length *= value;
336 hbeam.hb_speed *= value;
339 Vector3 refpos = ar_nodes[0].AbsPosition;
340 Vector3 relpos = ar_nodes[0].RelPosition;
341 for (
int i = 1; i < ar_num_nodes; i++)
343 ar_initial_node_positions[i] = refpos + (ar_initial_node_positions[i] - refpos) * value;
344 ar_nodes[i].AbsPosition = refpos + (ar_nodes[i].AbsPosition - refpos) * value;
345 ar_nodes[i].RelPosition = relpos + (ar_nodes[i].RelPosition - relpos) * value;
346 ar_nodes[i].Velocity *= value;
347 ar_nodes[i].Forces *= value;
348 ar_nodes[i].mass *= value;
350 updateSlideNodePositions();
352 m_gfx_actor->ScaleActor(relpos, value);
356 float Actor::getRotation()
358 if (ar_state == ActorState::DISPOSED)
361 Vector3 dir = getDirection();
363 return atan2(dir.dotProduct(Vector3::UNIT_X), dir.dotProduct(-Vector3::UNIT_Z));
366 Vector3 Actor::getDirection()
368 return ar_main_camera_dir_corr * this->GetCameraDir();
371 Vector3 Actor::getPosition()
373 return m_avg_node_position;
376 Ogre::Quaternion Actor::getOrientation()
378 Ogre::Vector3 localZ = ar_main_camera_dir_corr * -this->GetCameraDir();
379 Ogre::Vector3 localX = ar_main_camera_dir_corr * this->GetCameraRoll();
380 Ogre::Vector3 localY = localZ.crossProduct(localX);
381 return Ogre::Quaternion(localX, localY, localZ);
384 void Actor::pushNetwork(
char* data,
int size)
390 update.
node_data.resize(m_net_node_buf_size);
391 update.
wheel_data.resize(ar_num_wheels *
sizeof(
float));
404 memcpy(update.
node_data.data(), ptr, m_net_node_buf_size);
405 ptr += m_net_node_buf_size;
408 for (
int i = 0; i < ar_num_wheels; i++)
410 float wspeed = *(
float*)(ptr);
412 ptr +=
sizeof(float);
416 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
419 char byte = *(ptr + (i / 8));
420 char mask = char(1) << (7 - (i % 8));
421 m_prop_anim_key_states[i].anim_active = (
byte & mask);
426 if (!m_net_initialized)
434 strncpy(reg.
name, ar_filename.c_str(), 128);
443 text << info.
username <<
_L(
" content mismatch: ") << reg.name;
450 m_net_initialized =
true;
452 RoR::LogFormat(
"[RoR|Network] Stream mismatch, filename: '%s'", ar_filename.c_str());
457 if (!m_net_initialized)
461 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
462 if (oob->
time > rnow + 100)
468 m_net_updates.push_back(update);
469 #endif // USE_SOCKETW
472 void Actor::calcNetwork()
476 if (m_net_updates.size() < 2)
480 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
483 int index_offset = 0;
484 for (
int i = 0; i < m_net_updates.size() - 1; i++)
487 if (oob->
time > rnow)
494 char* netb1 = (
char*) m_net_updates[index_offset ].node_data.data();
495 char* netb2 = (
char*) m_net_updates[index_offset + 1].node_data.data();
496 float* net_rp1 = (
float*) m_net_updates[index_offset ].wheel_data.data();
497 float* net_rp2 = (
float*) m_net_updates[index_offset + 1].wheel_data.data();
499 float tratio = (float)(rnow - oob1->
time) / (float)(oob2->
time - oob1->
time);
503 m_net_updates.clear();
506 else if (tratio > 1.0f)
510 else if (index_offset == 0 && (m_net_updates.size() > 5 || (tratio < 0.125f && m_net_updates.size() > 2)))
515 half_float::half* halfb1 =
reinterpret_cast<half_float::half*
>(netb1 +
sizeof(float) * 3);
516 half_float::half* halfb2 =
reinterpret_cast<half_float::half*
>(netb2 +
sizeof(float) * 3);
517 Vector3 p1ref = Vector3::ZERO;
518 Vector3 p2ref = Vector3::ZERO;
519 Vector3 p1 = Vector3::ZERO;
520 Vector3 p2 = Vector3::ZERO;
522 for (
int i = 0; i < m_net_first_wheel_node; i++)
527 p1.x = ((
float*)netb1)[0];
528 p1.y = ((
float*)netb1)[1];
529 p1.z = ((
float*)netb1)[2];
532 p2.x = ((
float*)netb2)[0];
533 p2.y = ((
float*)netb2)[1];
534 p2.z = ((
float*)netb2)[2];
540 const int bufpos = (i - 1) * 3;
541 const Vector3 p1rel(halfb1[bufpos + 0], halfb1[bufpos + 1], halfb1[bufpos + 2]);
542 const Vector3 p2rel(halfb2[bufpos + 0], halfb2[bufpos + 1], halfb2[bufpos + 2]);
549 ar_nodes[i].AbsPosition = p1 + tratio * (p2 - p1);
550 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
551 ar_nodes[i].Velocity = (p2 - p1) * 1000.0f / (
float)(oob2->
time - oob1->
time);
554 for (
int i = 0; i < ar_num_wheels; i++)
556 float rp = net_rp1[i] + tratio * (net_rp2[i] - net_rp1[i]);
558 Vector3 axis = ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition;
560 Plane pplan = Plane(axis, ar_wheels[i].wh_axis_node_0->AbsPosition);
561 Vector3 ortho = -pplan.projectVector(ar_wheels[i].wh_near_attach_node->AbsPosition) - ar_wheels[i].wh_axis_node_0->AbsPosition;
562 Vector3 ray = ortho.crossProduct(axis);
564 ray *= ar_wheels[i].wh_radius;
565 float drp = Math::TWO_PI / (ar_wheels[i].wh_num_nodes / 2);
566 for (
int j = 0; j < ar_wheels[i].wh_num_nodes / 2; j++)
568 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
570 ar_wheels[i].wh_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
571 ar_wheels[i].wh_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_nodes[j * 2]->AbsPosition - ar_origin;
573 ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
574 ar_wheels[i].wh_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition - ar_origin;
577 ray *= ar_wheels[i].wh_rim_radius;
578 for (
int j = 0; j < ar_wheels[i].wh_num_rim_nodes / 2; j++)
580 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
582 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
583 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2]->AbsPosition - ar_origin;
585 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
586 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition - ar_origin;
589 this->UpdateBoundingBoxes();
590 this->calculateAveragePosition();
599 ar_wheel_speed = netwspeed;
609 if (ar_num_aeroengines > 0)
631 ar_engine->pushNetworkState(engspeed, engforce, engclutch, gear, running, contact, automode);
636 toggleCustomParticles();
642 this->setLightStateMask(oob1->
lightmask);
654 for (
int i = 0; i < index_offset; i++)
656 m_net_updates.pop_front();
659 m_net_initialized =
true;
662 void Actor::RecalculateNodeMasses(Real total)
665 for (
int i = 0; i < ar_num_nodes; i++)
667 if (!ar_nodes[i].nd_tyre_node)
669 if (!ar_nodes[i].nd_loaded_mass)
671 ar_nodes[i].mass = 0;
673 else if (!ar_nodes[i].nd_override_mass)
675 ar_nodes[i].mass = m_load_mass / (float)m_masscount;
681 for (
int i = 0; i < ar_num_beams; i++)
685 Real half_newlen = ar_beams[i].L / 2.0;
686 if (!ar_beams[i].p1->nd_tyre_node)
688 if (!ar_beams[i].p2->nd_tyre_node)
693 for (
int i = 0; i < ar_num_beams; i++)
697 Real half_mass = ar_beams[i].L * total / len / 2.0f;
698 if (!ar_beams[i].p1->nd_tyre_node)
699 ar_beams[i].p1->mass += half_mass;
700 if (!ar_beams[i].p2->nd_tyre_node)
701 ar_beams[i].p2->mass += half_mass;
705 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
707 it->rp_beam->p2->mass = 100.0f;
711 for (
int i = 0; i < this->ar_num_cinecams; ++i)
714 ar_nodes[ar_cinecam_node[i]].mass = m_definition->root_module->cinecam[i].node_mass;
718 for (
int i = 0; i < ar_num_nodes; i++)
720 if (!ar_nodes[i].nd_tyre_node &&
721 !(ar_minimass_skip_loaded_nodes && ar_nodes[i].nd_loaded_mass) &&
722 ar_nodes[i].mass < ar_minimass[i])
727 snprintf(buf, 300,
"Node '%d' mass (%f Kg) is too light. Resetting to 'minimass' (%f Kg)", i, ar_nodes[i].mass, ar_minimass[i]);
730 ar_nodes[i].mass = ar_minimass[i];
735 for (
int i = 0; i < ar_num_nodes; i++)
739 String msg =
"Node " +
TOSTRING(i) +
" : " +
TOSTRING((
int)ar_nodes[i].mass) +
" kg";
740 if (ar_nodes[i].nd_loaded_mass)
742 if (ar_nodes[i].nd_override_mass)
743 msg +=
" (overriden by node mass)";
745 msg +=
" (normal load node: " +
TOSTRING(m_load_mass) +
" kg / " +
TOSTRING(m_masscount) +
" nodes)";
749 m_total_mass += ar_nodes[i].mass;
751 LOG(
"TOTAL VEHICLE MASS: " +
TOSTRING((
int)m_total_mass) +
" kg");
754 float Actor::getTotalMass(
bool withLocked)
756 if (ar_state == ActorState::DISPOSED)
762 float mass = m_total_mass;
764 for (
ActorPtr& actor : ar_linked_actors)
766 mass += actor->m_total_mass;
772 void Actor::DetermineLinkedActors()
777 ar_linked_actors.clear();
780 std::map<ActorPtr, bool> lookup_table;
782 lookup_table.insert(std::pair<ActorPtr, bool>(
this,
false));
788 for (
auto it_actor = lookup_table.begin(); it_actor != lookup_table.end(); ++it_actor)
790 if (!it_actor->second)
795 auto actor_pair = inter_actor_link.second;
796 if (actor == actor_pair.first || actor == actor_pair.second)
798 auto other_actor = (actor != actor_pair.first) ? actor_pair.first : actor_pair.second;
799 auto ret = lookup_table.insert(std::pair<ActorPtr, bool>(other_actor,
false));
802 ar_linked_actors.push_back(other_actor);
807 it_actor->second =
true;
813 int Actor::getWheelNodeCount()
const
815 return m_wheel_node_count;
818 void Actor::calcNodeConnectivityGraph()
822 ar_node_to_node_connections.resize(ar_num_nodes, std::vector<int>());
823 ar_node_to_beam_connections.resize(ar_num_nodes, std::vector<int>());
825 for (i = 0; i < ar_num_beams; i++)
827 if (ar_beams[i].p1 != NULL && ar_beams[i].p2 != NULL && ar_beams[i].p1->pos >= 0 && ar_beams[i].p2->pos >= 0)
829 ar_node_to_node_connections[ar_beams[i].p1->pos].push_back(ar_beams[i].p2->pos);
830 ar_node_to_beam_connections[ar_beams[i].p1->pos].push_back(i);
831 ar_node_to_node_connections[ar_beams[i].p2->pos].push_back(ar_beams[i].p1->pos);
832 ar_node_to_beam_connections[ar_beams[i].p2->pos].push_back(i);
837 bool Actor::Intersects(
ActorPtr actor, Vector3 offset)
839 Vector3 bb_min = ar_bounding_box.getMinimum() + offset;
840 Vector3 bb_max = ar_bounding_box.getMaximum() + offset;
841 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
847 for (
int i = 0; i < ar_num_beams; i++)
849 if (!(ar_beams[i].p1->nd_contacter || ar_beams[i].p1->nd_contactable) ||
850 !(ar_beams[i].p2->nd_contacter || ar_beams[i].p2->nd_contactable))
853 Vector3 origin = ar_beams[i].p1->AbsPosition + offset;
854 Vector3 target = ar_beams[i].p2->AbsPosition + offset;
856 Ray ray(origin, target - origin);
865 auto result = Ogre::Math::intersects(ray, a, b, c);
866 if (result.first && result.second < 1.0f)
883 Ray ray(origin, target - origin);
885 for (
int j = 0; j < ar_num_collcabs; j++)
887 int index = ar_collcabs[j] * 3;
888 Vector3 a = ar_nodes[ar_cabs[index + 0]].AbsPosition + offset;
889 Vector3 b = ar_nodes[ar_cabs[index + 1]].AbsPosition + offset;
890 Vector3 c = ar_nodes[ar_cabs[index + 2]].AbsPosition + offset;
892 auto result = Ogre::Math::intersects(ray, a, b, c);
893 if (result.first && result.second < 1.0f)
903 Vector3 Actor::calculateCollisionOffset(Vector3 direction)
905 if (direction == Vector3::ZERO)
906 return Vector3::ZERO;
908 Real max_distance = direction.normalise();
911 Vector3 collision_offset = Vector3::ZERO;
913 while (collision_offset.length() < max_distance)
915 Vector3 bb_min = ar_bounding_box.getMinimum() + collision_offset;
916 Vector3 bb_max = ar_bounding_box.getMaximum() + collision_offset;
917 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
919 bool collision =
false;
925 if (!bb.intersects(actor->ar_bounding_box))
929 if (m_intra_point_col_detector)
931 for (
int i = 0; i < actor->ar_num_collcabs; i++)
933 int tmpv = actor->ar_collcabs[i] * 3;
934 node_t* no = &actor->ar_nodes[actor->ar_cabs[tmpv]];
935 node_t* na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]];
936 node_t* nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]];
938 m_intra_point_col_detector->query(no->
AbsPosition - collision_offset,
941 actor->ar_collision_range * 3.0f);
943 if (collision = !m_intra_point_col_detector->hit_list.empty())
951 float proximity = std::max(.05f, std::sqrt(std::max(m_min_camera_radius, actor->m_min_camera_radius)) / 50.f);
954 for (
int i = 0; i < ar_num_nodes; i++)
956 if (!ar_nodes[i].nd_contacter && !ar_nodes[i].nd_contactable)
959 Vector3 query_position = ar_nodes[i].AbsPosition + collision_offset;
961 for (
int j = 0; j < actor->ar_num_nodes; j++)
963 if (!actor->ar_nodes[j].nd_contacter && !actor->ar_nodes[j].nd_contactable)
966 if (collision = query_position.squaredDistance(actor->ar_nodes[j].AbsPosition) < proximity)
979 if (!collision && m_inter_point_col_detector)
981 for (
int i = 0; i < ar_num_collcabs; i++)
983 int tmpv = ar_collcabs[i] * 3;
984 node_t* no = &ar_nodes[ar_cabs[tmpv]];
985 node_t* na = &ar_nodes[ar_cabs[tmpv + 1]];
986 node_t* nb = &ar_nodes[ar_cabs[tmpv + 2]];
988 m_inter_point_col_detector->query(no->
AbsPosition + collision_offset,
991 ar_collision_range * 3.0f);
993 if (collision = !m_inter_point_col_detector->hit_list.empty())
1005 if (collision = this->Intersects(actor, collision_offset))
1013 collision_offset += direction * 0.05f;
1016 return collision_offset;
1019 void Actor::resolveCollisions(Ogre::Vector3 direction)
1021 if (m_intra_point_col_detector)
1022 m_intra_point_col_detector->UpdateIntraPoint(
true);
1024 if (m_inter_point_col_detector)
1025 m_inter_point_col_detector->UpdateInterPoint(
true);
1027 Vector3 offset = calculateCollisionOffset(direction);
1029 if (offset == Vector3::ZERO)
1033 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1035 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
false, this->getMinHeight() + offset.y);
1038 void Actor::resolveCollisions(
float max_distance,
bool consider_up)
1040 if (m_intra_point_col_detector)
1041 m_intra_point_col_detector->UpdateIntraPoint(
true);
1043 if (m_inter_point_col_detector)
1044 m_inter_point_col_detector->UpdateInterPoint(
true);
1046 Vector3 u = Vector3::UNIT_Y;
1047 Vector3 f = Vector3(getDirection().
x, 0.0f, getDirection().
z).normalisedCopy();
1048 Vector3 l = u.crossProduct(f);
1051 Vector3 left = calculateCollisionOffset(+l * max_distance);
1052 Vector3 right = calculateCollisionOffset(-l * left.length());
1053 Vector3 lateral = left.length() < right.length() * 1.1f ? left : right;
1055 Vector3 front = calculateCollisionOffset(+f * lateral.length());
1056 Vector3 back = calculateCollisionOffset(-f * front.length());
1057 Vector3 sagittal = front.length() < back.length() * 1.1f ? front : back;
1059 Vector3 offset = lateral.length() < sagittal.length() * 1.2f ? lateral : sagittal;
1063 Vector3 up = calculateCollisionOffset(+u * offset.length());
1064 if (up.length() * 1.2f < offset.length())
1068 if (offset == Vector3::ZERO)
1072 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1074 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
true, this->getMinHeight() + offset.y);
1077 void Actor::calculateAveragePosition()
1082 m_avg_node_position = ar_nodes[ar_custom_camera_node].AbsPosition;
1084 else if (ar_extern_camera_mode == ExtCameraMode::CINECAM && ar_num_cinecams > 0)
1087 m_avg_node_position = ar_nodes[ar_cinecam_node[0]].AbsPosition;
1089 else if (ar_extern_camera_mode == ExtCameraMode::NODE && ar_extern_camera_node !=
NODENUM_INVALID)
1092 m_avg_node_position = ar_nodes[ar_extern_camera_node].AbsPosition;
1097 Vector3 aposition = Vector3::ZERO;
1098 for (
int n = 0; n < ar_num_nodes; n++)
1100 aposition += ar_nodes[n].AbsPosition;
1102 m_avg_node_position = aposition / ar_num_nodes;
1112 void Actor::UpdateBoundingBoxes()
1115 ar_bounding_box = AxisAlignedBox::BOX_NULL;
1116 ar_predicted_bounding_box = AxisAlignedBox::BOX_NULL;
1117 ar_evboxes_bounding_box = AxisAlignedBox::BOX_NULL;
1118 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1120 ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1121 ar_predicted_coll_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1126 const float CABNODE_MAX_CAMDIST = 15.f;
1127 const Ogre::Vector3 mainCamPos = ar_nodes[ar_main_camera_node_pos].RelPosition;
1130 for (
int i = 0; i < ar_num_nodes; i++)
1132 Vector3 vel = ar_nodes[i].Velocity;
1133 Vector3 pos = ar_nodes[i].AbsPosition;
1134 int16_t cid = ar_nodes[i].nd_coll_bbox_id;
1136 ar_bounding_box.merge(pos);
1137 if (mainCamPos.squaredDistance(ar_nodes[i].RelPosition) < (CABNODE_MAX_CAMDIST*CABNODE_MAX_CAMDIST))
1139 ar_evboxes_bounding_box.merge(pos);
1141 ar_predicted_bounding_box.merge(pos);
1142 ar_predicted_bounding_box.merge(pos + vel);
1143 if (cid != node_t::INVALID_BBOX)
1145 ar_collision_bounding_boxes[cid].merge(pos);
1146 ar_predicted_coll_bounding_boxes[cid].merge(pos);
1147 ar_predicted_coll_bounding_boxes[cid].merge(pos + vel);
1154 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1161 void Actor::UpdatePhysicsOrigin()
1163 if (ar_nodes[0].RelPosition.squaredLength() > 10000.0)
1165 Vector3 offset = ar_nodes[0].RelPosition;
1166 ar_origin += offset;
1167 for (
int i = 0; i < ar_num_nodes; i++)
1169 ar_nodes[i].RelPosition -= offset;
1174 void Actor::ResetAngle(
float rot)
1177 Vector3 origin = ar_nodes[ar_main_camera_node_pos].AbsPosition;
1181 matrix.FromEulerAnglesXYZ(Radian(0), Radian(-rot + m_spawn_rotation), Radian(0));
1183 for (
int i = 0; i < ar_num_nodes; i++)
1186 ar_nodes[i].AbsPosition -= origin;
1187 ar_nodes[i].AbsPosition = matrix * ar_nodes[i].AbsPosition;
1188 ar_nodes[i].AbsPosition += origin;
1189 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - this->ar_origin;
1192 this->UpdateBoundingBoxes();
1193 calculateAveragePosition();
1196 void Actor::updateInitPosition()
1198 for (
int i = 0; i < ar_num_nodes; i++)
1200 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1204 void Actor::resetPosition(
float px,
float pz,
bool setInitPosition,
float miny)
1207 Vector3 offset = Vector3(px, ar_nodes[0].AbsPosition.y, pz) - ar_nodes[0].AbsPosition;
1208 for (
int i = 0; i < ar_num_nodes; i++)
1210 ar_nodes[i].AbsPosition += offset;
1211 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1215 float vertical_offset = miny - this->getMinHeight();
1218 vertical_offset += std::max(0.0f,
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight() - miny);
1220 for (
int i = 1; i < ar_num_nodes; i++)
1222 if (ar_nodes[i].nd_no_ground_contact)
1225 vertical_offset += std::max(0.0f, terrainHeight - (ar_nodes[i].AbsPosition.y + vertical_offset));
1227 for (
int i = 0; i < ar_num_nodes; i++)
1229 ar_nodes[i].AbsPosition.y += vertical_offset;
1230 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1234 float mesh_offset = 0.0f;
1235 for (
int i = 0; i < ar_num_nodes; i++)
1237 if (mesh_offset >= 1.0f)
1239 if (ar_nodes[i].nd_no_ground_contact)
1241 float offset = mesh_offset;
1242 while (offset < 1.0f)
1244 Vector3 query = ar_nodes[i].AbsPosition + Vector3(0.0f, offset, 0.0f);
1245 if (!
App::GetGameContext()->GetTerrain()->GetCollisions()->collisionCorrect(&query,
false))
1247 mesh_offset = offset;
1253 for (
int i = 0; i < ar_num_nodes; i++)
1255 ar_nodes[i].AbsPosition.y += mesh_offset;
1256 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1259 resetPosition(Vector3::ZERO, setInitPosition);
1262 void Actor::resetPosition(Ogre::Vector3 translation,
bool setInitPosition)
1265 if (translation != Vector3::ZERO)
1267 Vector3 offset = translation - ar_nodes[0].AbsPosition;
1268 for (
int i = 0; i < ar_num_nodes; i++)
1270 ar_nodes[i].AbsPosition += offset;
1271 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1275 if (setInitPosition)
1277 for (
int i = 0; i < ar_num_nodes; i++)
1279 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1283 this->UpdateBoundingBoxes();
1284 calculateAveragePosition();
1287 void Actor::softRespawn(Ogre::Vector3 spawnpos, Ogre::Quaternion spawnrot)
1290 this->SyncReset(
false);
1293 ar_origin = spawnpos;
1294 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1296 ar_nodes[i].AbsPosition = spawnpos + ar_nodes_spawn_offsets[i];
1297 ar_nodes[i].RelPosition = ar_nodes_spawn_offsets[i];
1298 ar_nodes[i].Forces = Ogre::Vector3::ZERO;
1299 ar_nodes[i].Velocity = Ogre::Vector3::ZERO;
1304 for (
NodeNum_t i = 0; i < ar_num_nodes; i++)
1306 ar_nodes[i].AbsPosition = spawnpos + spawnrot * (ar_nodes[i].AbsPosition - spawnpos);
1307 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1311 void Actor::mouseMove(
NodeNum_t node, Vector3 pos,
float force)
1313 m_mouse_grab_node = node;
1314 m_mouse_grab_move_force = force * std::pow(m_total_mass / 3000.0f, 0.75f);
1315 m_mouse_grab_pos = pos;
1318 void Actor::toggleWheelDiffMode()
1320 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1322 m_wheel_diffs[i]->ToggleDifferentialMode();
1326 void Actor::toggleAxleDiffMode()
1328 for (
int i = 0; i < m_num_axle_diffs; ++i)
1330 m_axle_diffs[i]->ToggleDifferentialMode();
1334 void Actor::displayAxleDiffMode()
1336 if (m_num_axle_diffs == 0)
1339 _L(
"No inter-axle differential installed on current vehicle!"),
"error.png");
1343 String message =
"";
1344 for (
int i = 0; i < m_num_axle_diffs; ++i)
1346 if (m_axle_diffs[i])
1351 int a1 = m_axle_diffs[i]->di_idx_1 + 1;
1352 int a2 = m_axle_diffs[i]->di_idx_2 + 1;
1354 message += m_axle_diffs[i]->GetDifferentialTypeName();
1358 "Inter-axle differentials:\n" + message,
"cog.png");
1362 void Actor::displayWheelDiffMode()
1364 if (m_num_wheel_diffs == 0)
1367 _L(
"No inter-wheel differential installed on current vehicle!"),
"error.png");
1371 String message =
"";
1372 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1374 if (m_wheel_diffs[i])
1379 message +=
_L(
"Axle ") +
TOSTRING(i + 1) +
": ";
1380 message += m_wheel_diffs[i]->GetDifferentialTypeName();
1384 "Inter-wheel differentials:\n" + message,
"cog.png");
1388 void Actor::displayTransferCaseMode()
1390 if (m_transfer_case)
1393 _L(
"Transfercase switched to: ") + this->getTransferCaseName(),
"cog.png");
1398 _L(
"No transfercase installed on current vehicle!"),
"error.png");
1402 void Actor::toggleTransferCaseMode()
1404 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_ax_2 < 0 || !m_transfer_case->tr_2wd)
1407 if (m_transfer_case->tr_4wd_mode && !m_transfer_case->tr_2wd_lo)
1409 for (
int i = 0; i < m_transfer_case->tr_gear_ratios.size(); i++)
1411 this->toggleTransferCaseGearRatio();
1412 if (m_transfer_case->tr_gear_ratios[0] == 1.0f)
1417 m_transfer_case->tr_4wd_mode = !m_transfer_case->tr_4wd_mode;
1419 if (m_transfer_case->tr_4wd_mode)
1421 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
true;
1422 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
true;
1423 m_num_proped_wheels += 2;
1427 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
false;
1428 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
false;
1429 m_num_proped_wheels -= 2;
1433 void Actor::toggleTransferCaseGearRatio()
1435 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_gear_ratios.size() < 2)
1438 if (m_transfer_case->tr_4wd_mode || m_transfer_case->tr_2wd_lo)
1440 auto gear_ratios = &m_transfer_case->tr_gear_ratios;
1441 std::rotate(gear_ratios->begin(), gear_ratios->begin() + 1, gear_ratios->end());
1443 ar_engine->setTCaseRatio(m_transfer_case->tr_gear_ratios[0]);
1447 String Actor::getTransferCaseName()
1450 if (m_transfer_case)
1452 name += m_transfer_case->tr_4wd_mode ?
"4WD " :
"2WD ";
1453 if (m_transfer_case->tr_gear_ratios[0] > 1.0f)
1454 name +=
"Lo (" +
TOSTRING(m_transfer_case->tr_gear_ratios[0]) +
":1)";
1461 Ogre::Vector3 Actor::getRotationCenter()
1463 Vector3 sum = Vector3::ZERO;
1464 std::vector<Vector3> positions;
1465 for (
int i = 0; i < ar_num_nodes; i++)
1467 Vector3 pos = ar_nodes[i].AbsPosition;
1468 const auto it = std::find_if(positions.begin(), positions.end(),
1469 [pos](
const Vector3 ref) { return pos.positionEquals(ref, 0.01f); });
1470 if (it == positions.end())
1473 positions.push_back(pos);
1476 return sum / positions.size();
1479 float Actor::getMinHeight(
bool skip_virtual_nodes)
1481 float height = std::numeric_limits<float>::max();
1482 for (
int i = 0; i < ar_num_nodes; i++)
1484 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1486 height = std::min(ar_nodes[i].AbsPosition.y, height);
1489 return (!skip_virtual_nodes || height < std::numeric_limits<float>::max()) ? height : getMinHeight(
false);
1492 float Actor::getMaxHeight(
bool skip_virtual_nodes)
1494 float height = std::numeric_limits<float>::min();
1495 for (
int i = 0; i < ar_num_nodes; i++)
1497 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1499 height = std::max(height, ar_nodes[i].AbsPosition.y);
1502 return (!skip_virtual_nodes || height > std::numeric_limits<float>::min()) ? height : getMaxHeight(
false);
1505 float Actor::getHeightAboveGround(
bool skip_virtual_nodes)
1507 float agl = std::numeric_limits<float>::max();
1508 for (
int i = 0; i < ar_num_nodes; i++)
1510 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1512 Vector3 pos = ar_nodes[i].AbsPosition;
1516 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGround(
false);
1519 float Actor::getHeightAboveGroundBelow(
float height,
bool skip_virtual_nodes)
1521 float agl = std::numeric_limits<float>::max();
1522 for (
int i = 0; i < ar_num_nodes; i++)
1524 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1526 Vector3 pos = ar_nodes[i].AbsPosition;
1530 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGroundBelow(height,
false);
1533 void Actor::reset(
bool keep_position)
1535 if (ar_state == ActorState::DISPOSED)
1540 rq->
amr_type = (keep_position) ? ActorModifyRequest::Type::RESET_ON_SPOT : ActorModifyRequest::Type::RESET_ON_INIT_POS;
1544 void Actor::SoftReset()
1548 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1552 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1557 Vector3 translation = -agl * Vector3::UNIT_Y;
1558 this->resetPosition(ar_nodes[0].AbsPosition + translation,
false);
1559 for (
ActorPtr& actor : ar_linked_actors)
1561 actor->resetPosition(actor->ar_nodes[0].AbsPosition + translation,
false);
1565 m_ongoing_reset =
true;
1568 void Actor::SyncReset(
bool reset_position)
1572 m_reset_timer.reset();
1574 m_camera_local_gforces_cur = Vector3::ZERO;
1575 m_camera_local_gforces_max = Vector3::ZERO;
1577 ar_hydro_dir_state = 0.0;
1578 ar_hydro_aileron_state = 0.0;
1579 ar_hydro_rudder_state = 0.0;
1580 ar_hydro_elevator_state = 0.0;
1581 ar_hydro_dir_wheel_display = 0.0;
1583 ar_fusedrag = Vector3::ZERO;
1585 ar_parking_brake =
false;
1586 ar_trailer_parking_brake =
false;
1587 ar_avg_wheel_speed = 0.0f;
1588 ar_wheel_speed = 0.0f;
1589 ar_wheel_spin = 0.0f;
1592 ar_origin = Vector3::ZERO;
1593 float cur_rot = getRotation();
1594 Vector3 cur_position = ar_nodes[0].AbsPosition;
1596 this->DisjoinInterActorBeams();
1598 for (
int i = 0; i < ar_num_nodes; i++)
1600 ar_nodes[i].AbsPosition = ar_initial_node_positions[i];
1601 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1602 ar_nodes[i].Velocity = Vector3::ZERO;
1603 ar_nodes[i].Forces = Vector3::ZERO;
1606 for (
int i = 0; i < ar_num_beams; i++)
1608 ar_beams[i].maxposstress = ar_beams[i].default_beam_deform;
1609 ar_beams[i].maxnegstress = -ar_beams[i].default_beam_deform;
1610 ar_beams[i].minmaxposnegstress = ar_beams[i].default_beam_deform;
1611 ar_beams[i].strength = ar_beams[i].initial_beam_strength;
1612 ar_beams[i].L = ar_beams[i].refL;
1613 ar_beams[i].stress = 0.0;
1614 ar_beams[i].bm_broken =
false;
1615 ar_beams[i].bm_disabled =
false;
1618 this->applyNodeBeamScales();
1622 for (
auto& h : ar_hooks)
1624 h.hk_beam->bm_disabled =
true;
1627 for (
auto& t : ar_ties)
1629 t.ti_locked_ropable =
nullptr;
1630 t.ti_beam->bm_disabled =
true;
1635 for (
auto& r : ar_ropables)
1637 r.attached_ties = 0;
1638 r.attached_ropes = 0;
1641 for (
int i = 0; i < ar_num_wheels; i++)
1643 ar_wheels[i].wh_speed = 0.0;
1644 ar_wheels[i].wh_torque = 0.0;
1645 ar_wheels[i].wh_avg_speed = 0.0;
1646 ar_wheels[i].wh_is_detached =
false;
1653 ar_engine->startEngine();
1655 ar_engine->setWheelSpin(0.0f);
1658 int num_axle_diffs = (m_transfer_case && m_transfer_case->tr_4wd_mode) ? m_num_axle_diffs + 1 : m_num_axle_diffs;
1659 for (
int i = 0; i < num_axle_diffs; i++)
1660 m_axle_diffs[i]->di_delta_rotation = 0.0f;
1661 for (
int i = 0; i < m_num_wheel_diffs; i++)
1662 m_wheel_diffs[i]->di_delta_rotation = 0.0f;
1663 for (
int i = 0; i < ar_num_aeroengines; i++)
1664 ar_aeroengines[i]->reset();
1665 for (
int i = 0; i < ar_num_screwprops; i++)
1666 ar_screwprops[i]->reset();
1667 for (
int i = 0; i < ar_num_rotators; i++)
1668 ar_rotators[i].angle = 0.0;
1669 for (
int i = 0; i < ar_num_wings; i++)
1670 ar_wings[i].fa->broken =
false;
1672 this->ar_autopilot->reset();
1674 m_buoyance->sink =
false;
1678 hydrobeam.hb_inertia.ResetCmdKeyDelay();
1681 this->GetGfxActor()->ResetFlexbodies();
1684 if (!reset_position)
1686 this->ResetAngle(cur_rot);
1687 this->resetPosition(cur_position,
false);
1688 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1691 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1695 this->resetPosition(ar_nodes[0].AbsPosition - agl * Vector3::UNIT_Y,
false);
1700 this->UpdateBoundingBoxes();
1701 this->calculateAveragePosition();
1706 ar_command_key[i].commandValue = 0.0;
1707 ar_command_key[i].triggerInputValue = 0.0f;
1708 ar_command_key[i].playerInputValue = 0.0f;
1709 for (
auto& b : ar_command_key[i].beams)
1711 b.cmb_state->auto_moving_mode = 0;
1712 b.cmb_state->pressed_center_mode =
false;
1716 this->resetSlideNodes();
1717 if (m_slidenodes_locked)
1719 this->toggleSlideNodeLock();
1722 m_ongoing_reset =
true;
1725 void Actor::applyNodeBeamScales()
1727 for (
int i = 0; i < ar_num_nodes; i++)
1729 ar_nodes[i].mass = ar_initial_node_masses[i] * ar_nb_mass_scale;
1732 m_total_mass = ar_initial_total_mass * ar_nb_mass_scale;
1734 for (
int i = 0; i < ar_num_beams; i++)
1736 if ((ar_beams[i].p1->nd_tyre_node || ar_beams[i].p1->nd_rim_node) ||
1737 (ar_beams[i].p2->nd_tyre_node || ar_beams[i].p2->nd_rim_node))
1739 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_wheels_scale.first;
1740 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_wheels_scale.second;
1742 else if (ar_beams[i].bounded ==
SHOCK1 || ar_beams[i].bounded ==
SHOCK2 || ar_beams[i].bounded ==
SHOCK3)
1744 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_shocks_scale.first;;
1745 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_shocks_scale.second;
1749 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_beams_scale.first;
1750 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_beams_scale.second;
1755 void Actor::ForceFeedbackStep(
int steps)
1757 m_force_sensors.out_body_forces = m_force_sensors.accu_body_forces / steps;
1758 if (!ar_hydros.empty())
1760 m_force_sensors.out_hydros_forces = (m_force_sensors.accu_hydros_forces / steps) / ar_hydros.size();
1764 void Actor::HandleAngelScriptEvents(
float dt)
1766 #ifdef USE_ANGELSCRIPT
1768 if (m_water_contact && !m_water_contact_old)
1770 m_water_contact_old = m_water_contact;
1773 #endif // USE_ANGELSCRIPT
1776 void Actor::searchBeamDefaults()
1780 auto old_beams_scale = ar_nb_beams_scale;
1781 auto old_shocks_scale = ar_nb_shocks_scale;
1782 auto old_wheels_scale = ar_nb_wheels_scale;
1784 if (ar_nb_initialized)
1786 ar_nb_beams_scale.first = Math::RangeRandom(ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1787 ar_nb_beams_scale.second = Math::RangeRandom(ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1788 ar_nb_shocks_scale.first = Math::RangeRandom(ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1789 ar_nb_shocks_scale.second = Math::RangeRandom(ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1790 ar_nb_wheels_scale.first = Math::RangeRandom(ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1791 ar_nb_wheels_scale.second = Math::RangeRandom(ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1795 ar_nb_beams_scale.first = Math::Clamp(1.0f, ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1796 ar_nb_beams_scale.second = Math::Clamp(1.0f, ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1797 ar_nb_shocks_scale.first = Math::Clamp(1.0f, ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1798 ar_nb_shocks_scale.second = Math::Clamp(1.0f, ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1799 ar_nb_wheels_scale.first = Math::Clamp(1.0f, ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1800 ar_nb_wheels_scale.second = Math::Clamp(1.0f, ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1801 ar_nb_reference = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1802 ar_nb_optimum = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1805 this->applyNodeBeamScales();
1807 m_ongoing_reset =
false;
1808 this->CalcForcesEulerPrepare(
true);
1809 for (
int i = 0; i < ar_nb_skip_steps; i++)
1811 this->CalcForcesEulerCompute(i == 0, ar_nb_skip_steps);
1812 if (m_ongoing_reset)
1815 m_ongoing_reset =
true;
1817 float sum_movement = 0.0f;
1818 float movement = 0.0f;
1819 float sum_velocity = 0.0f;
1820 float velocity = 0.0f;
1821 float sum_stress = 0.0f;
1822 float stress = 0.0f;
1824 for (
int k = 0; k < ar_nb_measure_steps; k++)
1826 this->CalcForcesEulerCompute(
false, ar_nb_measure_steps);
1827 for (
int i = 0; i < ar_num_nodes; i++)
1829 float v = ar_nodes[i].Velocity.length();
1830 sum_movement += v / (float)ar_nb_measure_steps;
1831 movement = std::max(movement, v);
1833 for (
int i = 0; i < ar_num_beams; i++)
1835 Vector3 dis = (ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition).normalisedCopy();
1836 float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis);
1837 sum_velocity += std::abs(v) / (float)ar_nb_measure_steps;
1838 velocity = std::max(velocity, std::abs(v));
1839 sum_stress += std::abs(ar_beams[i].stress) / (float)ar_nb_measure_steps;
1840 stress = std::max(stress, std::abs(ar_beams[i].stress));
1841 if (k == 0 && ar_beams[i].bm_broken)
1846 if (sum_broken > ar_nb_reference[6] ||
1847 stress > ar_nb_reference[0] || velocity > ar_nb_reference[2] || movement > ar_nb_optimum[4] ||
1848 sum_stress > ar_nb_reference[1] || sum_velocity > ar_nb_reference[3] || sum_movement > ar_nb_optimum[5] * 2.f)
1850 ar_nb_beams_scale = old_beams_scale;
1851 ar_nb_shocks_scale = old_shocks_scale;
1852 ar_nb_wheels_scale = old_wheels_scale;
1859 ar_nb_optimum = {stress, sum_stress, velocity, sum_velocity, movement, sum_movement, (float)sum_broken};
1860 if (!ar_nb_initialized)
1862 ar_nb_reference = ar_nb_optimum;
1864 ar_nb_initialized =
true;
1867 void Actor::HandleInputEvents(
float dt)
1869 if (!m_ongoing_reset)
1872 if (m_anglesnap_request > 0)
1874 float rotation = Radian(getRotation()).valueDegrees();
1875 float target_rotation = std::round(rotation / m_anglesnap_request) * m_anglesnap_request;
1876 m_rotation_request = -Degree(target_rotation - rotation).valueRadians();
1877 m_rotation_request_center = getRotationCenter();
1878 m_anglesnap_request = 0;
1881 if (m_rotation_request != 0.0f)
1883 Quaternion rot = Quaternion(Radian(m_rotation_request), Vector3::UNIT_Y);
1885 for (
int i = 0; i < ar_num_nodes; i++)
1887 ar_nodes[i].AbsPosition -= m_rotation_request_center;
1888 ar_nodes[i].AbsPosition = rot * ar_nodes[i].AbsPosition;
1889 ar_nodes[i].AbsPosition += m_rotation_request_center;
1890 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1891 ar_nodes[i].Velocity = rot * ar_nodes[i].Velocity;
1892 ar_nodes[i].Forces = rot * ar_nodes[i].Forces;
1895 m_rotation_request = 0.0f;
1896 this->UpdateBoundingBoxes();
1897 calculateAveragePosition();
1900 if (m_translation_request != Vector3::ZERO)
1902 for (
int i = 0; i < ar_num_nodes; i++)
1904 ar_nodes[i].AbsPosition += m_translation_request;
1905 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1908 m_translation_request = Vector3::ZERO;
1909 UpdateBoundingBoxes();
1910 calculateAveragePosition();
1914 void Actor::sendStreamSetup()
1925 Ogre::StringUtil::splitFilename(m_used_actor_entry->resource_bundle_path, bname, bpath);
1926 std::string bq_filename =
fmt::format(
"{}:{}", bname, ar_filename);
1927 strncpy(reg.
name, bq_filename.c_str(), 128);
1930 if (m_used_skin_entry !=
nullptr)
1932 strncpy(reg.
skin, m_used_skin_entry->dname.c_str(), 60);
1938 #endif // USE_SOCKETW
1944 void Actor::sendStreamData()
1948 if (ar_net_timer.getMilliseconds() - ar_net_last_update_time < 100)
1951 ar_net_last_update_time = ar_net_timer.getMilliseconds();
1962 unsigned int packet_len = 0;
1979 if (ar_engine->hasContact())
1981 if (ar_engine->isRunning())
1984 switch (ar_engine->getAutoMode())
1998 if (ar_num_aeroengines > 0)
2000 float rpm = ar_aeroengines[0]->getRPM();
2005 send_oob->
brake = ar_brake;
2010 if (getCustomParticleMode())
2013 if (ar_parking_brake)
2015 if (m_tractioncontrol)
2017 if (m_antilockbrake)
2031 float* send_nodes = (
float *)ptr;
2032 packet_len += m_net_total_buffer_size;
2038 Vector3& refpos = ar_nodes[0].AbsPosition;
2039 send_nodes[0] = refpos.x;
2040 send_nodes[1] = refpos.y;
2041 send_nodes[2] = refpos.z;
2043 ptr +=
sizeof(float) * 3;
2046 half_float::half* sbuf = (half_float::half*)ptr;
2047 for (i = 1; i < m_net_first_wheel_node; i++)
2049 Ogre::Vector3 relpos = ar_nodes[i].AbsPosition - ar_nodes[0].AbsPosition;
2050 sbuf[(i-1) * 3 + 0] =
static_cast<half_float::half
>(relpos.x);
2051 sbuf[(i-1) * 3 + 1] =
static_cast<half_float::half
>(relpos.y);
2052 sbuf[(i-1) * 3 + 2] =
static_cast<half_float::half
>(relpos.z);
2054 ptr +=
sizeof(half_float::half) * 3;
2058 float* wfbuf = (
float*)ptr;
2059 for (i = 0; i < ar_num_wheels; i++)
2061 wfbuf[i] = ar_wheels[i].wh_net_rp;
2063 ptr += ar_num_wheels *
sizeof(float);
2066 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
2068 if (m_prop_anim_key_states[i].anim_active)
2071 char& dst_byte = *(ptr + (i / 8));
2072 char mask = ((char)m_prop_anim_key_states[i].anim_active) << (7 - (i % 8));
2082 void Actor::CalcAnimators(
hydrobeam_t const& hydrobeam,
float &cstate,
int &div)
2089 for (spi = 0; spi < ar_num_screwprops; spi++)
2090 if (ar_screwprops[spi])
2091 ctmp += ar_screwprops[spi]->getRudder();
2104 for (spi = 0; spi < ar_num_screwprops; spi++)
2105 if (ar_screwprops[spi])
2106 ctmp += ar_screwprops[spi]->getThrottle();
2117 if (m_num_wheel_diffs && m_wheel_diffs[0])
2119 String name = m_wheel_diffs[0]->GetDifferentialTypeName();
2122 if (name ==
"Split")
2124 if (name ==
"Locked")
2136 float heading = getRotation();
2138 cstate = (heading * 57.29578f) / 360.0f;
2145 float torque = ar_engine->getCrankFactor();
2148 if (torque >= ar_anim_previous_crank)
2149 cstate -= torque / 10.0f;
2153 if (cstate <= -1.0f)
2155 ar_anim_previous_crank = torque;
2163 int shifter = ar_engine->getGear();
2164 if (shifter > m_previous_gear)
2167 ar_anim_shift_timer = 0.2f;
2169 if (shifter < m_previous_gear)
2172 ar_anim_shift_timer = -0.2f;
2174 m_previous_gear = shifter;
2176 if (ar_anim_shift_timer > 0.0f)
2180 if (ar_anim_shift_timer < 0.0f)
2181 ar_anim_shift_timer = 0.0f;
2183 if (ar_anim_shift_timer < 0.0f)
2187 if (ar_anim_shift_timer > 0.0f)
2188 ar_anim_shift_timer = 0.0f;
2197 int shifter = ar_engine->getGear();
2202 else if (shifter < 0)
2208 cstate -= int((shifter - 1.0) / 2.0);
2216 int shifter = ar_engine->getGear();
2224 cstate = shifter % 2;
2232 int shifter = ar_engine->getGear();
2233 int numgears = ar_engine->getNumGears();
2234 cstate -= (shifter + 2.0) / (numgears + 2.0);
2241 float pbrake = ar_parking_brake;
2249 float speedo = ar_wheel_speed / ar_guisettings_speedo_max_kph;
2250 cstate -= speedo * 3.0f;
2257 float tacho = ar_engine->getRPM() / ar_engine->getShiftUpRPM();
2265 float turbo = ar_engine->getTurboPSI() * 3.34;
2266 cstate -= turbo / 67.0f;
2280 float accel = ar_engine->getAcc();
2281 cstate -= accel + 0.06f;
2289 float clutch = ar_engine->getClutch();
2290 cstate -= fabs(1.0f - clutch);
2301 float pcent = ar_aeroengines[aenum]->getRPMpc();
2303 angle = -5.0 + pcent * 1.9167;
2304 else if (pcent < 110.0)
2305 angle = 110.0 + (pcent - 60.0) * 4.075;
2308 cstate -= angle / 314.0f;
2313 float throttle = ar_aeroengines[aenum]->getThrottle();
2319 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2327 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2330 cstate = tp->
pitch / 120.0f;
2336 if (!ar_aeroengines[aenum]->getIgnition())
2340 if (ar_aeroengines[aenum]->isFailed())
2349 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438;
2350 float altitude = ar_nodes[0].AbsPosition.y;
2351 float sea_level_pressure = 101325;
2352 float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947);
2353 float airdensity = airpressure * 0.0000120896;
2354 float kt = ground_speed_kt * sqrt(airdensity / 1.225);
2355 cstate -= kt / 100.0f;
2362 float vvi = ar_nodes[0].Velocity.y * 196.85;
2364 cstate -= vvi / 6000.0f;
2367 if (cstate <= -1.0f)
2378 float altimeter = (ar_nodes[0].AbsPosition.y * 1.1811) / 360.0f;
2379 int alti_int = int(altimeter);
2380 float alti_mod = (altimeter - alti_int);
2387 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 3600.0f;
2388 int alti_int = int(alti);
2389 float alti_mod = (alti - alti_int);
2391 if (cstate <= -1.0f)
2398 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 36000.0f;
2400 if (cstate <= -1.0f)
2410 if (ar_num_wings > 4)
2411 aoa = (ar_wings[4].fa->aoa) / 25.0f;
2412 if ((ar_nodes[0].Velocity.length() * 1.9438) < 10.0f)
2415 if (cstate <= -1.0f)
2425 Vector3 rollv = this->GetCameraRoll();
2426 Vector3 dirv = this->GetCameraDir();
2427 Vector3 upv = dirv.crossProduct(-rollv);
2428 float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y));
2430 rollangle = Math::RadiansToDegrees(rollangle);
2433 rollangle = 180.0f - rollangle;
2434 cstate = rollangle / 180.0f;
2438 cstate = cstate - 2.0f;
2445 Vector3 dirv = this->GetCameraDir();
2446 float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y));
2448 cstate = (Math::RadiansToDegrees(pitchangle) / 90.0f);
2455 float airbrake = ar_airbrake_intensity;
2457 cstate -= airbrake / 5.0f;
2471 void Actor::CalcCabCollisions()
2473 for (
int i = 0; i < ar_num_nodes; i++)
2475 ar_nodes[i].nd_has_mesh_contact =
false;
2477 if (m_intra_point_col_detector !=
nullptr)
2479 m_intra_point_col_detector->UpdateIntraPoint();
2481 *m_intra_point_col_detector,
2485 ar_intra_collcabrate,
2488 *ar_submesh_ground_model);
2492 void Actor::CalcShocks2(
int i, Real difftoBeamL, Real& k, Real& d, Real v)
2496 k = ar_beams[i].shock->springout;
2497 d = ar_beams[i].shock->dampout;
2499 float logafactor = 1.0f;
2500 if (ar_beams[i].longbound != 0.0f)
2502 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2503 logafactor = std::min(logafactor * logafactor, 1.0f);
2505 k += ar_beams[i].shock->sprogout * k * logafactor;
2506 d += ar_beams[i].shock->dprogout * d * logafactor;
2510 k = ar_beams[i].shock->springin;
2511 d = ar_beams[i].shock->dampin;
2513 float logafactor = 1.0f;
2514 if (ar_beams[i].shortbound != 0.0f)
2516 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2517 logafactor = std::min(logafactor * logafactor, 1.0f);
2519 k += ar_beams[i].shock->sprogin * k * logafactor;
2520 d += ar_beams[i].shock->dprogin * d * logafactor;
2525 float beamsLep = ar_beams[i].L * 0.8f;
2526 float longboundprelimit = ar_beams[i].longbound * beamsLep;
2527 float shortboundprelimit = -ar_beams[i].shortbound * beamsLep;
2528 if (difftoBeamL > longboundprelimit)
2531 k = ar_beams[i].shock->springout;
2532 d = ar_beams[i].shock->dampout;
2534 float logafactor = 1.0f;
2535 if (ar_beams[i].longbound != 0.0f)
2537 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2538 logafactor = std::min(logafactor * logafactor, 1.0f);
2540 k += ar_beams[i].shock->sprogout * k * logafactor;
2541 d += ar_beams[i].shock->dprogout * d * logafactor;
2544 if (ar_beams[i].longbound != 0.0f)
2546 logafactor = ((difftoBeamL - longboundprelimit) * 5.0f) / (ar_beams[i].longbound * ar_beams[i].L);
2547 logafactor = std::min(logafactor * logafactor, 1.0f);
2549 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2550 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2554 k = ar_beams[i].shock->springin;
2555 d = ar_beams[i].shock->dampin;
2558 else if (difftoBeamL < shortboundprelimit)
2561 k = ar_beams[i].shock->springin;
2562 d = ar_beams[i].shock->dampin;
2564 float logafactor = 1.0f;
2565 if (ar_beams[i].shortbound != 0.0f)
2567 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2568 logafactor = std::min(logafactor * logafactor, 1.0f);
2570 k += ar_beams[i].shock->sprogin * k * logafactor;
2571 d += ar_beams[i].shock->dprogin * d * logafactor;
2574 if (ar_beams[i].shortbound != 0.0f)
2576 logafactor = ((difftoBeamL - shortboundprelimit) * 5.0f) / (ar_beams[i].shortbound * ar_beams[i].L);
2577 logafactor = std::min(logafactor * logafactor, 1.0f);
2579 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2580 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2584 k = ar_beams[i].shock->springout;
2585 d = ar_beams[i].shock->dampout;
2588 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2591 k = std::max(k, ar_beams[i].shock->sbd_spring);
2592 d = std::max(d, ar_beams[i].shock->sbd_damp);
2595 else if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2598 k = ar_beams[i].shock->sbd_spring;
2599 d = ar_beams[i].shock->sbd_damp;
2603 void Actor::CalcShocks3(
int i, Real difftoBeamL, Real &k, Real& d, Real v)
2605 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2607 float interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L;
2608 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2609 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2611 else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2613 float interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L;
2614 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2615 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2619 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2620 k = ar_beams[i].shock->springout;
2621 d = ar_beams[i].shock->dampout * ar_beams[i].shock->dslowout * std::min(v, ar_beams[i].shock->splitout) +
2622 ar_beams[i].shock->dampout * ar_beams[i].shock->dfastout * std::max(0.0f, v - ar_beams[i].shock->splitout);
2627 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2628 k = ar_beams[i].shock->springin;
2629 d = ar_beams[i].shock->dampin * ar_beams[i].shock->dslowin * std::min(v, ar_beams[i].shock->splitin ) +
2630 ar_beams[i].shock->dampin * ar_beams[i].shock->dfastin * std::max(0.0f, v - ar_beams[i].shock->splitin );
2635 void Actor::CalcTriggers(
int i, Real difftoBeamL,
bool trigger_hooks)
2641 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2643 ar_beams[i].shock->trigger_switch_state -= dt;
2644 if (ar_beams[i].shock->trigger_switch_state <= 0.0f)
2645 ar_beams[i].shock->trigger_switch_state = 0.0f;
2648 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2652 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 1)
2654 LOG(
" Trigger disabled. Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2655 ar_beams[i].shock->last_debug_state = 1;
2657 ar_beams[scount].shock->trigger_enabled =
false;
2663 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2667 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 9)
2669 LOG(
" Trigger enabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2670 ar_beams[i].shock->last_debug_state = 9;
2672 ar_beams[scount].shock->trigger_enabled =
true;
2678 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
false;
2679 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 2)
2681 LOG(
" F-key trigger block released. Blocker BeamID " +
TOSTRING(i) +
" Released F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2682 ar_beams[i].shock->last_debug_state = 2;
2687 if (!ar_beams[i].shock->trigger_switch_state)
2689 for (
int scount = 0; scount < ar_num_shocks; scount++)
2691 int short1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2692 int short2 = ar_beams[i].shock->trigger_cmdshort;
2693 int long1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2694 int long2 = ar_beams[i].shock->trigger_cmdlong;
2695 int tmpi = ar_beams[ar_shocks[scount].beamid].shock->beamid;
2696 if (((short1 == short2 && long1 == long2) || (short1 == long2 && long1 == short2)) && i != tmpi)
2698 int tmpcmdkey = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2699 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2700 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort = tmpcmdkey;
2701 ar_beams[i].shock->trigger_switch_state = ar_beams[i].shock->trigger_boundary_t;
2702 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 3)
2704 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));
2705 ar_beams[i].shock->last_debug_state = 3;
2713 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2722 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2735 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2743 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), 1.0f);
2748 if (!ar_command_key[ar_beams[i].shock->trigger_cmdlong].trigger_cmdkeyblock_state)
2751 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2753 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = 1;
2754 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 4)
2756 LOG(
" Trigger Longbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdlong));
2757 ar_beams[i].shock->last_debug_state = 4;
2771 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2784 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2794 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2799 if (!ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2802 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 0;
2804 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2806 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 5)
2808 LOG(
" Trigger Shortbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2809 ar_beams[i].shock->last_debug_state = 5;
2820 if (ar_beams[i].longbound - ar_beams[i].shortbound > 0.0f)
2822 float diffPercentage = difftoBeamL / ar_beams[i].L;
2823 float triggerValue = (diffPercentage - ar_beams[i].shortbound) / (ar_beams[i].longbound - ar_beams[i].shortbound);
2825 triggerValue = std::max(0.0f, triggerValue);
2826 triggerValue = std::min(triggerValue, 1.0f);
2830 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2835 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = triggerValue;
2836 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = triggerValue;
2842 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2846 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 6)
2848 LOG(
" Trigger enabled. Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2849 ar_beams[i].shock->last_debug_state = 6;
2851 ar_beams[scount].shock->trigger_enabled =
true;
2857 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2861 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 10)
2863 LOG(
" Trigger disabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2864 ar_beams[i].shock->last_debug_state = 10;
2866 ar_beams[scount].shock->trigger_enabled =
false;
2872 ar_beams[i].shock->trigger_switch_state = 0.0f;
2873 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 7)
2875 LOG(
" Trigger switch reset. Switch BeamID " +
TOSTRING(i));
2876 ar_beams[i].shock->last_debug_state = 7;
2879 else if ((ar_beams[i].shock->flags &
SHOCK_FLAG_TRG_CMD_BLOCKER) && !ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2881 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
true;
2882 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 8)
2884 LOG(
" F-key trigger blocked. Blocker BeamID " +
TOSTRING(i) +
" Blocked F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2885 ar_beams[i].shock->last_debug_state = 8;
2892 void Actor::setAirbrakeIntensity(
float intensity)
2894 ar_airbrake_intensity = intensity;
2897 ab->updatePosition((
float)ar_airbrake_intensity / 5.0);
2902 void Actor::updateSkidmarks()
2904 for (
int i = 0; i < ar_num_wheels; i++)
2906 if (!m_skid_trails[i])
2909 for (
int j = 0; j < ar_wheels[i].wh_num_nodes; j++)
2911 auto n = ar_wheels[i].wh_nodes[j];
2912 if (!n || !n->nd_has_ground_contact || n->nd_last_collision_gm ==
nullptr ||
2913 n->nd_last_collision_gm->fx_type != Collisions::FX_HARD)
2917 if (n->nd_avg_collision_slip > 6.f && n->nd_last_collision_slip.squaredLength() > 9.f)
2919 m_skid_trails[i]->update(n->AbsPosition, j, n->nd_avg_collision_slip, n->nd_last_collision_gm->name);
2926 void Actor::prepareInside(
bool inside)
2934 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2935 seatmat->setDepthWriteEnabled(
false);
2936 seatmat->setSceneBlending(SBT_TRANSPARENT_ALPHA);
2942 ar_dashboard->setVisible(
false);
2948 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2949 seatmat->setDepthWriteEnabled(
true);
2950 seatmat->setSceneBlending(SBT_REPLACE);
2961 m_gfx_actor->SetCastShadows(!inside);
2965 void Actor::toggleHeadlights()
2969 if (ar_state == ActorState::LOCAL_SIMULATED &&
this == player_actor.
GetRef() && ar_forward_commands)
2973 if (actor->ar_state == ActorState::LOCAL_SIMULATED &&
this != actor.GetRef() && actor->ar_import_commands)
2982 m_gfx_actor->SetCabLightsActive(this->getHeadlightsVisible());
2987 void Actor::forceAllFlaresOff()
2989 for (
size_t i = 0; i < ar_flares.size(); i++)
2991 ar_flares[i].snode->setVisible(
false);
2995 void Actor::updateFlareStates(
float dt)
2997 if (m_flares_mode == GfxFlaresMode::NONE) {
return; }
2999 for (
size_t i = 0; i < this->ar_flares.size(); i++)
3002 if (ar_flares[i].blinkdelay != 0)
3004 ar_flares[i].blinkdelay_curr -= dt;
3005 if (ar_flares[i].blinkdelay_curr <= 0)
3007 ar_flares[i].blinkdelay_curr = ar_flares[i].blinkdelay;
3008 ar_flares[i].blinkdelay_state = !ar_flares[i].blinkdelay_state;
3013 ar_flares[i].blinkdelay_state =
true;
3017 bool isvisible =
false;
3018 switch (ar_flares[i].fl_type)
3029 case FlareType::DASHBOARD: isvisible = ar_dashboard->_getBool(ar_flares[i].dashboard_link);
break;
3030 case FlareType::USER: isvisible = this->getCustomLightVisible(ar_flares[i].controlnumber);
break;
3034 isvisible = isvisible && ar_flares[i].blinkdelay_state;
3037 switch (ar_flares[i].fl_type)
3039 case FlareType::BLINKER_LEFT: m_blinker_left_lit = isvisible;
break;
3040 case FlareType::BLINKER_RIGHT: m_blinker_right_lit = isvisible;
break;
3045 if (ar_flares[i].uses_inertia)
3047 ar_flares[i].intensity = ar_flares[i].inertia.CalcSimpleDelay(isvisible, dt);
3051 ar_flares[i].intensity = (float)isvisible;
3058 if (this->getBlinkType() == blink)
3061 setBlinkType(blink);
3066 if (ar_state == ActorState::DISPOSED)
3098 void Actor::autoBlinkReset()
3103 if (this->getBlinkType() ==
BLINK_LEFT && ar_hydro_dir_state < -blink_lock_range)
3106 m_blinker_autoreset =
true;
3109 if (this->getBlinkType() ==
BLINK_LEFT && m_blinker_autoreset && ar_hydro_dir_state > -blink_lock_range)
3113 m_blinker_autoreset =
false;
3117 if (this->getBlinkType() ==
BLINK_RIGHT && ar_hydro_dir_state > blink_lock_range)
3118 m_blinker_autoreset =
true;
3120 if (this->getBlinkType() ==
BLINK_RIGHT && m_blinker_autoreset && ar_hydro_dir_state < blink_lock_range)
3123 m_blinker_autoreset =
false;
3133 this->toggleHeadlights();
3135 this->beaconsToggle();
3144 this->setBlinkType(btype);
3147 m_lightmask = lightmask;
3153 BITMASK_SET_1(lightmask, m_lightmask & m_flaregroups_no_import);
3155 BITMASK_SET_0(lightmask, ~m_lightmask & m_flaregroups_no_import);
3157 this->setLightStateMask(lightmask);
3160 void Actor::toggleCustomParticles()
3162 if (ar_state == ActorState::DISPOSED)
3165 ar_cparticles_active = !ar_cparticles_active;
3171 void Actor::updateSoundSources()
3176 for (
int i = 0; i < ar_num_soundsources; i++)
3179 ar_soundsources[i].ssi->setPosition(ar_nodes[ar_soundsources[i].nodenum].AbsPosition);
3180 ar_soundsources[i].ssi->setVelocity(ar_nodes[ar_soundsources[i].nodenum].Velocity);
3188 void Actor::updateVisual(
float dt)
3190 Vector3 ref(Vector3::UNIT_Y);
3192 updateSoundSources();
3196 if (ar_driveable ==
AIRPLANE && ar_state != ActorState::LOCAL_SLEEPING)
3199 m_avionic_chatter_timer -= dt;
3200 if (m_avionic_chatter_timer < 0)
3203 m_avionic_chatter_timer = Math::RangeRandom(11, 30);
3209 float autoaileron = 0;
3210 float autorudder = 0;
3211 float autoelevator = 0;
3214 ar_autopilot->UpdateIls();
3215 autoaileron = ar_autopilot->getAilerons();
3216 autorudder = ar_autopilot->getRudder();
3217 autoelevator = ar_autopilot->getElevator();
3218 ar_autopilot->gpws_update(ar_posnode_spawn_height);
3220 autoaileron += ar_aileron;
3221 autorudder += ar_rudder;
3222 autoelevator += ar_elevator;
3223 if (autoaileron < -1.0)
3225 if (autoaileron > 1.0)
3227 if (autorudder < -1.0)
3229 if (autorudder > 1.0)
3231 if (autoelevator < -1.0)
3232 autoelevator = -1.0;
3233 if (autoelevator > 1.0)
3235 for (
int i = 0; i < ar_num_wings; i++)
3237 if (ar_wings[i].fa->type ==
'a')
3238 ar_wings[i].fa->setControlDeflection(autoaileron);
3239 if (ar_wings[i].fa->type ==
'b')
3240 ar_wings[i].fa->setControlDeflection(-autoaileron);
3241 if (ar_wings[i].fa->type ==
'r')
3242 ar_wings[i].fa->setControlDeflection(autorudder);
3243 if (ar_wings[i].fa->type ==
'e' || ar_wings[i].fa->type ==
'S' || ar_wings[i].fa->type ==
'T')
3244 ar_wings[i].fa->setControlDeflection(autoelevator);
3245 if (ar_wings[i].fa->type ==
'f')
3246 ar_wings[i].fa->setControlDeflection(
FLAP_ANGLES[ar_aerial_flap]);
3247 if (ar_wings[i].fa->type ==
'c' || ar_wings[i].fa->type ==
'V')
3248 ar_wings[i].fa->setControlDeflection((autoaileron + autoelevator) / 2.0);
3249 if (ar_wings[i].fa->type ==
'd' || ar_wings[i].fa->type ==
'U')
3250 ar_wings[i].fa->setControlDeflection((-autoaileron + autoelevator) / 2.0);
3251 if (ar_wings[i].fa->type ==
'g')
3252 ar_wings[i].fa->setControlDeflection((autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3253 if (ar_wings[i].fa->type ==
'h')
3254 ar_wings[i].fa->setControlDeflection((-autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3255 if (ar_wings[i].fa->type ==
'i')
3256 ar_wings[i].fa->setControlDeflection((-autoelevator + autorudder) / 2.0);
3257 if (ar_wings[i].fa->type ==
'j')
3258 ar_wings[i].fa->setControlDeflection((autoelevator + autorudder) / 2.0);
3259 ar_wings[i].fa->updateVerticesPhysics();
3262 ar_hydro_aileron_command = autoaileron;
3263 ar_hydro_rudder_command = autorudder;
3264 ar_hydro_elevator_command = autoelevator;
3272 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3274 if (pos == ar_inter_beams.end())
3276 ar_inter_beams.push_back(beam);
3281 std::pair<ActorPtr, ActorPtr> actor_pair(
this, other);
3285 if (linked_before != linked_now)
3288 this->DetermineLinkedActors();
3289 for (
ActorPtr& actor : this->ar_linked_actors)
3290 actor->DetermineLinkedActors();
3297 for (
ActorPtr& actor : this->ar_linked_actors)
3315 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3317 if (pos != ar_inter_beams.end())
3319 ar_inter_beams.erase(pos);
3331 if (linked_before != linked_now)
3334 this->DetermineLinkedActors();
3335 for (
ActorPtr& actor : this->ar_linked_actors)
3336 actor->DetermineLinkedActors();
3340 if (other->
ar_state != ActorState::DISPOSED)
3361 void Actor::DisjoinInterActorBeams()
3369 this->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET);
3370 this->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET);
3371 this->tieToggle(-1, ActorLinkingRequestType::TIE_RESET);
3376 if (other_actor->ar_state != ActorState::LOCAL_SIMULATED)
3380 other_actor->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET,
NODENUM_INVALID, ar_instance_id);
3381 other_actor->tieToggle(-1, ActorLinkingRequestType::TIE_RESET, ar_instance_id);
3382 other_actor->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET, ar_instance_id);
3391 bool istied =
false;
3393 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3396 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3400 if (mode == ActorLinkingRequestType::TIE_RESET
3401 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->ti_locked_actor && it->ti_locked_actor->ar_instance_id != forceunlock_filter)
3409 istied = !it->ti_beam->bm_disabled;
3412 it->ti_tied =
false;
3413 it->ti_tying =
false;
3414 if (it->ti_locked_ropable)
3415 it->ti_locked_ropable->attached_ties--;
3417 it->ti_beam->p2 = &ar_nodes[0];
3418 it->ti_beam->bm_inter_actor =
false;
3419 it->ti_beam->bm_disabled =
true;
3420 if (it->ti_locked_actor !=
this)
3422 this->RemoveInterActorBeam(it->ti_beam, mode);
3424 it->ti_locked_actor =
nullptr;
3429 if (!istied && mode == ActorLinkingRequestType::TIE_TOGGLE)
3431 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3434 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3440 float mindist = it->ti_beam->refL;
3441 node_t* nearest_node = 0;
3447 if (actor->ar_state == ActorState::LOCAL_SLEEPING ||
3448 (actor ==
this && it->ti_no_self_lock))
3454 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3457 if (!itr->multilock && itr->attached_ties > 0)
3461 if (
this == actor.GetRef() && itr->node->pos == it->ti_beam->p1->pos)
3465 float dist = (it->ti_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3469 nearest_node = itr->node;
3470 nearest_actor = actor;
3471 locktedto = &(*itr);
3479 it->ti_beam->bm_disabled =
false;
3481 it->ti_locked_actor = nearest_actor;
3482 it->ti_beam->p2 = nearest_node;
3483 it->ti_beam->bm_inter_actor = nearest_actor !=
this;
3484 it->ti_beam->stress = 0;
3485 it->ti_beam->L = it->ti_beam->refL;
3487 it->ti_tying =
true;
3488 it->ti_locked_ropable = locktedto;
3490 if (it->ti_beam->bm_inter_actor)
3492 this->AddInterActorBeam(it->ti_beam, nearest_actor, mode);
3508 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
3511 if (group != -1 && (it->rp_group != -1 && it->rp_group != group))
3515 if (mode == ActorLinkingRequestType::ROPE_RESET
3516 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->rp_locked_actor && it->rp_locked_actor->ar_instance_id != forceunlock_filter)
3526 if (it->rp_locked_ropable)
3527 it->rp_locked_ropable->attached_ropes--;
3528 if (it->rp_locked_actor !=
this)
3530 this->RemoveInterActorBeam(it->rp_beam, mode);
3532 it->rp_locked_actor =
nullptr;
3533 it->rp_locked_ropable =
nullptr;
3535 else if (mode == ActorLinkingRequestType::ROPE_TOGGLE)
3539 float mindist = it->rp_beam->L;
3545 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3548 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3551 if (!itr->multilock && itr->attached_ropes > 0)
3555 float dist = (it->rp_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3559 nearest_actor = actor;
3569 it->rp_locked_ropable = rop;
3571 if (nearest_actor !=
this)
3573 this->AddInterActorBeam(it->rp_beam, nearest_actor, mode);
3582 ROR_ASSERT(mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK
3583 || mode == ActorLinkingRequestType::HOOK_TOGGLE || mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE
3584 || mode == ActorLinkingRequestType::HOOK_RESET);
3587 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3589 if (mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE && it->hk_hook_node->pos != mousenode)
3594 if (mode == ActorLinkingRequestType::HOOK_TOGGLE && group == -1)
3597 if (it->hk_group <= -2)
3600 if (mode == ActorLinkingRequestType::HOOK_LOCK && group == -2)
3603 if (it->hk_group >= -1 || !it->hk_autolock)
3606 if (mode == ActorLinkingRequestType::HOOK_UNLOCK && group == -2)
3609 if (it->hk_group >= -1 || !it->hk_autolock)
3612 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group <= -3)
3615 if (it->hk_group != group)
3618 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group >= -1)
3622 if (mode == ActorLinkingRequestType::HOOK_LOCK && it->hk_timer > 0.0f)
3629 if (mode == ActorLinkingRequestType::HOOK_RESET
3630 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->hk_locked_actor && it->hk_locked_actor->ar_instance_id != forceunlock_filter)
3635 ActorPtr prev_locked_actor = it->hk_locked_actor;
3638 if ((mode != ActorLinkingRequestType::HOOK_UNLOCK && mode != ActorLinkingRequestType::HOOK_RESET) && it->hk_locked ==
UNLOCKED)
3642 float mindist = it->hk_lockrange;
3643 float distance = 100000000.0f;
3647 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3649 if (
this == actor.GetRef() && !it->hk_selflock)
3652 node_t* nearest_node =
nullptr;
3653 for (
int i = 0; i < actor->ar_num_nodes; i++)
3656 if (actor->ar_nodes[i].nd_lockgroup == 9999)
3660 if (
this == actor.GetRef() && i == it->hk_hook_node->pos)
3664 if (it->hk_lockgroup != -1 && it->hk_lockgroup != actor->ar_nodes[i].nd_lockgroup)
3668 float n2n_distance = (it->hk_hook_node->AbsPosition - actor->ar_nodes[i].AbsPosition).length();
3669 if (n2n_distance < mindist)
3671 if (distance >= n2n_distance)
3674 distance = n2n_distance;
3675 nearest_node = &actor->ar_nodes[i];
3682 it->hk_lock_node = nearest_node;
3683 it->hk_locked_actor = actor;
3686 if (it->hk_beam->bm_disabled)
3688 it->hk_beam->p2 = it->hk_lock_node;
3689 it->hk_beam->bm_inter_actor = (it->hk_locked_actor !=
nullptr);
3690 it->hk_beam->L = (it->hk_hook_node->AbsPosition - it->hk_lock_node->AbsPosition).length();
3691 it->hk_beam->bm_disabled =
false;
3692 this->AddInterActorBeam(it->hk_beam, it->hk_locked_actor, mode);
3698 else if ((it->hk_locked ==
LOCKED || it->hk_locked ==
PRELOCK) && (mode != ActorLinkingRequestType::HOOK_LOCK || !it->hk_beam->bm_inter_actor))
3702 this->RemoveInterActorBeam(it->hk_beam, mode);
3703 if (it->hk_group <= -2)
3705 it->hk_timer = it->hk_timer_preset;
3707 it->hk_lock_node = 0;
3708 it->hk_locked_actor = 0;
3710 it->hk_beam->p2 = &ar_nodes[0];
3711 it->hk_beam->bm_inter_actor =
false;
3712 it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length();
3713 it->hk_beam->bm_disabled =
true;
3718 void Actor::parkingbrakeToggle()
3720 if (ar_state == ActorState::DISPOSED)
3723 ar_parking_brake = !ar_parking_brake;
3725 if (ar_parking_brake)
3733 void Actor::antilockbrakeToggle()
3735 if (ar_state == ActorState::DISPOSED)
3739 alb_mode = !alb_mode;
3742 void Actor::tractioncontrolToggle()
3744 if (ar_state == ActorState::DISPOSED)
3751 void Actor::beaconsToggle()
3753 if (ar_state == ActorState::DISPOSED)
3756 if (m_flares_mode == GfxFlaresMode::NONE)
3767 void Actor::muteAllSounds()
3770 if (ar_state == ActorState::DISPOSED)
3773 for (
int i = 0; i < ar_num_soundsources; i++)
3775 if (ar_soundsources[i].ssi)
3776 ar_soundsources[i].ssi->setEnabled(
false);
3778 #endif // USE_OPENAL
3781 void Actor::unmuteAllSounds()
3784 if (ar_state == ActorState::DISPOSED)
3787 for (
int i = 0; i < ar_num_soundsources; i++)
3789 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3790 ar_soundsources[i].ssi->setEnabled(enabled);
3792 #endif // USE_OPENAL
3795 void Actor::NotifyActorCameraChanged()
3799 if (ar_state == ActorState::DISPOSED)
3802 for (
int i = 0; i < ar_num_soundsources; i++)
3804 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3805 ar_soundsources[i].ssi->setEnabled(enabled);
3807 #endif // USE_OPENAL
3815 int Actor::GetNumActiveConnectedBeams(
int nodeid)
3817 int totallivebeams = 0;
3818 for (
unsigned int ni = 0; ni < ar_node_to_beam_connections[nodeid].size(); ++ni)
3820 if (!ar_beams[ar_node_to_beam_connections[nodeid][ni]].bm_disabled && !ar_beams[ar_node_to_beam_connections[nodeid][ni]].bounded)
3823 return totallivebeams;
3826 bool Actor::isTied()
3828 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3834 bool Actor::isLocked()
3836 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3837 if (it->hk_locked ==
LOCKED)
3842 void Actor::updateDashBoards(
float dt)
3853 int gear = ar_engine->getGear();
3856 int numGears = (int)ar_engine->getNumGears();
3859 String str = String();
3872 int cg = ar_engine->getAutoShift();
3875 str = ((cg ==
Engine::REAR) ?
"#ffffff" :
"#868686") + String(
"R\n");
3876 str += ((cg ==
Engine::NEUTRAL) ?
"#ff0012" :
"#8a000a") + String(
"N\n");
3877 str += ((cg ==
Engine::DRIVE) ?
"#12ff00" :
"#248c00") + String(
"D\n");
3878 str += ((cg ==
Engine::TWO) ?
"#ffffff" :
"#868686") + String(
"2\n");
3879 str += ((cg ==
Engine::ONE) ?
"#ffffff" :
"#868686") + String(
"1");
3884 str =
"#b8b8b8M\na\nn\nu";
3889 int autoGear = ar_engine->getAutoShift();
3893 float clutch = ar_engine->getClutch();
3897 float acc = ar_engine->getAcc();
3901 float rpm = ar_engine->getRPM();
3905 float turbo = ar_engine->getTurboPSI() * 3.34f;
3909 bool ign = (ar_engine->hasContact() && !ar_engine->isRunning());
3913 bool batt = (ar_engine->hasContact() && !ar_engine->isRunning());
3917 bool cw = (fabs(ar_engine->getTorque()) >= ar_engine->getClutchForce() * 10.0f);
3922 ar_dashboard->setFloat(
DD_BRAKE, ar_brake);
3924 Vector3 cam_dir = this->GetCameraDir();
3925 Vector3 cam_roll = this->GetCameraRoll();
3928 float velocity = ar_nodes[0].Velocity.length();
3929 if (cam_dir != Vector3::ZERO)
3931 velocity = cam_dir.dotProduct(ar_nodes[0].Velocity);
3935 float cur_speed_kph = ar_wheel_speed * 3.6f;
3936 float smooth_kph = (cur_speed_kph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_KPH) * 0.7);
3940 float cur_speed_mph = ar_wheel_speed * 2.23693629f;
3941 float smooth_mph = (cur_speed_mph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_MPH) * 0.7);
3945 if (cam_roll != Vector3::ZERO)
3947 float angle = asin(cam_roll.dotProduct(Vector3::UNIT_Y));
3953 float f = Radian(angle).valueDegrees();
3954 ar_dashboard->setFloat(
DD_ROLL, f);
3958 if (this->ar_has_active_shocks)
3961 float roll_corr = - m_stabilizer_shock_ratio * 10.0f;
3964 bool corr_active = (m_stabilizer_shock_request > 0);
3969 if (cam_dir != Vector3::ZERO)
3971 float angle = asin(cam_dir.dotProduct(Vector3::UNIT_Y));
3977 float f = Radian(angle).valueDegrees();
3978 ar_dashboard->setFloat(
DD_PITCH, f);
3985 bool locked = isLocked();
3986 ar_dashboard->setBool(
DD_LOCKED, locked);
3989 bool low_pres = !ar_engine_hydraulics_ready;
3997 int dash_tc_mode = 1;
4000 if (m_tractioncontrol)
4011 int dash_alb_mode = 1;
4014 if (m_antilockbrake)
4026 if (fabs(ar_command_key[0].commandValue) > 0.000001f)
4034 if (ar_num_screwprops)
4039 float throttle = ar_screwprops[i]->getThrottle();
4042 float steering = ar_screwprops[i]->getRudder();
4047 float depth = this->getHeightAboveGround();
4051 Vector3 hdir = this->GetCameraDir();
4052 float knots = hdir.dotProduct(ar_nodes[ar_main_camera_node_pos].Velocity) * 1.9438f;
4057 if (ar_num_aeroengines)
4061 float throttle = ar_aeroengines[i]->getThrottle();
4064 bool failed = ar_aeroengines[i]->isFailed();
4067 float pcent = ar_aeroengines[i]->getRPMpc();
4075 for (
int i = 0; i < ar_num_wings && i <
DD_MAX_WING; i++)
4078 float aoa = ar_wings[i].fa->aoa;
4084 if (ar_num_wings || ar_num_aeroengines)
4088 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438f;
4091 float altitude = ar_nodes[0].AbsPosition.y;
4093 float sea_level_pressure = 101325;
4095 float airpressure = sea_level_pressure * pow(1.0f - 0.0065f * altitude / 288.15f, 5.24947f);
4096 float airdensity = airpressure * 0.0000120896f;
4098 float knots = ground_speed_kt * sqrt(airdensity / 1.225f);
4104 float alt = ar_nodes[0].AbsPosition.y * 1.1811f;
4108 sprintf(altc,
"%03u", (
int)(ar_nodes[0].AbsPosition.y / 30.48f));
4117 if (!m_hud_features_ok)
4119 bool hasEngine = (ar_engine !=
nullptr);
4120 bool hasturbo =
false;
4121 bool autogearVisible =
false;
4125 hasturbo = ar_engine->hasTurbo();
4142 ar_dashboard->setEnabled(
DD_TIES_MODE, !ar_ties.empty());
4143 ar_dashboard->setEnabled(
DD_LOCKED, !ar_hooks.empty());
4147 ar_dashboard->updateFeatures();
4148 m_hud_features_ok =
true;
4174 ar_dashboard->setBool(
DD_SIGNAL_WARNING, m_blinker_right_lit && m_blinker_left_lit);
4183 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;
4185 float rollangle=asin(rollv.dotProduct(Vector3::UNIT_Y));
4188 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;
4190 float pitchangle=asin(dirv.dotProduct(Vector3::UNIT_Y));
4191 Vector3 upv=dirv.crossProduct(-rollv);
4192 if (upv.y<0) rollangle=3.14159-rollangle;
4198 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;
4200 float dirangle=atan2(idir.dotProduct(Vector3::UNIT_X), idir.dotProduct(-Vector3::UNIT_Z));
4202 if (curr_truck->autopilot)
4207 curr_truck->autopilot->getRadioFix(localizers, free_localizer, &vdev, &hdev);
4208 if (hdev>15) hdev=15;
4209 if (hdev<-15) hdev=-15;
4211 if (vdev>15) vdev=15;
4212 if (vdev<-15) vdev=-15;
4217 float vvi=curr_truck->ar_nodes[0].Velocity.y*196.85;
4218 if (vvi<1000.0 && vvi>-1000.0) angle=vvi*0.047;
4219 if (vvi>1000.0 && vvi<6000.0) angle=47.0+(vvi-1000.0)*0.01175;
4220 if (vvi>6000.0) angle=105.75;
4221 if (vvi<-1000.0 && vvi>-6000.0) angle=-47.0+(vvi+1000.0)*0.01175;
4222 if (vvi<-6000.0) angle=-105.75;
4226 if (curr_truck->aeroengines[0]->getType() == AeroEngineType::AE_XPROP)
4233 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4234 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4239 if (ftp>1 && curr_truck->aeroengines[1]->getType() == AeroEngineType::AE_XPROP)
4246 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4247 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4252 if (ftp>2 && curr_truck->aeroengines[2]->getType() == AeroEngineType::AE_XPROP)
4259 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4260 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4265 if (ftp>3 && curr_truck->aeroengines[3]->getType() == AeroEngineType::AE_XPROP)
4272 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4273 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4286 ar_dashboard->
update(dt);
4289 void Actor::calculateLocalGForces()
4291 Vector3 cam_dir = this->GetCameraDir();
4292 Vector3 cam_roll = this->GetCameraRoll();
4293 Vector3 cam_up = cam_dir.crossProduct(cam_roll);
4297 float vertacc = m_camera_gforces.dotProduct(cam_up) + gravity;
4298 float longacc = m_camera_gforces.dotProduct(cam_dir);
4299 float latacc = m_camera_gforces.dotProduct(cam_roll);
4301 m_camera_local_gforces_cur = Vector3(vertacc, longacc, latacc) / gravity;
4304 if (m_reset_timer.getMilliseconds() > 500)
4306 m_camera_local_gforces_max.makeCeil(-m_camera_local_gforces_cur);
4307 m_camera_local_gforces_max.makeCeil(+m_camera_local_gforces_cur);
4323 ar_brake = triggerValue;
4347 unsigned int vector_index,
4352 : ar_nb_optimum(7, std::numeric_limits<float>::max())
4353 , ar_nb_reference(7, std::numeric_limits<float>::max())
4354 , m_tyre_pressure(this)
4355 , ar_nb_beams_scale(std::make_pair(1.0f, 1.0f))
4356 , ar_nb_shocks_scale(std::make_pair(1.0f, 1.0f))
4357 , ar_nb_wheels_scale(std::make_pair(1.0f, 1.0f))
4358 , ar_nb_beams_k_interval(std::make_pair(0.1f, 2.0f))
4359 , ar_nb_beams_d_interval(std::make_pair(0.1f, 2.0f))
4360 , ar_nb_shocks_k_interval(std::make_pair(0.1f, 8.0f))
4361 , ar_nb_shocks_d_interval(std::make_pair(0.1f, 8.0f))
4362 , ar_nb_wheels_k_interval(std::make_pair(1.0f, 1.0f))
4363 , ar_nb_wheels_d_interval(std::make_pair(1.0f, 1.0f))
4366 , m_avg_node_position_prev(rq.asr_position)
4368 , m_avg_node_position(rq.asr_position)
4369 , ar_instance_id(actor_id)
4370 , ar_vector_index(vector_index)
4371 , m_avg_proped_wheel_radius(0.2f)
4372 , ar_filename(rq.asr_cache_entry->fname)
4373 , m_section_config(rq.asr_config)
4374 , m_used_actor_entry(rq.asr_cache_entry)
4375 , m_used_skin_entry(rq.asr_skin_entry)
4376 , m_working_tuneup_def(rq.asr_working_tuneup)
4379 , ar_update_physics(false)
4380 , ar_disable_aerodyn_turbulent_drag(false)
4381 , ar_engine_hydraulics_ready(true)
4382 , ar_guisettings_use_engine_max_rpm(false)
4383 , ar_hydro_speed_coupling(false)
4384 , ar_collision_relevant(false)
4385 , ar_is_police(false)
4386 , ar_rescuer_flag(false)
4387 , ar_forward_commands(false)
4388 , ar_import_commands(false)
4389 , ar_toggle_ropes(false)
4390 , ar_toggle_ties(false)
4393 , m_hud_features_ok(false)
4394 , m_slidenodes_locked(false)
4395 , m_net_initialized(false)
4396 , m_water_contact(false)
4397 , m_water_contact_old(false)
4398 , m_has_command_beams(false)
4399 , ar_cparticles_active(false)
4400 , m_beam_break_debug_enabled(false)
4401 , m_beam_deform_debug_enabled(false)
4402 , m_trigger_debug_enabled(false)
4403 , m_disable_default_sounds(false)
4404 , m_disable_smoke(false)
4479 for (
int i = 0; i <
ar_flares.size(); i++)
4481 if (
ar_flares[i].controlnumber == number)
4490 for (
int i = 0; i <
ar_flares.size(); i++)
4530 return Ogre::MaterialPtr();
4535 std::vector<std::string> names;
4538 names.push_back(it->first);
4551 return Ogre::Vector3::ZERO;
4582 std::stringstream buf;
4584 buf <<
"[nodes]" << std::endl;
4594 <<
", loaded:" << (int)(
ar_nodes[i].nd_loaded_mass)
4596 <<
" wheel_rim:" << (int)
ar_nodes[i].nd_rim_node
4598 <<
" (set_node_defaults)"
4612 buf <<
"[beams]" << std::endl;
4616 <<
" " << std::setw(4) << i
4620 <<
" (set_beam_defaults/scale)"
4621 <<
" spring:" << std::setw(8) <<
ar_beams[i].
k
4622 <<
", damp:" << std::setw(8) <<
ar_beams[i].
d
4632 Ogre::DataStreamPtr outStream = Ogre::ResourceGroupManager::getSingleton().createResource(fileName,
RGN_LOGS,
true);
4633 std::string text = buf.str();
4634 outStream->write(text.c_str(), text.length());
4642 if (state.eventlock_present)
4645 if (ev_active && (ev_active != state.event_active_prev))
4647 state.anim_active = !state.anim_active;
4653 state.anim_active = ev_active;
4655 state.event_active_prev = ev_active;
4836 default:
return 0.f;