71 #include <fmt/format.h>
95 this->DisjoinInterActorBeams();
98 ar_node_to_beam_connections.clear();
99 ar_node_to_node_connections.clear();
102 if (ar_dashboard !=
nullptr)
105 ar_dashboard =
nullptr;
115 for (
int i = 0; i < ar_num_soundsources; i++)
117 if (ar_soundsources[i].ssi)
120 ar_soundsources[i].ssi =
nullptr;
123 ar_num_soundsources = 0;
126 if (ar_engine !=
nullptr)
132 if (ar_autopilot !=
nullptr)
135 ar_autopilot =
nullptr;
138 if (m_fusealge_airfoil)
139 delete m_fusealge_airfoil;
140 m_fusealge_airfoil =
nullptr;
142 if (m_replay_handler)
143 delete m_replay_handler;
144 m_replay_handler =
nullptr;
146 ar_vehicle_ai =
nullptr;
149 if (m_deletion_scene_nodes.size() > 0)
151 for (
unsigned int i = 0; i < m_deletion_scene_nodes.size(); i++)
155 if (!m_deletion_scene_nodes[i])
157 m_deletion_scene_nodes[i]->removeAndDestroyAllChildren();
166 m_deletion_scene_nodes.clear();
169 if (m_deletion_entities.size() > 0)
171 for (
unsigned int i = 0; i < m_deletion_entities.size(); i++)
175 if (!m_deletion_entities[i])
177 m_deletion_entities[i]->detachAllObjectsFromBone();
186 m_deletion_entities.clear();
193 for (
int i = 0; i < ar_num_wings; i++)
199 delete ar_wings[i].fa;
200 if (ar_wings[i].cnode)
202 ar_wings[i].cnode->removeAndDestroyAllChildren();
214 for (
int i = 0; i < ar_num_aeroengines; i++)
216 if (ar_aeroengines[i])
217 delete ar_aeroengines[i];
221 for (
int i = 0; i < ar_num_screwprops; i++)
223 if (ar_screwprops[i])
225 delete ar_screwprops[i];
226 ar_screwprops[i] =
nullptr;
235 ar_airbrakes.clear();
238 for (
int i = 0; i < ar_num_wheels; ++i)
240 delete m_skid_trails[i];
241 m_skid_trails[i] =
nullptr;
245 for (
size_t i = 0; i < this->ar_flares.size(); i++)
249 if (ar_flares[i].snode)
251 ar_flares[i].snode->removeAndDestroyAllChildren();
254 if (ar_flares[i].bbs)
256 if (ar_flares[i].light)
265 this->ar_flares.clear();
268 for (std::vector<exhaust_t>::iterator it = exhausts.begin(); it != exhausts.end(); it++)
274 it->smokeNode->removeAndDestroyAllChildren();
279 it->smoker->removeAllAffectors();
280 it->smoker->removeAllEmitters();
292 for (
int i = 0; i < ar_num_custom_particles; i++)
296 if (ar_custom_particles[i].snode)
298 ar_custom_particles[i].snode->removeAndDestroyAllChildren();
301 if (ar_custom_particles[i].psys)
303 ar_custom_particles[i].psys->removeAllAffectors();
304 ar_custom_particles[i].psys->removeAllEmitters();
316 for (std::vector<RailGroup*>::iterator it = m_railgroups.begin(); it != m_railgroups.end(); it++)
320 m_railgroups.clear();
322 if (m_intra_point_col_detector)
324 delete m_intra_point_col_detector;
325 m_intra_point_col_detector =
nullptr;
328 if (m_inter_point_col_detector)
330 delete m_inter_point_col_detector;
331 m_inter_point_col_detector =
nullptr;
335 delete m_transfer_case;
337 for (
int i = 0; i < m_num_axle_diffs; ++i)
339 if (m_axle_diffs[i] !=
nullptr)
340 delete m_axle_diffs[i];
342 m_num_axle_diffs = 0;
344 for (
int i = 0; i < m_num_wheel_diffs; ++i)
346 if (m_wheel_diffs[i] !=
nullptr)
347 delete m_wheel_diffs[i];
349 m_num_wheel_diffs = 0;
353 m_wheel_node_count = 0;
358 delete[] ar_rotators;
363 ar_state = ActorState::DISPOSED;
368 void Actor::scaleTruck(
float value)
370 if (ar_state == ActorState::DISPOSED)
377 for (
int i = 0; i < ar_num_beams; i++)
380 ar_beams[i].d *= value;
381 ar_beams[i].L *= value;
382 ar_beams[i].refL *= value;
387 hbeam.hb_ref_length *= value;
388 hbeam.hb_speed *= value;
391 Vector3 refpos = ar_nodes[0].AbsPosition;
392 Vector3 relpos = ar_nodes[0].RelPosition;
393 for (
int i = 1; i < ar_num_nodes; i++)
395 ar_initial_node_positions[i] = refpos + (ar_initial_node_positions[i] - refpos) * value;
396 ar_nodes[i].AbsPosition = refpos + (ar_nodes[i].AbsPosition - refpos) * value;
397 ar_nodes[i].RelPosition = relpos + (ar_nodes[i].RelPosition - relpos) * value;
398 ar_nodes[i].Velocity *= value;
399 ar_nodes[i].Forces *= value;
400 ar_nodes[i].mass *= value;
402 updateSlideNodePositions();
404 m_gfx_actor->ScaleActor(relpos, value);
408 float Actor::getRotation()
410 if (ar_state == ActorState::DISPOSED)
413 Vector3 dir = getDirection();
415 return atan2(dir.dotProduct(Vector3::UNIT_X), dir.dotProduct(-Vector3::UNIT_Z));
418 Vector3 Actor::getDirection()
420 return ar_main_camera_dir_corr * this->GetCameraDir();
423 Vector3 Actor::getPosition()
425 return m_avg_node_position;
428 Ogre::Quaternion Actor::getOrientation()
430 Ogre::Vector3 localZ = ar_main_camera_dir_corr * -this->GetCameraDir();
431 Ogre::Vector3 localX = ar_main_camera_dir_corr * this->GetCameraRoll();
432 Ogre::Vector3 localY = localZ.crossProduct(localX);
433 return Ogre::Quaternion(localX, localY, localZ);
436 void Actor::pushNetwork(
char* data,
int size)
442 update.
node_data.resize(m_net_node_buf_size);
443 update.
wheel_data.resize(ar_num_wheels *
sizeof(
float));
456 memcpy(update.
node_data.data(), ptr, m_net_node_buf_size);
457 ptr += m_net_node_buf_size;
460 for (
int i = 0; i < ar_num_wheels; i++)
462 float wspeed = *(
float*)(ptr);
464 ptr +=
sizeof(float);
468 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
471 char byte = *(ptr + (i / 8));
472 char mask = char(1) << (7 - (i % 8));
473 m_prop_anim_key_states[i].anim_active = (
byte & mask);
478 if (!m_net_initialized)
486 strncpy(reg.
name, ar_filename.c_str(), 128);
495 text << info.
username <<
_L(
" content mismatch: ") << reg.name;
502 m_net_initialized =
true;
504 RoR::LogFormat(
"[RoR|Network] Stream mismatch, filename: '%s'", ar_filename.c_str());
509 if (!m_net_initialized)
513 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
514 if (oob->
time > rnow + 100)
520 m_net_updates.push_back(update);
521 #endif // USE_SOCKETW
524 void Actor::calcNetwork()
528 if (m_net_updates.size() < 2)
532 int rnow = std::max(0, tnow +
App::GetGameContext()->GetActorManager()->GetNetTimeOffset(ar_net_source_id));
535 int index_offset = 0;
536 for (
int i = 0; i < m_net_updates.size() - 1; i++)
539 if (oob->
time > rnow)
546 char* netb1 = (
char*) m_net_updates[index_offset ].node_data.data();
547 char* netb2 = (
char*) m_net_updates[index_offset + 1].node_data.data();
548 float* net_rp1 = (
float*) m_net_updates[index_offset ].wheel_data.data();
549 float* net_rp2 = (
float*) m_net_updates[index_offset + 1].wheel_data.data();
551 float tratio = (float)(rnow - oob1->
time) / (float)(oob2->
time - oob1->
time);
555 m_net_updates.clear();
558 else if (tratio > 1.0f)
562 else if (index_offset == 0 && (m_net_updates.size() > 5 || (tratio < 0.125f && m_net_updates.size() > 2)))
567 short* sp1 = (
short*)(netb1 +
sizeof(
float) * 3);
568 short* sp2 = (
short*)(netb2 +
sizeof(
float) * 3);
569 Vector3 p1ref = Vector3::ZERO;
570 Vector3 p2ref = Vector3::ZERO;
571 Vector3 p1 = Vector3::ZERO;
572 Vector3 p2 = Vector3::ZERO;
574 for (
int i = 0; i < m_net_first_wheel_node; i++)
579 p1.x = ((
float*)netb1)[0];
580 p1.y = ((
float*)netb1)[1];
581 p1.z = ((
float*)netb1)[2];
584 p2.x = ((
float*)netb2)[0];
585 p2.y = ((
float*)netb2)[1];
586 p2.z = ((
float*)netb2)[2];
593 p1.x = (float)(sp1[(i - 1) * 3 + 0]) / m_net_node_compression;
594 p1.y = (float)(sp1[(i - 1) * 3 + 1]) / m_net_node_compression;
595 p1.z = (float)(sp1[(i - 1) * 3 + 2]) / m_net_node_compression;
598 p2.x = (float)(sp2[(i - 1) * 3 + 0]) / m_net_node_compression;
599 p2.y = (float)(sp2[(i - 1) * 3 + 1]) / m_net_node_compression;
600 p2.z = (float)(sp2[(i - 1) * 3 + 2]) / m_net_node_compression;
605 ar_nodes[i].AbsPosition = p1 + tratio * (p2 - p1);
606 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
607 ar_nodes[i].Velocity = (p2 - p1) * 1000.0f / (
float)(oob2->
time - oob1->
time);
610 for (
int i = 0; i < ar_num_wheels; i++)
612 float rp = net_rp1[i] + tratio * (net_rp2[i] - net_rp1[i]);
614 Vector3 axis = ar_wheels[i].wh_axis_node_1->RelPosition - ar_wheels[i].wh_axis_node_0->RelPosition;
616 Plane pplan = Plane(axis, ar_wheels[i].wh_axis_node_0->AbsPosition);
617 Vector3 ortho = -pplan.projectVector(ar_wheels[i].wh_near_attach_node->AbsPosition) - ar_wheels[i].wh_axis_node_0->AbsPosition;
618 Vector3 ray = ortho.crossProduct(axis);
620 ray *= ar_wheels[i].wh_radius;
621 float drp = Math::TWO_PI / (ar_wheels[i].wh_num_nodes / 2);
622 for (
int j = 0; j < ar_wheels[i].wh_num_nodes / 2; j++)
624 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
626 ar_wheels[i].wh_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
627 ar_wheels[i].wh_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_nodes[j * 2]->AbsPosition - ar_origin;
629 ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
630 ar_wheels[i].wh_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_nodes[j * 2 + 1]->AbsPosition - ar_origin;
633 ray *= ar_wheels[i].wh_rim_radius;
634 for (
int j = 0; j < ar_wheels[i].wh_num_rim_nodes / 2; j++)
636 Vector3 uray = Quaternion(Radian(rp - drp * j), axis) * ray;
638 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->AbsPosition = ar_wheels[i].wh_axis_node_0->AbsPosition + uray;
639 ar_wheels[i].wh_rim_nodes[j * 2 + 0]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2]->AbsPosition - ar_origin;
641 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition = ar_wheels[i].wh_axis_node_1->AbsPosition + uray;
642 ar_wheels[i].wh_rim_nodes[j * 2 + 1]->RelPosition = ar_wheels[i].wh_rim_nodes[j * 2 + 1]->AbsPosition - ar_origin;
645 this->UpdateBoundingBoxes();
646 this->calculateAveragePosition();
655 ar_wheel_speed = netwspeed;
665 if (ar_num_aeroengines > 0)
687 ar_engine->PushNetworkState(engspeed, engforce, engclutch, gear, running, contact, automode);
692 toggleCustomParticles();
698 this->setLightStateMask(oob1->
lightmask);
710 for (
int i = 0; i < index_offset; i++)
712 m_net_updates.pop_front();
715 m_net_initialized =
true;
718 void Actor::RecalculateNodeMasses(Real total)
721 for (
int i = 0; i < ar_num_nodes; i++)
723 if (!ar_nodes[i].nd_tyre_node)
725 if (!ar_nodes[i].nd_loaded_mass)
727 ar_nodes[i].mass = 0;
729 else if (!ar_nodes[i].nd_override_mass)
731 ar_nodes[i].mass = m_load_mass / (float)m_masscount;
737 for (
int i = 0; i < ar_num_beams; i++)
741 Real half_newlen = ar_beams[i].L / 2.0;
742 if (!ar_beams[i].p1->nd_tyre_node)
744 if (!ar_beams[i].p2->nd_tyre_node)
749 for (
int i = 0; i < ar_num_beams; i++)
753 Real half_mass = ar_beams[i].L * total / len / 2.0f;
754 if (!ar_beams[i].p1->nd_tyre_node)
755 ar_beams[i].p1->mass += half_mass;
756 if (!ar_beams[i].p2->nd_tyre_node)
757 ar_beams[i].p2->mass += half_mass;
761 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
763 it->rp_beam->p2->mass = 100.0f;
767 for (
int i = 0; i < this->ar_num_cinecams; ++i)
770 ar_nodes[ar_cinecam_node[i]].mass = m_definition->root_module->cinecam[i].node_mass;
774 for (
int i = 0; i < ar_num_nodes; i++)
776 if (!ar_nodes[i].nd_tyre_node &&
777 !(ar_minimass_skip_loaded_nodes && ar_nodes[i].nd_loaded_mass) &&
778 ar_nodes[i].mass < ar_minimass[i])
783 snprintf(buf, 300,
"Node '%d' mass (%f Kg) is too light. Resetting to 'minimass' (%f Kg)", i, ar_nodes[i].mass, ar_minimass[i]);
786 ar_nodes[i].mass = ar_minimass[i];
791 for (
int i = 0; i < ar_num_nodes; i++)
795 String msg =
"Node " +
TOSTRING(i) +
" : " +
TOSTRING((
int)ar_nodes[i].mass) +
" kg";
796 if (ar_nodes[i].nd_loaded_mass)
798 if (ar_nodes[i].nd_override_mass)
799 msg +=
" (overriden by node mass)";
801 msg +=
" (normal load node: " +
TOSTRING(m_load_mass) +
" kg / " +
TOSTRING(m_masscount) +
" nodes)";
805 m_total_mass += ar_nodes[i].mass;
807 LOG(
"TOTAL VEHICLE MASS: " +
TOSTRING((
int)m_total_mass) +
" kg");
810 float Actor::getTotalMass(
bool withLocked)
812 if (ar_state == ActorState::DISPOSED)
818 float mass = m_total_mass;
820 for (
ActorPtr& actor : ar_linked_actors)
822 mass += actor->m_total_mass;
828 void Actor::DetermineLinkedActors()
833 ar_linked_actors.clear();
836 std::map<ActorPtr, bool> lookup_table;
838 lookup_table.insert(std::pair<ActorPtr, bool>(
this,
false));
844 for (
auto it_actor = lookup_table.begin(); it_actor != lookup_table.end(); ++it_actor)
846 if (!it_actor->second)
851 auto actor_pair = inter_actor_link.second;
852 if (actor == actor_pair.first || actor == actor_pair.second)
854 auto other_actor = (actor != actor_pair.first) ? actor_pair.first : actor_pair.second;
855 auto ret = lookup_table.insert(std::pair<ActorPtr, bool>(other_actor,
false));
858 ar_linked_actors.push_back(other_actor);
863 it_actor->second =
true;
869 int Actor::getWheelNodeCount()
const
871 return m_wheel_node_count;
874 void Actor::calcNodeConnectivityGraph()
878 ar_node_to_node_connections.resize(ar_num_nodes, std::vector<int>());
879 ar_node_to_beam_connections.resize(ar_num_nodes, std::vector<int>());
881 for (i = 0; i < ar_num_beams; i++)
883 if (ar_beams[i].p1 != NULL && ar_beams[i].p2 != NULL && ar_beams[i].p1->pos >= 0 && ar_beams[i].p2->pos >= 0)
885 ar_node_to_node_connections[ar_beams[i].p1->pos].push_back(ar_beams[i].p2->pos);
886 ar_node_to_beam_connections[ar_beams[i].p1->pos].push_back(i);
887 ar_node_to_node_connections[ar_beams[i].p2->pos].push_back(ar_beams[i].p1->pos);
888 ar_node_to_beam_connections[ar_beams[i].p2->pos].push_back(i);
893 bool Actor::Intersects(
ActorPtr actor, Vector3 offset)
895 Vector3 bb_min = ar_bounding_box.getMinimum() + offset;
896 Vector3 bb_max = ar_bounding_box.getMaximum() + offset;
897 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
903 for (
int i = 0; i < ar_num_beams; i++)
905 if (!(ar_beams[i].p1->nd_contacter || ar_beams[i].p1->nd_contactable) ||
906 !(ar_beams[i].p2->nd_contacter || ar_beams[i].p2->nd_contactable))
909 Vector3 origin = ar_beams[i].p1->AbsPosition + offset;
910 Vector3 target = ar_beams[i].p2->AbsPosition + offset;
912 Ray ray(origin, target - origin);
921 auto result = Ogre::Math::intersects(ray, a, b, c);
922 if (result.first && result.second < 1.0f)
939 Ray ray(origin, target - origin);
941 for (
int j = 0; j < ar_num_collcabs; j++)
943 int index = ar_collcabs[j] * 3;
944 Vector3 a = ar_nodes[ar_cabs[index + 0]].AbsPosition + offset;
945 Vector3 b = ar_nodes[ar_cabs[index + 1]].AbsPosition + offset;
946 Vector3 c = ar_nodes[ar_cabs[index + 2]].AbsPosition + offset;
948 auto result = Ogre::Math::intersects(ray, a, b, c);
949 if (result.first && result.second < 1.0f)
959 Vector3 Actor::calculateCollisionOffset(Vector3 direction)
961 if (direction == Vector3::ZERO)
962 return Vector3::ZERO;
964 Real max_distance = direction.normalise();
967 Vector3 collision_offset = Vector3::ZERO;
969 while (collision_offset.length() < max_distance)
971 Vector3 bb_min = ar_bounding_box.getMinimum() + collision_offset;
972 Vector3 bb_max = ar_bounding_box.getMaximum() + collision_offset;
973 AxisAlignedBox bb = AxisAlignedBox(bb_min, bb_max);
975 bool collision =
false;
981 if (!bb.intersects(actor->ar_bounding_box))
985 if (m_intra_point_col_detector)
987 for (
int i = 0; i < actor->ar_num_collcabs; i++)
989 int tmpv = actor->ar_collcabs[i] * 3;
990 node_t* no = &actor->ar_nodes[actor->ar_cabs[tmpv]];
991 node_t* na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]];
992 node_t* nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]];
994 m_intra_point_col_detector->query(no->
AbsPosition - collision_offset,
997 actor->ar_collision_range * 3.0f);
999 if (collision = !m_intra_point_col_detector->hit_list.empty())
1007 float proximity = std::max(.05f, std::sqrt(std::max(m_min_camera_radius, actor->m_min_camera_radius)) / 50.f);
1010 for (
int i = 0; i < ar_num_nodes; i++)
1012 if (!ar_nodes[i].nd_contacter && !ar_nodes[i].nd_contactable)
1015 Vector3 query_position = ar_nodes[i].AbsPosition + collision_offset;
1017 for (
int j = 0; j < actor->ar_num_nodes; j++)
1019 if (!actor->ar_nodes[j].nd_contacter && !actor->ar_nodes[j].nd_contactable)
1022 if (collision = query_position.squaredDistance(actor->ar_nodes[j].AbsPosition) < proximity)
1035 if (!collision && m_inter_point_col_detector)
1037 for (
int i = 0; i < ar_num_collcabs; i++)
1039 int tmpv = ar_collcabs[i] * 3;
1040 node_t* no = &ar_nodes[ar_cabs[tmpv]];
1041 node_t* na = &ar_nodes[ar_cabs[tmpv + 1]];
1042 node_t* nb = &ar_nodes[ar_cabs[tmpv + 2]];
1044 m_inter_point_col_detector->query(no->
AbsPosition + collision_offset,
1047 ar_collision_range * 3.0f);
1049 if (collision = !m_inter_point_col_detector->hit_list.empty())
1061 if (collision = this->Intersects(actor, collision_offset))
1069 collision_offset += direction * 0.05f;
1072 return collision_offset;
1075 void Actor::resolveCollisions(Ogre::Vector3 direction)
1077 if (m_intra_point_col_detector)
1078 m_intra_point_col_detector->UpdateIntraPoint(
true);
1080 if (m_inter_point_col_detector)
1081 m_inter_point_col_detector->UpdateInterPoint(
true);
1083 Vector3 offset = calculateCollisionOffset(direction);
1085 if (offset == Vector3::ZERO)
1089 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1091 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
false, this->getMinHeight() + offset.y);
1094 void Actor::resolveCollisions(
float max_distance,
bool consider_up)
1096 if (m_intra_point_col_detector)
1097 m_intra_point_col_detector->UpdateIntraPoint(
true);
1099 if (m_inter_point_col_detector)
1100 m_inter_point_col_detector->UpdateInterPoint(
true);
1102 Vector3 u = Vector3::UNIT_Y;
1103 Vector3 f = Vector3(getDirection().
x, 0.0f, getDirection().
z).normalisedCopy();
1104 Vector3 l = u.crossProduct(f);
1107 Vector3 left = calculateCollisionOffset(+l * max_distance);
1108 Vector3 right = calculateCollisionOffset(-l * left.length());
1109 Vector3 lateral = left.length() < right.length() * 1.1f ? left : right;
1111 Vector3 front = calculateCollisionOffset(+f * lateral.length());
1112 Vector3 back = calculateCollisionOffset(-f * front.length());
1113 Vector3 sagittal = front.length() < back.length() * 1.1f ? front : back;
1115 Vector3 offset = lateral.length() < sagittal.length() * 1.2f ? lateral : sagittal;
1119 Vector3 up = calculateCollisionOffset(+u * offset.length());
1120 if (up.length() * 1.2f < offset.length())
1124 if (offset == Vector3::ZERO)
1128 offset += 0.2f * Vector3(offset.x, 0.0f, offset.z).normalisedCopy();
1130 resetPosition(ar_nodes[0].AbsPosition.x + offset.x, ar_nodes[0].AbsPosition.z + offset.z,
true, this->getMinHeight() + offset.y);
1133 void Actor::calculateAveragePosition()
1138 m_avg_node_position = ar_nodes[ar_custom_camera_node].AbsPosition;
1140 else if (ar_extern_camera_mode == ExtCameraMode::CINECAM && ar_num_cinecams > 0)
1143 m_avg_node_position = ar_nodes[ar_cinecam_node[0]].AbsPosition;
1145 else if (ar_extern_camera_mode == ExtCameraMode::NODE && ar_extern_camera_node !=
NODENUM_INVALID)
1148 m_avg_node_position = ar_nodes[ar_extern_camera_node].AbsPosition;
1153 Vector3 aposition = Vector3::ZERO;
1154 for (
int n = 0; n < ar_num_nodes; n++)
1156 aposition += ar_nodes[n].AbsPosition;
1158 m_avg_node_position = aposition / ar_num_nodes;
1168 void Actor::UpdateBoundingBoxes()
1171 ar_bounding_box = AxisAlignedBox::BOX_NULL;
1172 ar_predicted_bounding_box = AxisAlignedBox::BOX_NULL;
1173 ar_evboxes_bounding_box = AxisAlignedBox::BOX_NULL;
1174 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1176 ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1177 ar_predicted_coll_bounding_boxes[i] = AxisAlignedBox::BOX_NULL;
1182 const float CABNODE_MAX_CAMDIST = 15.f;
1183 const Ogre::Vector3 mainCamPos = ar_nodes[ar_main_camera_node_pos].RelPosition;
1186 for (
int i = 0; i < ar_num_nodes; i++)
1188 Vector3 vel = ar_nodes[i].Velocity;
1189 Vector3 pos = ar_nodes[i].AbsPosition;
1190 int16_t cid = ar_nodes[i].nd_coll_bbox_id;
1192 ar_bounding_box.merge(pos);
1193 if (mainCamPos.squaredDistance(ar_nodes[i].RelPosition) < (CABNODE_MAX_CAMDIST*CABNODE_MAX_CAMDIST))
1195 ar_evboxes_bounding_box.merge(pos);
1197 ar_predicted_bounding_box.merge(pos);
1198 ar_predicted_bounding_box.merge(pos + vel);
1199 if (cid != node_t::INVALID_BBOX)
1201 ar_collision_bounding_boxes[cid].merge(pos);
1202 ar_predicted_coll_bounding_boxes[cid].merge(pos);
1203 ar_predicted_coll_bounding_boxes[cid].merge(pos + vel);
1210 for (
size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i)
1217 void Actor::UpdatePhysicsOrigin()
1219 if (ar_nodes[0].RelPosition.squaredLength() > 10000.0)
1221 Vector3 offset = ar_nodes[0].RelPosition;
1222 ar_origin += offset;
1223 for (
int i = 0; i < ar_num_nodes; i++)
1225 ar_nodes[i].RelPosition -= offset;
1230 void Actor::ResetAngle(
float rot)
1233 Vector3 origin = ar_nodes[ar_main_camera_node_pos].AbsPosition;
1237 matrix.FromEulerAnglesXYZ(Radian(0), Radian(-rot + m_spawn_rotation), Radian(0));
1239 for (
int i = 0; i < ar_num_nodes; i++)
1242 ar_nodes[i].AbsPosition -= origin;
1243 ar_nodes[i].AbsPosition = matrix * ar_nodes[i].AbsPosition;
1244 ar_nodes[i].AbsPosition += origin;
1245 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - this->ar_origin;
1248 this->UpdateBoundingBoxes();
1249 calculateAveragePosition();
1252 void Actor::updateInitPosition()
1254 for (
int i = 0; i < ar_num_nodes; i++)
1256 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1260 void Actor::resetPosition(
float px,
float pz,
bool setInitPosition,
float miny)
1263 Vector3 offset = Vector3(px, ar_nodes[0].AbsPosition.y, pz) - ar_nodes[0].AbsPosition;
1264 for (
int i = 0; i < ar_num_nodes; i++)
1266 ar_nodes[i].AbsPosition += offset;
1267 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1271 float vertical_offset = miny - this->getMinHeight();
1274 vertical_offset += std::max(0.0f,
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight() - miny);
1276 for (
int i = 1; i < ar_num_nodes; i++)
1278 if (ar_nodes[i].nd_no_ground_contact)
1281 vertical_offset += std::max(0.0f, terrainHeight - (ar_nodes[i].AbsPosition.y + vertical_offset));
1283 for (
int i = 0; i < ar_num_nodes; i++)
1285 ar_nodes[i].AbsPosition.y += vertical_offset;
1286 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1290 float mesh_offset = 0.0f;
1291 for (
int i = 0; i < ar_num_nodes; i++)
1293 if (mesh_offset >= 1.0f)
1295 if (ar_nodes[i].nd_no_ground_contact)
1297 float offset = mesh_offset;
1298 while (offset < 1.0f)
1300 Vector3 query = ar_nodes[i].AbsPosition + Vector3(0.0f, offset, 0.0f);
1301 if (!
App::GetGameContext()->GetTerrain()->GetCollisions()->collisionCorrect(&query,
false))
1303 mesh_offset = offset;
1309 for (
int i = 0; i < ar_num_nodes; i++)
1311 ar_nodes[i].AbsPosition.y += mesh_offset;
1312 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1315 resetPosition(Vector3::ZERO, setInitPosition);
1318 void Actor::resetPosition(Ogre::Vector3 translation,
bool setInitPosition)
1321 if (translation != Vector3::ZERO)
1323 Vector3 offset = translation - ar_nodes[0].AbsPosition;
1324 for (
int i = 0; i < ar_num_nodes; i++)
1326 ar_nodes[i].AbsPosition += offset;
1327 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1331 if (setInitPosition)
1333 for (
int i = 0; i < ar_num_nodes; i++)
1335 ar_initial_node_positions[i] = ar_nodes[i].AbsPosition;
1339 this->UpdateBoundingBoxes();
1340 calculateAveragePosition();
1343 void Actor::mouseMove(
NodeNum_t node, Vector3 pos,
float force)
1345 m_mouse_grab_node = node;
1346 m_mouse_grab_move_force = force * std::pow(m_total_mass / 3000.0f, 0.75f);
1347 m_mouse_grab_pos = pos;
1350 void Actor::toggleWheelDiffMode()
1352 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1354 m_wheel_diffs[i]->ToggleDifferentialMode();
1358 void Actor::toggleAxleDiffMode()
1360 for (
int i = 0; i < m_num_axle_diffs; ++i)
1362 m_axle_diffs[i]->ToggleDifferentialMode();
1366 void Actor::displayAxleDiffMode()
1368 if (m_num_axle_diffs == 0)
1371 _L(
"No inter-axle differential installed on current vehicle!"),
"error.png");
1375 String message =
"";
1376 for (
int i = 0; i < m_num_axle_diffs; ++i)
1378 if (m_axle_diffs[i])
1383 int a1 = m_axle_diffs[i]->di_idx_1 + 1;
1384 int a2 = m_axle_diffs[i]->di_idx_2 + 1;
1386 message += m_axle_diffs[i]->GetDifferentialTypeName();
1390 "Inter-axle differentials:\n" + message,
"cog.png");
1394 void Actor::displayWheelDiffMode()
1396 if (m_num_wheel_diffs == 0)
1399 _L(
"No inter-wheel differential installed on current vehicle!"),
"error.png");
1403 String message =
"";
1404 for (
int i = 0; i < m_num_wheel_diffs; ++i)
1406 if (m_wheel_diffs[i])
1411 message +=
_L(
"Axle ") +
TOSTRING(i + 1) +
": ";
1412 message += m_wheel_diffs[i]->GetDifferentialTypeName();
1416 "Inter-wheel differentials:\n" + message,
"cog.png");
1420 void Actor::displayTransferCaseMode()
1422 if (m_transfer_case)
1425 _L(
"Transfercase switched to: ") + this->getTransferCaseName(),
"cog.png");
1430 _L(
"No transfercase installed on current vehicle!"),
"error.png");
1434 void Actor::toggleTransferCaseMode()
1436 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_ax_2 < 0 || !m_transfer_case->tr_2wd)
1439 if (m_transfer_case->tr_4wd_mode && !m_transfer_case->tr_2wd_lo)
1441 for (
int i = 0; i < m_transfer_case->tr_gear_ratios.size(); i++)
1443 this->toggleTransferCaseGearRatio();
1444 if (m_transfer_case->tr_gear_ratios[0] == 1.0f)
1449 m_transfer_case->tr_4wd_mode = !m_transfer_case->tr_4wd_mode;
1451 if (m_transfer_case->tr_4wd_mode)
1453 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
true;
1454 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
true;
1455 m_num_proped_wheels += 2;
1459 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_1].wh_propulsed =
false;
1460 ar_wheels[m_wheel_diffs[m_transfer_case->tr_ax_2]->di_idx_2].wh_propulsed =
false;
1461 m_num_proped_wheels -= 2;
1465 void Actor::toggleTransferCaseGearRatio()
1467 if (!ar_engine || !m_transfer_case || m_transfer_case->tr_gear_ratios.size() < 2)
1470 if (m_transfer_case->tr_4wd_mode || m_transfer_case->tr_2wd_lo)
1472 auto gear_ratios = &m_transfer_case->tr_gear_ratios;
1473 std::rotate(gear_ratios->begin(), gear_ratios->begin() + 1, gear_ratios->end());
1475 ar_engine->SetTCaseRatio(m_transfer_case->tr_gear_ratios[0]);
1479 String Actor::getTransferCaseName()
1482 if (m_transfer_case)
1484 name += m_transfer_case->tr_4wd_mode ?
"4WD " :
"2WD ";
1485 if (m_transfer_case->tr_gear_ratios[0] > 1.0f)
1486 name +=
"Lo (" +
TOSTRING(m_transfer_case->tr_gear_ratios[0]) +
":1)";
1493 Ogre::Vector3 Actor::getRotationCenter()
1495 Vector3 sum = Vector3::ZERO;
1496 std::vector<Vector3> positions;
1497 for (
int i = 0; i < ar_num_nodes; i++)
1499 Vector3 pos = ar_nodes[i].AbsPosition;
1500 const auto it = std::find_if(positions.begin(), positions.end(),
1501 [pos](
const Vector3 ref) { return pos.positionEquals(ref, 0.01f); });
1502 if (it == positions.end())
1505 positions.push_back(pos);
1508 return sum / positions.size();
1511 float Actor::getMinHeight(
bool skip_virtual_nodes)
1513 float height = std::numeric_limits<float>::max();
1514 for (
int i = 0; i < ar_num_nodes; i++)
1516 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1518 height = std::min(ar_nodes[i].AbsPosition.y, height);
1521 return (!skip_virtual_nodes || height < std::numeric_limits<float>::max()) ? height : getMinHeight(
false);
1524 float Actor::getMaxHeight(
bool skip_virtual_nodes)
1526 float height = std::numeric_limits<float>::min();
1527 for (
int i = 0; i < ar_num_nodes; i++)
1529 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1531 height = std::max(height, ar_nodes[i].AbsPosition.y);
1534 return (!skip_virtual_nodes || height > std::numeric_limits<float>::min()) ? height : getMaxHeight(
false);
1537 float Actor::getHeightAboveGround(
bool skip_virtual_nodes)
1539 float agl = std::numeric_limits<float>::max();
1540 for (
int i = 0; i < ar_num_nodes; i++)
1542 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1544 Vector3 pos = ar_nodes[i].AbsPosition;
1548 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGround(
false);
1551 float Actor::getHeightAboveGroundBelow(
float height,
bool skip_virtual_nodes)
1553 float agl = std::numeric_limits<float>::max();
1554 for (
int i = 0; i < ar_num_nodes; i++)
1556 if (!skip_virtual_nodes || !ar_nodes[i].nd_no_ground_contact)
1558 Vector3 pos = ar_nodes[i].AbsPosition;
1562 return (!skip_virtual_nodes || agl < std::numeric_limits<float>::max()) ? agl : getHeightAboveGroundBelow(height,
false);
1565 void Actor::reset(
bool keep_position)
1567 if (ar_state == ActorState::DISPOSED)
1572 rq->
amr_type = (keep_position) ? ActorModifyRequest::Type::RESET_ON_SPOT : ActorModifyRequest::Type::RESET_ON_INIT_POS;
1576 void Actor::SoftReset()
1580 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1584 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1589 Vector3 translation = -agl * Vector3::UNIT_Y;
1590 this->resetPosition(ar_nodes[0].AbsPosition + translation,
false);
1591 for (
ActorPtr& actor : ar_linked_actors)
1593 actor->resetPosition(actor->ar_nodes[0].AbsPosition + translation,
false);
1597 m_ongoing_reset =
true;
1600 void Actor::SyncReset(
bool reset_position)
1604 m_reset_timer.reset();
1606 m_camera_local_gforces_cur = Vector3::ZERO;
1607 m_camera_local_gforces_max = Vector3::ZERO;
1609 ar_hydro_dir_state = 0.0;
1610 ar_hydro_aileron_state = 0.0;
1611 ar_hydro_rudder_state = 0.0;
1612 ar_hydro_elevator_state = 0.0;
1613 ar_hydro_dir_wheel_display = 0.0;
1615 ar_fusedrag = Vector3::ZERO;
1617 ar_parking_brake =
false;
1618 ar_trailer_parking_brake =
false;
1619 ar_avg_wheel_speed = 0.0f;
1620 ar_wheel_speed = 0.0f;
1621 ar_wheel_spin = 0.0f;
1624 ar_origin = Vector3::ZERO;
1625 float cur_rot = getRotation();
1626 Vector3 cur_position = ar_nodes[0].AbsPosition;
1628 this->DisjoinInterActorBeams();
1630 for (
int i = 0; i < ar_num_nodes; i++)
1632 ar_nodes[i].AbsPosition = ar_initial_node_positions[i];
1633 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1634 ar_nodes[i].Velocity = Vector3::ZERO;
1635 ar_nodes[i].Forces = Vector3::ZERO;
1638 for (
int i = 0; i < ar_num_beams; i++)
1640 ar_beams[i].maxposstress = ar_beams[i].default_beam_deform;
1641 ar_beams[i].maxnegstress = -ar_beams[i].default_beam_deform;
1642 ar_beams[i].minmaxposnegstress = ar_beams[i].default_beam_deform;
1643 ar_beams[i].strength = ar_beams[i].initial_beam_strength;
1644 ar_beams[i].L = ar_beams[i].refL;
1645 ar_beams[i].stress = 0.0;
1646 ar_beams[i].bm_broken =
false;
1647 ar_beams[i].bm_disabled =
false;
1650 this->applyNodeBeamScales();
1654 for (
auto& h : ar_hooks)
1656 h.hk_beam->bm_disabled =
true;
1659 for (
auto& t : ar_ties)
1661 t.ti_locked_ropable =
nullptr;
1662 t.ti_beam->bm_disabled =
true;
1667 for (
auto& r : ar_ropables)
1669 r.attached_ties = 0;
1670 r.attached_ropes = 0;
1673 for (
int i = 0; i < ar_num_wheels; i++)
1675 ar_wheels[i].wh_speed = 0.0;
1676 ar_wheels[i].wh_torque = 0.0;
1677 ar_wheels[i].wh_avg_speed = 0.0;
1678 ar_wheels[i].wh_is_detached =
false;
1685 ar_engine->StartEngine();
1687 ar_engine->SetWheelSpin(0.0f);
1690 int num_axle_diffs = (m_transfer_case && m_transfer_case->tr_4wd_mode) ? m_num_axle_diffs + 1 : m_num_axle_diffs;
1691 for (
int i = 0; i < num_axle_diffs; i++)
1692 m_axle_diffs[i]->di_delta_rotation = 0.0f;
1693 for (
int i = 0; i < m_num_wheel_diffs; i++)
1694 m_wheel_diffs[i]->di_delta_rotation = 0.0f;
1695 for (
int i = 0; i < ar_num_aeroengines; i++)
1696 ar_aeroengines[i]->reset();
1697 for (
int i = 0; i < ar_num_screwprops; i++)
1698 ar_screwprops[i]->reset();
1699 for (
int i = 0; i < ar_num_rotators; i++)
1700 ar_rotators[i].angle = 0.0;
1701 for (
int i = 0; i < ar_num_wings; i++)
1702 ar_wings[i].fa->broken =
false;
1704 this->ar_autopilot->reset();
1706 m_buoyance->sink =
false;
1710 hydrobeam.hb_inertia.ResetCmdKeyDelay();
1713 this->GetGfxActor()->ResetFlexbodies();
1716 if (!reset_position)
1718 this->ResetAngle(cur_rot);
1719 this->resetPosition(cur_position,
false);
1720 float agl = this->getHeightAboveGroundBelow(this->getMaxHeight(
true),
true);
1723 agl = std::min(this->getMinHeight(
true) -
App::GetGameContext()->GetTerrain()->getWater()->GetStaticWaterHeight(), agl);
1727 this->resetPosition(ar_nodes[0].AbsPosition - agl * Vector3::UNIT_Y,
false);
1732 this->UpdateBoundingBoxes();
1733 this->calculateAveragePosition();
1738 ar_command_key[i].commandValue = 0.0;
1739 ar_command_key[i].triggerInputValue = 0.0f;
1740 ar_command_key[i].playerInputValue = 0.0f;
1741 for (
auto& b : ar_command_key[i].beams)
1743 b.cmb_state->auto_moving_mode = 0;
1744 b.cmb_state->pressed_center_mode =
false;
1748 this->resetSlideNodes();
1749 if (m_slidenodes_locked)
1751 this->toggleSlideNodeLock();
1754 m_ongoing_reset =
true;
1757 void Actor::applyNodeBeamScales()
1759 for (
int i = 0; i < ar_num_nodes; i++)
1761 ar_nodes[i].mass = ar_initial_node_masses[i] * ar_nb_mass_scale;
1764 m_total_mass = ar_initial_total_mass * ar_nb_mass_scale;
1766 for (
int i = 0; i < ar_num_beams; i++)
1768 if ((ar_beams[i].p1->nd_tyre_node || ar_beams[i].p1->nd_rim_node) ||
1769 (ar_beams[i].p2->nd_tyre_node || ar_beams[i].p2->nd_rim_node))
1771 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_wheels_scale.first;
1772 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_wheels_scale.second;
1774 else if (ar_beams[i].bounded ==
SHOCK1 || ar_beams[i].bounded ==
SHOCK2 || ar_beams[i].bounded ==
SHOCK3)
1776 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_shocks_scale.first;;
1777 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_shocks_scale.second;
1781 ar_beams[i].k = ar_initial_beam_defaults[i].first * ar_nb_beams_scale.first;
1782 ar_beams[i].d = ar_initial_beam_defaults[i].second * ar_nb_beams_scale.second;
1787 void Actor::ForceFeedbackStep(
int steps)
1789 m_force_sensors.out_body_forces = m_force_sensors.accu_body_forces / steps;
1790 if (!ar_hydros.empty())
1792 m_force_sensors.out_hydros_forces = (m_force_sensors.accu_hydros_forces / steps) / ar_hydros.size();
1796 void Actor::HandleAngelScriptEvents(
float dt)
1798 #ifdef USE_ANGELSCRIPT
1800 if (m_water_contact && !m_water_contact_old)
1802 m_water_contact_old = m_water_contact;
1805 #endif // USE_ANGELSCRIPT
1808 void Actor::searchBeamDefaults()
1812 auto old_beams_scale = ar_nb_beams_scale;
1813 auto old_shocks_scale = ar_nb_shocks_scale;
1814 auto old_wheels_scale = ar_nb_wheels_scale;
1816 if (ar_nb_initialized)
1818 ar_nb_beams_scale.first = Math::RangeRandom(ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1819 ar_nb_beams_scale.second = Math::RangeRandom(ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1820 ar_nb_shocks_scale.first = Math::RangeRandom(ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1821 ar_nb_shocks_scale.second = Math::RangeRandom(ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1822 ar_nb_wheels_scale.first = Math::RangeRandom(ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1823 ar_nb_wheels_scale.second = Math::RangeRandom(ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1827 ar_nb_beams_scale.first = Math::Clamp(1.0f, ar_nb_beams_k_interval.first, ar_nb_beams_k_interval.second);
1828 ar_nb_beams_scale.second = Math::Clamp(1.0f, ar_nb_beams_d_interval.first, ar_nb_beams_d_interval.second);
1829 ar_nb_shocks_scale.first = Math::Clamp(1.0f, ar_nb_shocks_k_interval.first, ar_nb_shocks_k_interval.second);
1830 ar_nb_shocks_scale.second = Math::Clamp(1.0f, ar_nb_shocks_d_interval.first, ar_nb_shocks_d_interval.second);
1831 ar_nb_wheels_scale.first = Math::Clamp(1.0f, ar_nb_wheels_k_interval.first, ar_nb_wheels_k_interval.second);
1832 ar_nb_wheels_scale.second = Math::Clamp(1.0f, ar_nb_wheels_d_interval.first, ar_nb_wheels_d_interval.second);
1833 ar_nb_reference = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1834 ar_nb_optimum = std::vector<float>(ar_nb_reference.size(), std::numeric_limits<float>::max());
1837 this->applyNodeBeamScales();
1839 m_ongoing_reset =
false;
1840 this->CalcForcesEulerPrepare(
true);
1841 for (
int i = 0; i < ar_nb_skip_steps; i++)
1843 this->CalcForcesEulerCompute(i == 0, ar_nb_skip_steps);
1844 if (m_ongoing_reset)
1847 m_ongoing_reset =
true;
1849 float sum_movement = 0.0f;
1850 float movement = 0.0f;
1851 float sum_velocity = 0.0f;
1852 float velocity = 0.0f;
1853 float sum_stress = 0.0f;
1854 float stress = 0.0f;
1856 for (
int k = 0; k < ar_nb_measure_steps; k++)
1858 this->CalcForcesEulerCompute(
false, ar_nb_measure_steps);
1859 for (
int i = 0; i < ar_num_nodes; i++)
1861 float v = ar_nodes[i].Velocity.length();
1862 sum_movement += v / (float)ar_nb_measure_steps;
1863 movement = std::max(movement, v);
1865 for (
int i = 0; i < ar_num_beams; i++)
1867 Vector3 dis = (ar_beams[i].p1->RelPosition - ar_beams[i].p2->RelPosition).normalisedCopy();
1868 float v = (ar_beams[i].p1->Velocity - ar_beams[i].p2->Velocity).dotProduct(dis);
1869 sum_velocity += std::abs(v) / (float)ar_nb_measure_steps;
1870 velocity = std::max(velocity, std::abs(v));
1871 sum_stress += std::abs(ar_beams[i].stress) / (float)ar_nb_measure_steps;
1872 stress = std::max(stress, std::abs(ar_beams[i].stress));
1873 if (k == 0 && ar_beams[i].bm_broken)
1878 if (sum_broken > ar_nb_reference[6] ||
1879 stress > ar_nb_reference[0] || velocity > ar_nb_reference[2] || movement > ar_nb_optimum[4] ||
1880 sum_stress > ar_nb_reference[1] || sum_velocity > ar_nb_reference[3] || sum_movement > ar_nb_optimum[5] * 2.f)
1882 ar_nb_beams_scale = old_beams_scale;
1883 ar_nb_shocks_scale = old_shocks_scale;
1884 ar_nb_wheels_scale = old_wheels_scale;
1891 ar_nb_optimum = {stress, sum_stress, velocity, sum_velocity, movement, sum_movement, (float)sum_broken};
1892 if (!ar_nb_initialized)
1894 ar_nb_reference = ar_nb_optimum;
1896 ar_nb_initialized =
true;
1899 void Actor::HandleInputEvents(
float dt)
1901 if (!m_ongoing_reset)
1904 if (m_anglesnap_request > 0)
1906 float rotation = Radian(getRotation()).valueDegrees();
1907 float target_rotation = std::round(rotation / m_anglesnap_request) * m_anglesnap_request;
1908 m_rotation_request = -Degree(target_rotation - rotation).valueRadians();
1909 m_rotation_request_center = getRotationCenter();
1910 m_anglesnap_request = 0;
1913 if (m_rotation_request != 0.0f)
1915 Quaternion rot = Quaternion(Radian(m_rotation_request), Vector3::UNIT_Y);
1917 for (
int i = 0; i < ar_num_nodes; i++)
1919 ar_nodes[i].AbsPosition -= m_rotation_request_center;
1920 ar_nodes[i].AbsPosition = rot * ar_nodes[i].AbsPosition;
1921 ar_nodes[i].AbsPosition += m_rotation_request_center;
1922 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1923 ar_nodes[i].Velocity = rot * ar_nodes[i].Velocity;
1924 ar_nodes[i].Forces = rot * ar_nodes[i].Forces;
1927 m_rotation_request = 0.0f;
1928 this->UpdateBoundingBoxes();
1929 calculateAveragePosition();
1932 if (m_translation_request != Vector3::ZERO)
1934 for (
int i = 0; i < ar_num_nodes; i++)
1936 ar_nodes[i].AbsPosition += m_translation_request;
1937 ar_nodes[i].RelPosition = ar_nodes[i].AbsPosition - ar_origin;
1940 m_translation_request = Vector3::ZERO;
1941 UpdateBoundingBoxes();
1942 calculateAveragePosition();
1946 void Actor::sendStreamSetup()
1953 strncpy(reg.
name, ar_filename.c_str(), 128);
1954 if (m_used_skin_entry !=
nullptr)
1956 strncpy(reg.
skin, m_used_skin_entry->dname.c_str(), 60);
1962 #endif // USE_SOCKETW
1968 void Actor::sendStreamData()
1972 if (ar_net_timer.getMilliseconds() - ar_net_last_update_time < 100)
1975 ar_net_last_update_time = ar_net_timer.getMilliseconds();
1984 char send_buffer[8192] = {0};
1986 unsigned int packet_len = 0;
2003 if (ar_engine->hasContact())
2005 if (ar_engine->isRunning())
2008 switch (ar_engine->GetAutoShiftMode())
2022 if (ar_num_aeroengines > 0)
2024 float rpm = ar_aeroengines[0]->getRPM();
2029 send_oob->
brake = ar_brake;
2034 if (getCustomParticleMode())
2037 if (ar_parking_brake)
2039 if (m_tractioncontrol)
2041 if (m_antilockbrake)
2055 float* send_nodes = (
float *)ptr;
2056 packet_len += m_net_total_buffer_size;
2062 Vector3& refpos = ar_nodes[0].AbsPosition;
2063 send_nodes[0] = refpos.x;
2064 send_nodes[1] = refpos.y;
2065 send_nodes[2] = refpos.z;
2067 ptr +=
sizeof(float) * 3;
2070 short* sbuf = (
short*)ptr;
2071 for (i = 1; i < m_net_first_wheel_node; i++)
2073 Vector3 relpos = ar_nodes[i].AbsPosition - refpos;
2074 sbuf[(i - 1) * 3 + 0] = (
short int)(relpos.x * m_net_node_compression);
2075 sbuf[(i - 1) * 3 + 1] = (
short int)(relpos.y * m_net_node_compression);
2076 sbuf[(i - 1) * 3 + 2] = (
short int)(relpos.z * m_net_node_compression);
2078 ptr +=
sizeof(
short int) * 3;
2082 float* wfbuf = (
float*)ptr;
2083 for (i = 0; i < ar_num_wheels; i++)
2085 wfbuf[i] = ar_wheels[i].wh_net_rp;
2087 ptr += ar_num_wheels *
sizeof(float);
2090 for (
size_t i = 0; i < m_prop_anim_key_states.size(); i++)
2092 if (m_prop_anim_key_states[i].anim_active)
2095 char& dst_byte = *(ptr + (i / 8));
2096 char mask = ((char)m_prop_anim_key_states[i].anim_active) << (7 - (i % 8));
2106 void Actor::CalcAnimators(
hydrobeam_t const& hydrobeam,
float &cstate,
int &div)
2113 for (spi = 0; spi < ar_num_screwprops; spi++)
2114 if (ar_screwprops[spi])
2115 ctmp += ar_screwprops[spi]->getRudder();
2128 for (spi = 0; spi < ar_num_screwprops; spi++)
2129 if (ar_screwprops[spi])
2130 ctmp += ar_screwprops[spi]->getThrottle();
2141 if (m_num_wheel_diffs && m_wheel_diffs[0])
2143 String name = m_wheel_diffs[0]->GetDifferentialTypeName();
2146 if (name ==
"Split")
2148 if (name ==
"Locked")
2160 float heading = getRotation();
2162 cstate = (heading * 57.29578f) / 360.0f;
2169 float torque = ar_engine->GetCrankFactor();
2172 if (torque >= ar_anim_previous_crank)
2173 cstate -= torque / 10.0f;
2177 if (cstate <= -1.0f)
2179 ar_anim_previous_crank = torque;
2187 int shifter = ar_engine->GetGear();
2188 if (shifter > m_previous_gear)
2191 ar_anim_shift_timer = 0.2f;
2193 if (shifter < m_previous_gear)
2196 ar_anim_shift_timer = -0.2f;
2198 m_previous_gear = shifter;
2200 if (ar_anim_shift_timer > 0.0f)
2204 if (ar_anim_shift_timer < 0.0f)
2205 ar_anim_shift_timer = 0.0f;
2207 if (ar_anim_shift_timer < 0.0f)
2211 if (ar_anim_shift_timer > 0.0f)
2212 ar_anim_shift_timer = 0.0f;
2221 int shifter = ar_engine->GetGear();
2226 else if (shifter < 0)
2232 cstate -= int((shifter - 1.0) / 2.0);
2240 int shifter = ar_engine->GetGear();
2248 cstate = shifter % 2;
2256 int shifter = ar_engine->GetGear();
2257 int numgears = ar_engine->getNumGears();
2258 cstate -= (shifter + 2.0) / (numgears + 2.0);
2265 float pbrake = ar_parking_brake;
2273 float speedo = ar_wheel_speed / ar_guisettings_speedo_max_kph;
2274 cstate -= speedo * 3.0f;
2281 float tacho = ar_engine->GetEngineRpm() / ar_engine->getMaxRPM();
2289 float turbo = ar_engine->GetTurboPsi() * 3.34;
2290 cstate -= turbo / 67.0f;
2304 float accel = ar_engine->GetAcceleration();
2305 cstate -= accel + 0.06f;
2313 float clutch = ar_engine->GetClutch();
2314 cstate -= fabs(1.0f - clutch);
2325 float pcent = ar_aeroengines[aenum]->getRPMpc();
2327 angle = -5.0 + pcent * 1.9167;
2328 else if (pcent < 110.0)
2329 angle = 110.0 + (pcent - 60.0) * 4.075;
2332 cstate -= angle / 314.0f;
2337 float throttle = ar_aeroengines[aenum]->getThrottle();
2343 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2351 if (ar_aeroengines[aenum]->getType() == AeroEngineType::AE_XPROP)
2354 cstate = tp->
pitch / 120.0f;
2360 if (!ar_aeroengines[aenum]->getIgnition())
2364 if (ar_aeroengines[aenum]->isFailed())
2373 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438;
2374 float altitude = ar_nodes[0].AbsPosition.y;
2375 float sea_level_pressure = 101325;
2376 float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947);
2377 float airdensity = airpressure * 0.0000120896;
2378 float kt = ground_speed_kt * sqrt(airdensity / 1.225);
2379 cstate -= kt / 100.0f;
2386 float vvi = ar_nodes[0].Velocity.y * 196.85;
2388 cstate -= vvi / 6000.0f;
2391 if (cstate <= -1.0f)
2402 float altimeter = (ar_nodes[0].AbsPosition.y * 1.1811) / 360.0f;
2403 int alti_int = int(altimeter);
2404 float alti_mod = (altimeter - alti_int);
2411 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 3600.0f;
2412 int alti_int = int(alti);
2413 float alti_mod = (alti - alti_int);
2415 if (cstate <= -1.0f)
2422 float alti = ar_nodes[0].AbsPosition.y * 1.1811 / 36000.0f;
2424 if (cstate <= -1.0f)
2434 if (ar_num_wings > 4)
2435 aoa = (ar_wings[4].fa->aoa) / 25.0f;
2436 if ((ar_nodes[0].Velocity.length() * 1.9438) < 10.0f)
2439 if (cstate <= -1.0f)
2449 Vector3 rollv = this->GetCameraRoll();
2450 Vector3 dirv = this->GetCameraDir();
2451 Vector3 upv = dirv.crossProduct(-rollv);
2452 float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y));
2454 rollangle = Math::RadiansToDegrees(rollangle);
2457 rollangle = 180.0f - rollangle;
2458 cstate = rollangle / 180.0f;
2462 cstate = cstate - 2.0f;
2469 Vector3 dirv = this->GetCameraDir();
2470 float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y));
2472 cstate = (Math::RadiansToDegrees(pitchangle) / 90.0f);
2479 float airbrake = ar_airbrake_intensity;
2481 cstate -= airbrake / 5.0f;
2495 void Actor::CalcCabCollisions()
2497 for (
int i = 0; i < ar_num_nodes; i++)
2499 ar_nodes[i].nd_has_mesh_contact =
false;
2501 if (m_intra_point_col_detector !=
nullptr)
2503 m_intra_point_col_detector->UpdateIntraPoint();
2505 *m_intra_point_col_detector,
2509 ar_intra_collcabrate,
2512 *ar_submesh_ground_model);
2516 void Actor::CalcShocks2(
int i, Real difftoBeamL, Real& k, Real& d, Real v)
2520 k = ar_beams[i].shock->springout;
2521 d = ar_beams[i].shock->dampout;
2523 float logafactor = 1.0f;
2524 if (ar_beams[i].longbound != 0.0f)
2526 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2527 logafactor = std::min(logafactor * logafactor, 1.0f);
2529 k += ar_beams[i].shock->sprogout * k * logafactor;
2530 d += ar_beams[i].shock->dprogout * d * logafactor;
2534 k = ar_beams[i].shock->springin;
2535 d = ar_beams[i].shock->dampin;
2537 float logafactor = 1.0f;
2538 if (ar_beams[i].shortbound != 0.0f)
2540 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2541 logafactor = std::min(logafactor * logafactor, 1.0f);
2543 k += ar_beams[i].shock->sprogin * k * logafactor;
2544 d += ar_beams[i].shock->dprogin * d * logafactor;
2549 float beamsLep = ar_beams[i].L * 0.8f;
2550 float longboundprelimit = ar_beams[i].longbound * beamsLep;
2551 float shortboundprelimit = -ar_beams[i].shortbound * beamsLep;
2552 if (difftoBeamL > longboundprelimit)
2555 k = ar_beams[i].shock->springout;
2556 d = ar_beams[i].shock->dampout;
2558 float logafactor = 1.0f;
2559 if (ar_beams[i].longbound != 0.0f)
2561 logafactor = difftoBeamL / (ar_beams[i].longbound * ar_beams[i].L);
2562 logafactor = std::min(logafactor * logafactor, 1.0f);
2564 k += ar_beams[i].shock->sprogout * k * logafactor;
2565 d += ar_beams[i].shock->dprogout * d * logafactor;
2568 if (ar_beams[i].longbound != 0.0f)
2570 logafactor = ((difftoBeamL - longboundprelimit) * 5.0f) / (ar_beams[i].longbound * ar_beams[i].L);
2571 logafactor = std::min(logafactor * logafactor, 1.0f);
2573 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2574 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2578 k = ar_beams[i].shock->springin;
2579 d = ar_beams[i].shock->dampin;
2582 else if (difftoBeamL < shortboundprelimit)
2585 k = ar_beams[i].shock->springin;
2586 d = ar_beams[i].shock->dampin;
2588 float logafactor = 1.0f;
2589 if (ar_beams[i].shortbound != 0.0f)
2591 logafactor = difftoBeamL / (ar_beams[i].shortbound * ar_beams[i].L);
2592 logafactor = std::min(logafactor * logafactor, 1.0f);
2594 k += ar_beams[i].shock->sprogin * k * logafactor;
2595 d += ar_beams[i].shock->dprogin * d * logafactor;
2598 if (ar_beams[i].shortbound != 0.0f)
2600 logafactor = ((difftoBeamL - shortboundprelimit) * 5.0f) / (ar_beams[i].shortbound * ar_beams[i].L);
2601 logafactor = std::min(logafactor * logafactor, 1.0f);
2603 k += (k + 100.0f) * ar_beams[i].shock->sprogout * logafactor;
2604 d += (d + 100.0f) * ar_beams[i].shock->dprogout * logafactor;
2608 k = ar_beams[i].shock->springout;
2609 d = ar_beams[i].shock->dampout;
2612 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2615 k = std::max(k, ar_beams[i].shock->sbd_spring);
2616 d = std::max(d, ar_beams[i].shock->sbd_damp);
2619 else if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2622 k = ar_beams[i].shock->sbd_spring;
2623 d = ar_beams[i].shock->sbd_damp;
2627 void Actor::CalcShocks3(
int i, Real difftoBeamL, Real &k, Real& d, Real v)
2629 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2631 float interp_ratio = difftoBeamL - ar_beams[i].longbound * ar_beams[i].L;
2632 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2633 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2635 else if (difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2637 float interp_ratio = -difftoBeamL - ar_beams[i].shortbound * ar_beams[i].L;
2638 k += (ar_beams[i].shock->sbd_spring - k) * interp_ratio;
2639 d += (ar_beams[i].shock->sbd_damp - d) * interp_ratio;
2643 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2644 k = ar_beams[i].shock->springout;
2645 d = ar_beams[i].shock->dampout * ar_beams[i].shock->dslowout * std::min(v, ar_beams[i].shock->splitout) +
2646 ar_beams[i].shock->dampout * ar_beams[i].shock->dfastout * std::max(0.0f, v - ar_beams[i].shock->splitout);
2651 v = Math::Clamp(std::abs(v), +0.15f, +20.0f);
2652 k = ar_beams[i].shock->springin;
2653 d = ar_beams[i].shock->dampin * ar_beams[i].shock->dslowin * std::min(v, ar_beams[i].shock->splitin ) +
2654 ar_beams[i].shock->dampin * ar_beams[i].shock->dfastin * std::max(0.0f, v - ar_beams[i].shock->splitin );
2659 void Actor::CalcTriggers(
int i, Real difftoBeamL,
bool trigger_hooks)
2665 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L || difftoBeamL < -ar_beams[i].shortbound * ar_beams[i].L)
2667 ar_beams[i].shock->trigger_switch_state -= dt;
2668 if (ar_beams[i].shock->trigger_switch_state <= 0.0f)
2669 ar_beams[i].shock->trigger_switch_state = 0.0f;
2672 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2676 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 1)
2678 LOG(
" Trigger disabled. Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2679 ar_beams[i].shock->last_debug_state = 1;
2681 ar_beams[scount].shock->trigger_enabled =
false;
2687 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2691 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 9)
2693 LOG(
" Trigger enabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2694 ar_beams[i].shock->last_debug_state = 9;
2696 ar_beams[scount].shock->trigger_enabled =
true;
2702 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
false;
2703 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 2)
2705 LOG(
" F-key trigger block released. Blocker BeamID " +
TOSTRING(i) +
" Released F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2706 ar_beams[i].shock->last_debug_state = 2;
2711 if (!ar_beams[i].shock->trigger_switch_state)
2713 for (
int scount = 0; scount < ar_num_shocks; scount++)
2715 int short1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2716 int short2 = ar_beams[i].shock->trigger_cmdshort;
2717 int long1 = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2718 int long2 = ar_beams[i].shock->trigger_cmdlong;
2719 int tmpi = ar_beams[ar_shocks[scount].beamid].shock->beamid;
2720 if (((short1 == short2 && long1 == long2) || (short1 == long2 && long1 == short2)) && i != tmpi)
2722 int tmpcmdkey = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong;
2723 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdlong = ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort;
2724 ar_beams[ar_shocks[scount].beamid].shock->trigger_cmdshort = tmpcmdkey;
2725 ar_beams[i].shock->trigger_switch_state = ar_beams[i].shock->trigger_boundary_t;
2726 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 3)
2728 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));
2729 ar_beams[i].shock->last_debug_state = 3;
2737 if (difftoBeamL > ar_beams[i].longbound * ar_beams[i].L)
2746 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2759 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2767 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), 1.0f);
2772 if (!ar_command_key[ar_beams[i].shock->trigger_cmdlong].trigger_cmdkeyblock_state)
2775 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2777 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = 1;
2778 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 4)
2780 LOG(
" Trigger Longbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdlong));
2781 ar_beams[i].shock->last_debug_state = 4;
2795 rq->
alr_type = ActorLinkingRequestType::HOOK_UNLOCK;
2808 rq->
alr_type = ActorLinkingRequestType::HOOK_LOCK;
2818 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2823 if (!ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2826 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 0;
2828 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = 1;
2830 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 5)
2832 LOG(
" Trigger Shortbound activated. Trigger BeamID " +
TOSTRING(i) +
" Triggered F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2833 ar_beams[i].shock->last_debug_state = 5;
2844 if (ar_beams[i].longbound - ar_beams[i].shortbound > 0.0f)
2846 float diffPercentage = difftoBeamL / ar_beams[i].L;
2847 float triggerValue = (diffPercentage - ar_beams[i].shortbound) / (ar_beams[i].longbound - ar_beams[i].shortbound);
2849 triggerValue = std::max(0.0f, triggerValue);
2850 triggerValue = std::min(triggerValue, 1.0f);
2854 engineTriggerHelper(ar_beams[i].shock->trigger_cmdshort,
EngineTriggerType(ar_beams[i].shock->trigger_cmdlong), triggerValue);
2859 ar_command_key[ar_beams[i].shock->trigger_cmdshort].triggerInputValue = triggerValue;
2860 ar_command_key[ar_beams[i].shock->trigger_cmdlong].triggerInputValue = triggerValue;
2866 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdlong; scount++)
2870 if (m_trigger_debug_enabled && ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 6)
2872 LOG(
" Trigger enabled. Blocker BeamID " +
TOSTRING(i) +
" disabled trigger " +
TOSTRING(scount));
2873 ar_beams[i].shock->last_debug_state = 6;
2875 ar_beams[scount].shock->trigger_enabled =
true;
2881 for (
int scount = i + 1; scount <= i + ar_beams[i].shock->trigger_cmdshort; scount++)
2885 if (m_trigger_debug_enabled && !ar_beams[scount].shock->trigger_enabled && ar_beams[i].shock->last_debug_state != 10)
2887 LOG(
" Trigger disabled. Inverted Blocker BeamID " +
TOSTRING(i) +
" enabled trigger " +
TOSTRING(scount));
2888 ar_beams[i].shock->last_debug_state = 10;
2890 ar_beams[scount].shock->trigger_enabled =
false;
2896 ar_beams[i].shock->trigger_switch_state = 0.0f;
2897 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 7)
2899 LOG(
" Trigger switch reset. Switch BeamID " +
TOSTRING(i));
2900 ar_beams[i].shock->last_debug_state = 7;
2903 else if ((ar_beams[i].shock->flags &
SHOCK_FLAG_TRG_CMD_BLOCKER) && !ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state)
2905 ar_command_key[ar_beams[i].shock->trigger_cmdshort].trigger_cmdkeyblock_state =
true;
2906 if (m_trigger_debug_enabled && ar_beams[i].shock->last_debug_state != 8)
2908 LOG(
" F-key trigger blocked. Blocker BeamID " +
TOSTRING(i) +
" Blocked F" +
TOSTRING(ar_beams[i].shock->trigger_cmdshort));
2909 ar_beams[i].shock->last_debug_state = 8;
2916 void Actor::setAirbrakeIntensity(
float intensity)
2918 ar_airbrake_intensity = intensity;
2921 ab->updatePosition((
float)ar_airbrake_intensity / 5.0);
2926 void Actor::updateSkidmarks()
2928 for (
int i = 0; i < ar_num_wheels; i++)
2930 if (!m_skid_trails[i])
2933 for (
int j = 0; j < ar_wheels[i].wh_num_nodes; j++)
2935 auto n = ar_wheels[i].wh_nodes[j];
2936 if (!n || !n->nd_has_ground_contact || n->nd_last_collision_gm ==
nullptr ||
2937 n->nd_last_collision_gm->fx_type != Collisions::FX_HARD)
2941 if (n->nd_avg_collision_slip > 6.f && n->nd_last_collision_slip.squaredLength() > 9.f)
2943 m_skid_trails[i]->update(n->AbsPosition, j, n->nd_avg_collision_slip, n->nd_last_collision_gm->name);
2950 void Actor::prepareInside(
bool inside)
2958 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2959 seatmat->setDepthWriteEnabled(
false);
2960 seatmat->setSceneBlending(SBT_TRANSPARENT_ALPHA);
2966 ar_dashboard->setVisible(
false);
2972 MaterialPtr seatmat = (MaterialPtr)(MaterialManager::getSingleton().getByName(
"driversseat"));
2973 seatmat->setDepthWriteEnabled(
true);
2974 seatmat->setSceneBlending(SBT_REPLACE);
2985 m_gfx_actor->SetCastShadows(!inside);
2989 void Actor::toggleHeadlights()
2993 if (ar_state == ActorState::LOCAL_SIMULATED &&
this == player_actor.
GetRef() && ar_forward_commands)
2997 if (actor->ar_state == ActorState::LOCAL_SIMULATED &&
this != actor.GetRef() && actor->ar_import_commands)
3006 m_gfx_actor->SetCabLightsActive(this->getHeadlightsVisible());
3011 void Actor::forceAllFlaresOff()
3013 for (
size_t i = 0; i < ar_flares.size(); i++)
3015 ar_flares[i].snode->setVisible(
false);
3019 void Actor::updateFlareStates(
float dt)
3021 if (m_flares_mode == GfxFlaresMode::NONE) {
return; }
3023 for (
size_t i = 0; i < this->ar_flares.size(); i++)
3026 if (ar_flares[i].blinkdelay != 0)
3028 ar_flares[i].blinkdelay_curr -= dt;
3029 if (ar_flares[i].blinkdelay_curr <= 0)
3031 ar_flares[i].blinkdelay_curr = ar_flares[i].blinkdelay;
3032 ar_flares[i].blinkdelay_state = !ar_flares[i].blinkdelay_state;
3037 ar_flares[i].blinkdelay_state =
true;
3041 bool isvisible =
false;
3042 switch (ar_flares[i].fl_type)
3053 case FlareType::DASHBOARD: isvisible = ar_dashboard->_getBool(ar_flares[i].dashboard_link);
break;
3054 case FlareType::USER: isvisible = this->getCustomLightVisible(ar_flares[i].controlnumber);
break;
3058 isvisible = isvisible && ar_flares[i].blinkdelay_state;
3061 switch (ar_flares[i].fl_type)
3063 case FlareType::BLINKER_LEFT: m_blinker_left_lit = isvisible;
break;
3064 case FlareType::BLINKER_RIGHT: m_blinker_right_lit = isvisible;
break;
3069 if (ar_flares[i].uses_inertia)
3071 ar_flares[i].intensity = ar_flares[i].inertia.CalcSimpleDelay(isvisible, dt);
3075 ar_flares[i].intensity = (float)isvisible;
3082 if (this->getBlinkType() == blink)
3085 setBlinkType(blink);
3090 if (ar_state == ActorState::DISPOSED)
3122 void Actor::autoBlinkReset()
3127 if (this->getBlinkType() ==
BLINK_LEFT && ar_hydro_dir_state < -blink_lock_range)
3130 m_blinker_autoreset =
true;
3133 if (this->getBlinkType() ==
BLINK_LEFT && m_blinker_autoreset && ar_hydro_dir_state > -blink_lock_range)
3137 m_blinker_autoreset =
false;
3141 if (this->getBlinkType() ==
BLINK_RIGHT && ar_hydro_dir_state > blink_lock_range)
3142 m_blinker_autoreset =
true;
3144 if (this->getBlinkType() ==
BLINK_RIGHT && m_blinker_autoreset && ar_hydro_dir_state < blink_lock_range)
3147 m_blinker_autoreset =
false;
3157 this->toggleHeadlights();
3159 this->beaconsToggle();
3168 this->setBlinkType(btype);
3171 m_lightmask = lightmask;
3174 void Actor::toggleCustomParticles()
3176 if (ar_state == ActorState::DISPOSED)
3179 m_custom_particles_enabled = !m_custom_particles_enabled;
3180 for (
int i = 0; i < ar_num_custom_particles; i++)
3182 ar_custom_particles[i].active = !ar_custom_particles[i].active;
3183 for (
int j = 0; j < ar_custom_particles[i].psys->getNumEmitters(); j++)
3185 ar_custom_particles[i].psys->getEmitter(j)->setEnabled(ar_custom_particles[i].active);
3193 void Actor::updateSoundSources()
3198 for (
int i = 0; i < ar_num_soundsources; i++)
3201 ar_soundsources[i].ssi->setPosition(ar_nodes[ar_soundsources[i].nodenum].AbsPosition);
3202 ar_soundsources[i].ssi->setVelocity(ar_nodes[ar_soundsources[i].nodenum].Velocity);
3210 void Actor::updateVisual(
float dt)
3212 Vector3 ref(Vector3::UNIT_Y);
3214 updateSoundSources();
3218 if (ar_driveable ==
AIRPLANE && ar_state != ActorState::LOCAL_SLEEPING)
3221 m_avionic_chatter_timer -= dt;
3222 if (m_avionic_chatter_timer < 0)
3225 m_avionic_chatter_timer = Math::RangeRandom(11, 30);
3232 if (ar_engine && exhausts.size() > 0)
3234 std::vector<exhaust_t>::iterator it;
3235 for (it = exhausts.begin(); it != exhausts.end(); it++)
3239 Vector3 dir = ar_nodes[it->emitterNode].AbsPosition - ar_nodes[it->directionNode].AbsPosition;
3241 ParticleEmitter* emit = it->smoker->getEmitter(0);
3242 it->smokeNode->setPosition(ar_nodes[it->emitterNode].AbsPosition);
3243 emit->setDirection(dir);
3244 if (!m_disable_smoke && ar_engine->GetSmoke() != -1.0)
3246 emit->setEnabled(
true);
3247 emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.02 + ar_engine->GetSmoke() * 0.06));
3248 emit->setTimeToLive((0.02 + ar_engine->GetSmoke() * 0.06) / 0.04);
3252 emit->setEnabled(
false);
3254 emit->setParticleVelocity(1.0 + ar_engine->GetSmoke() * 2.0, 2.0 + ar_engine->GetSmoke() * 3.0);
3259 float autoaileron = 0;
3260 float autorudder = 0;
3261 float autoelevator = 0;
3264 ar_autopilot->UpdateIls(
App::GetGameContext()->GetTerrain()->getObjectManager()->GetLocalizers());
3265 autoaileron = ar_autopilot->getAilerons();
3266 autorudder = ar_autopilot->getRudder();
3267 autoelevator = ar_autopilot->getElevator();
3268 ar_autopilot->gpws_update(ar_posnode_spawn_height);
3270 autoaileron += ar_aileron;
3271 autorudder += ar_rudder;
3272 autoelevator += ar_elevator;
3273 if (autoaileron < -1.0)
3275 if (autoaileron > 1.0)
3277 if (autorudder < -1.0)
3279 if (autorudder > 1.0)
3281 if (autoelevator < -1.0)
3282 autoelevator = -1.0;
3283 if (autoelevator > 1.0)
3285 for (
int i = 0; i < ar_num_wings; i++)
3287 if (ar_wings[i].fa->type ==
'a')
3288 ar_wings[i].fa->setControlDeflection(autoaileron);
3289 if (ar_wings[i].fa->type ==
'b')
3290 ar_wings[i].fa->setControlDeflection(-autoaileron);
3291 if (ar_wings[i].fa->type ==
'r')
3292 ar_wings[i].fa->setControlDeflection(autorudder);
3293 if (ar_wings[i].fa->type ==
'e' || ar_wings[i].fa->type ==
'S' || ar_wings[i].fa->type ==
'T')
3294 ar_wings[i].fa->setControlDeflection(autoelevator);
3295 if (ar_wings[i].fa->type ==
'f')
3296 ar_wings[i].fa->setControlDeflection(
FLAP_ANGLES[ar_aerial_flap]);
3297 if (ar_wings[i].fa->type ==
'c' || ar_wings[i].fa->type ==
'V')
3298 ar_wings[i].fa->setControlDeflection((autoaileron + autoelevator) / 2.0);
3299 if (ar_wings[i].fa->type ==
'd' || ar_wings[i].fa->type ==
'U')
3300 ar_wings[i].fa->setControlDeflection((-autoaileron + autoelevator) / 2.0);
3301 if (ar_wings[i].fa->type ==
'g')
3302 ar_wings[i].fa->setControlDeflection((autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3303 if (ar_wings[i].fa->type ==
'h')
3304 ar_wings[i].fa->setControlDeflection((-autoaileron +
FLAP_ANGLES[ar_aerial_flap]) / 2.0);
3305 if (ar_wings[i].fa->type ==
'i')
3306 ar_wings[i].fa->setControlDeflection((-autoelevator + autorudder) / 2.0);
3307 if (ar_wings[i].fa->type ==
'j')
3308 ar_wings[i].fa->setControlDeflection((autoelevator + autorudder) / 2.0);
3309 ar_wings[i].fa->updateVerticesPhysics();
3312 ar_hydro_aileron_command = autoaileron;
3313 ar_hydro_rudder_command = autorudder;
3314 ar_hydro_elevator_command = autoelevator;
3322 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3324 if (pos == ar_inter_beams.end())
3326 ar_inter_beams.push_back(beam);
3331 std::pair<ActorPtr, ActorPtr> actor_pair(
this, other);
3335 if (linked_before != linked_now)
3338 this->DetermineLinkedActors();
3339 for (
ActorPtr& actor : this->ar_linked_actors)
3340 actor->DetermineLinkedActors();
3347 for (
ActorPtr& actor : this->ar_linked_actors)
3364 auto pos = std::find(ar_inter_beams.begin(), ar_inter_beams.end(), beam);
3366 if (pos != ar_inter_beams.end())
3368 ar_inter_beams.erase(pos);
3380 if (linked_before != linked_now)
3383 this->DetermineLinkedActors();
3384 for (
ActorPtr& actor : this->ar_linked_actors)
3385 actor->DetermineLinkedActors();
3405 void Actor::DisjoinInterActorBeams()
3413 this->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET);
3414 this->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET);
3415 this->tieToggle(-1, ActorLinkingRequestType::TIE_RESET);
3420 if (other_actor->ar_state != ActorState::LOCAL_SIMULATED)
3424 other_actor->hookToggle(-1, ActorLinkingRequestType::HOOK_RESET,
NODENUM_INVALID, ar_instance_id);
3425 other_actor->tieToggle(-1, ActorLinkingRequestType::TIE_RESET, ar_instance_id);
3426 other_actor->ropeToggle(-1, ActorLinkingRequestType::ROPE_RESET, ar_instance_id);
3435 bool istied =
false;
3437 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3440 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3444 if (mode == ActorLinkingRequestType::TIE_RESET
3445 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->ti_locked_actor && it->ti_locked_actor->ar_instance_id != forceunlock_filter)
3453 istied = !it->ti_beam->bm_disabled;
3456 it->ti_tied =
false;
3457 it->ti_tying =
false;
3458 if (it->ti_locked_ropable)
3459 it->ti_locked_ropable->attached_ties--;
3461 it->ti_beam->p2 = &ar_nodes[0];
3462 it->ti_beam->bm_inter_actor =
false;
3463 it->ti_beam->bm_disabled =
true;
3464 if (it->ti_locked_actor !=
this)
3466 this->RemoveInterActorBeam(it->ti_beam, mode);
3468 it->ti_locked_actor =
nullptr;
3473 if (!istied && mode == ActorLinkingRequestType::TIE_TOGGLE)
3475 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3478 if (group != -1 && (it->ti_group != -1 && it->ti_group != group))
3484 float mindist = it->ti_beam->refL;
3485 node_t* nearest_node = 0;
3491 if (actor->ar_state == ActorState::LOCAL_SLEEPING ||
3492 (actor ==
this && it->ti_no_self_lock))
3498 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3501 if (!itr->multilock && itr->attached_ties > 0)
3505 if (
this == actor.GetRef() && itr->node->pos == it->ti_beam->p1->pos)
3509 float dist = (it->ti_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3513 nearest_node = itr->node;
3514 nearest_actor = actor;
3515 locktedto = &(*itr);
3523 it->ti_beam->bm_disabled =
false;
3525 it->ti_locked_actor = nearest_actor;
3526 it->ti_beam->p2 = nearest_node;
3527 it->ti_beam->bm_inter_actor = nearest_actor !=
this;
3528 it->ti_beam->stress = 0;
3529 it->ti_beam->L = it->ti_beam->refL;
3531 it->ti_tying =
true;
3532 it->ti_locked_ropable = locktedto;
3534 if (it->ti_beam->bm_inter_actor)
3536 this->AddInterActorBeam(it->ti_beam, nearest_actor, mode);
3552 for (std::vector<rope_t>::iterator it = ar_ropes.begin(); it != ar_ropes.end(); it++)
3555 if (group != -1 && (it->rp_group != -1 && it->rp_group != group))
3559 if (mode == ActorLinkingRequestType::ROPE_RESET
3560 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->rp_locked_actor && it->rp_locked_actor->ar_instance_id != forceunlock_filter)
3570 if (it->rp_locked_ropable)
3571 it->rp_locked_ropable->attached_ropes--;
3572 if (it->rp_locked_actor !=
this)
3574 this->RemoveInterActorBeam(it->rp_beam, mode);
3576 it->rp_locked_actor =
nullptr;
3577 it->rp_locked_ropable =
nullptr;
3579 else if (mode == ActorLinkingRequestType::ROPE_TOGGLE)
3583 float mindist = it->rp_beam->L;
3589 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3592 for (std::vector<ropable_t>::iterator itr = actor->ar_ropables.begin(); itr != actor->ar_ropables.end(); itr++)
3595 if (!itr->multilock && itr->attached_ropes > 0)
3599 float dist = (it->rp_beam->p1->AbsPosition - itr->node->AbsPosition).length();
3603 nearest_actor = actor;
3613 it->rp_locked_ropable = rop;
3615 if (nearest_actor !=
this)
3617 this->AddInterActorBeam(it->rp_beam, nearest_actor, mode);
3626 ROR_ASSERT(mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK
3627 || mode == ActorLinkingRequestType::HOOK_TOGGLE || mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE
3628 || mode == ActorLinkingRequestType::HOOK_RESET);
3631 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3633 if (mode == ActorLinkingRequestType::HOOK_MOUSE_TOGGLE && it->hk_hook_node->pos != mousenode)
3638 if (mode == ActorLinkingRequestType::HOOK_TOGGLE && group == -1)
3641 if (it->hk_group <= -2)
3644 if (mode == ActorLinkingRequestType::HOOK_LOCK && group == -2)
3647 if (it->hk_group >= -1 || !it->hk_autolock)
3650 if (mode == ActorLinkingRequestType::HOOK_UNLOCK && group == -2)
3653 if (it->hk_group >= -1 || !it->hk_autolock)
3656 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group <= -3)
3659 if (it->hk_group != group)
3662 if ((mode == ActorLinkingRequestType::HOOK_LOCK || mode == ActorLinkingRequestType::HOOK_UNLOCK) && group >= -1)
3666 if (mode == ActorLinkingRequestType::HOOK_LOCK && it->hk_timer > 0.0f)
3673 if (mode == ActorLinkingRequestType::HOOK_RESET
3674 && forceunlock_filter !=
ACTORINSTANCEID_INVALID && it->hk_locked_actor && it->hk_locked_actor->ar_instance_id != forceunlock_filter)
3679 ActorPtr prev_locked_actor = it->hk_locked_actor;
3682 if ((mode != ActorLinkingRequestType::HOOK_UNLOCK && mode != ActorLinkingRequestType::HOOK_RESET) && it->hk_locked ==
UNLOCKED)
3686 float mindist = it->hk_lockrange;
3687 float distance = 100000000.0f;
3691 if (actor->ar_state == ActorState::LOCAL_SLEEPING)
3693 if (
this == actor.GetRef() && !it->hk_selflock)
3696 node_t* nearest_node =
nullptr;
3697 for (
int i = 0; i < actor->ar_num_nodes; i++)
3700 if (actor->ar_nodes[i].nd_lockgroup == 9999)
3704 if (
this == actor.GetRef() && i == it->hk_hook_node->pos)
3708 if (it->hk_lockgroup != -1 && it->hk_lockgroup != actor->ar_nodes[i].nd_lockgroup)
3712 float n2n_distance = (it->hk_hook_node->AbsPosition - actor->ar_nodes[i].AbsPosition).length();
3713 if (n2n_distance < mindist)
3715 if (distance >= n2n_distance)
3718 distance = n2n_distance;
3719 nearest_node = &actor->ar_nodes[i];
3726 it->hk_lock_node = nearest_node;
3727 it->hk_locked_actor = actor;
3730 if (it->hk_beam->bm_disabled)
3732 it->hk_beam->p2 = it->hk_lock_node;
3733 it->hk_beam->bm_inter_actor = (it->hk_locked_actor !=
nullptr);
3734 it->hk_beam->L = (it->hk_hook_node->AbsPosition - it->hk_lock_node->AbsPosition).length();
3735 it->hk_beam->bm_disabled =
false;
3736 this->AddInterActorBeam(it->hk_beam, it->hk_locked_actor, mode);
3742 else if ((it->hk_locked ==
LOCKED || it->hk_locked ==
PRELOCK) && (mode != ActorLinkingRequestType::HOOK_LOCK || !it->hk_beam->bm_inter_actor))
3746 this->RemoveInterActorBeam(it->hk_beam, mode);
3747 if (it->hk_group <= -2)
3749 it->hk_timer = it->hk_timer_preset;
3751 it->hk_lock_node = 0;
3752 it->hk_locked_actor = 0;
3754 it->hk_beam->p2 = &ar_nodes[0];
3755 it->hk_beam->bm_inter_actor =
false;
3756 it->hk_beam->L = (ar_nodes[0].AbsPosition - it->hk_hook_node->AbsPosition).length();
3757 it->hk_beam->bm_disabled =
true;
3762 void Actor::parkingbrakeToggle()
3764 if (ar_state == ActorState::DISPOSED)
3767 ar_parking_brake = !ar_parking_brake;
3769 if (ar_parking_brake)
3777 void Actor::antilockbrakeToggle()
3779 if (ar_state == ActorState::DISPOSED)
3783 alb_mode = !alb_mode;
3786 void Actor::tractioncontrolToggle()
3788 if (ar_state == ActorState::DISPOSED)
3795 void Actor::beaconsToggle()
3797 if (ar_state == ActorState::DISPOSED)
3800 if (m_flares_mode == GfxFlaresMode::NONE)
3811 void Actor::muteAllSounds()
3814 if (ar_state == ActorState::DISPOSED)
3817 for (
int i = 0; i < ar_num_soundsources; i++)
3819 if (ar_soundsources[i].ssi)
3820 ar_soundsources[i].ssi->setEnabled(
false);
3822 #endif // USE_OPENAL
3825 void Actor::unmuteAllSounds()
3828 if (ar_state == ActorState::DISPOSED)
3831 for (
int i = 0; i < ar_num_soundsources; i++)
3833 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3834 ar_soundsources[i].ssi->setEnabled(enabled);
3836 #endif // USE_OPENAL
3839 void Actor::NotifyActorCameraChanged()
3843 if (ar_state == ActorState::DISPOSED)
3846 for (
int i = 0; i < ar_num_soundsources; i++)
3848 bool enabled = (ar_soundsources[i].type == -2 || ar_soundsources[i].type == ar_current_cinecam);
3849 ar_soundsources[i].ssi->setEnabled(enabled);
3851 #endif // USE_OPENAL
3859 int Actor::GetNumActiveConnectedBeams(
int nodeid)
3861 int totallivebeams = 0;
3862 for (
unsigned int ni = 0; ni < ar_node_to_beam_connections[nodeid].size(); ++ni)
3864 if (!ar_beams[ar_node_to_beam_connections[nodeid][ni]].bm_disabled && !ar_beams[ar_node_to_beam_connections[nodeid][ni]].bounded)
3867 return totallivebeams;
3870 bool Actor::isTied()
3872 for (std::vector<tie_t>::iterator it = ar_ties.begin(); it != ar_ties.end(); it++)
3878 bool Actor::isLocked()
3880 for (std::vector<hook_t>::iterator it = ar_hooks.begin(); it != ar_hooks.end(); it++)
3881 if (it->hk_locked ==
LOCKED)
3886 void Actor::updateDashBoards(
float dt)
3897 int gear = ar_engine->GetGear();
3900 int numGears = (int)ar_engine->getNumGears();
3903 String str = String();
3916 int cg = ar_engine->getAutoShift();
3917 if (cg != EngineSim::MANUALMODE)
3919 str = ((cg == EngineSim::REAR) ?
"#ffffff" :
"#868686") + String(
"R\n");
3920 str += ((cg == EngineSim::NEUTRAL) ?
"#ff0012" :
"#8a000a") + String(
"N\n");
3921 str += ((cg == EngineSim::DRIVE) ?
"#12ff00" :
"#248c00") + String(
"D\n");
3922 str += ((cg == EngineSim::TWO) ?
"#ffffff" :
"#868686") + String(
"2\n");
3923 str += ((cg == EngineSim::ONE) ?
"#ffffff" :
"#868686") + String(
"1");
3928 str =
"#b8b8b8M\na\nn\nu";
3933 int autoGear = ar_engine->getAutoShift();
3937 float clutch = ar_engine->GetClutch();
3941 float acc = ar_engine->GetAcceleration();
3945 float rpm = ar_engine->GetEngineRpm();
3949 float turbo = ar_engine->GetTurboPsi() * 3.34f;
3953 bool ign = (ar_engine->hasContact() && !ar_engine->isRunning());
3957 bool batt = (ar_engine->hasContact() && !ar_engine->isRunning());
3961 bool cw = (fabs(ar_engine->GetTorque()) >= ar_engine->GetClutchForce() * 10.0f);
3966 ar_dashboard->setFloat(
DD_BRAKE, ar_brake);
3968 Vector3 cam_dir = this->GetCameraDir();
3969 Vector3 cam_roll = this->GetCameraRoll();
3972 float velocity = ar_nodes[0].Velocity.length();
3973 if (cam_dir != Vector3::ZERO)
3975 velocity = cam_dir.dotProduct(ar_nodes[0].Velocity);
3979 float cur_speed_kph = ar_wheel_speed * 3.6f;
3980 float smooth_kph = (cur_speed_kph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_KPH) * 0.7);
3984 float cur_speed_mph = ar_wheel_speed * 2.23693629f;
3985 float smooth_mph = (cur_speed_mph * 0.3) + (ar_dashboard->_getFloat(
DD_ENGINE_SPEEDO_MPH) * 0.7);
3989 if (cam_roll != Vector3::ZERO)
3991 float angle = asin(cam_roll.dotProduct(Vector3::UNIT_Y));
3997 float f = Radian(angle).valueDegrees();
3998 ar_dashboard->setFloat(
DD_ROLL, f);
4002 if (this->ar_has_active_shocks)
4005 float roll_corr = - m_stabilizer_shock_ratio * 10.0f;
4008 bool corr_active = (m_stabilizer_shock_request > 0);
4013 if (cam_dir != Vector3::ZERO)
4015 float angle = asin(cam_dir.dotProduct(Vector3::UNIT_Y));
4021 float f = Radian(angle).valueDegrees();
4022 ar_dashboard->setFloat(
DD_PITCH, f);
4029 bool locked = isLocked();
4030 ar_dashboard->setBool(
DD_LOCKED, locked);
4033 bool low_pres = !ar_engine_hydraulics_ready;
4041 int dash_tc_mode = 1;
4044 if (m_tractioncontrol)
4055 int dash_alb_mode = 1;
4058 if (m_antilockbrake)
4070 if (fabs(ar_command_key[0].commandValue) > 0.000001f)
4078 if (ar_num_screwprops)
4083 float throttle = ar_screwprops[i]->getThrottle();
4086 float steering = ar_screwprops[i]->getRudder();
4091 float depth = this->getHeightAboveGround();
4095 Vector3 hdir = this->GetCameraDir();
4096 float knots = hdir.dotProduct(ar_nodes[ar_main_camera_node_pos].Velocity) * 1.9438f;
4101 if (ar_num_aeroengines)
4105 float throttle = ar_aeroengines[i]->getThrottle();
4108 bool failed = ar_aeroengines[i]->isFailed();
4111 float pcent = ar_aeroengines[i]->getRPMpc();
4119 for (
int i = 0; i < ar_num_wings && i <
DD_MAX_WING; i++)
4122 float aoa = ar_wings[i].fa->aoa;
4128 if (ar_num_wings || ar_num_aeroengines)
4132 float ground_speed_kt = ar_nodes[0].Velocity.length() * 1.9438f;
4135 float altitude = ar_nodes[0].AbsPosition.y;
4137 float sea_level_pressure = 101325;
4139 float airpressure = sea_level_pressure * pow(1.0f - 0.0065f * altitude / 288.15f, 5.24947f);
4140 float airdensity = airpressure * 0.0000120896f;
4142 float knots = ground_speed_kt * sqrt(airdensity / 1.225f);
4148 float alt = ar_nodes[0].AbsPosition.y * 1.1811f;
4152 sprintf(altc,
"%03u", (
int)(ar_nodes[0].AbsPosition.y / 30.48f));
4161 if (!m_hud_features_ok)
4163 bool hasEngine = (ar_engine !=
nullptr);
4164 bool hasturbo =
false;
4165 bool autogearVisible =
false;
4169 hasturbo = ar_engine->HasTurbo();
4170 autogearVisible = (ar_engine->getAutoShift() != EngineSim::MANUALMODE);
4186 ar_dashboard->setEnabled(
DD_TIES_MODE, !ar_ties.empty());
4187 ar_dashboard->setEnabled(
DD_LOCKED, !ar_hooks.empty());
4191 ar_dashboard->updateFeatures();
4192 m_hud_features_ok =
true;
4218 ar_dashboard->setBool(
DD_SIGNAL_WARNING, m_blinker_right_lit && m_blinker_left_lit);
4227 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;
4229 float rollangle=asin(rollv.dotProduct(Vector3::UNIT_Y));
4232 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;
4234 float pitchangle=asin(dirv.dotProduct(Vector3::UNIT_Y));
4235 Vector3 upv=dirv.crossProduct(-rollv);
4236 if (upv.y<0) rollangle=3.14159-rollangle;
4242 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;
4244 float dirangle=atan2(idir.dotProduct(Vector3::UNIT_X), idir.dotProduct(-Vector3::UNIT_Z));
4246 if (curr_truck->autopilot)
4251 curr_truck->autopilot->getRadioFix(localizers, free_localizer, &vdev, &hdev);
4252 if (hdev>15) hdev=15;
4253 if (hdev<-15) hdev=-15;
4255 if (vdev>15) vdev=15;
4256 if (vdev<-15) vdev=-15;
4261 float vvi=curr_truck->ar_nodes[0].Velocity.y*196.85;
4262 if (vvi<1000.0 && vvi>-1000.0) angle=vvi*0.047;
4263 if (vvi>1000.0 && vvi<6000.0) angle=47.0+(vvi-1000.0)*0.01175;
4264 if (vvi>6000.0) angle=105.75;
4265 if (vvi<-1000.0 && vvi>-6000.0) angle=-47.0+(vvi+1000.0)*0.01175;
4266 if (vvi<-6000.0) angle=-105.75;
4270 if (curr_truck->aeroengines[0]->getType() == AeroEngineType::AE_XPROP)
4277 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4278 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4283 if (ftp>1 && curr_truck->aeroengines[1]->getType() == AeroEngineType::AE_XPROP)
4290 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4291 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4296 if (ftp>2 && curr_truck->aeroengines[2]->getType() == AeroEngineType::AE_XPROP)
4303 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4304 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4309 if (ftp>3 && curr_truck->aeroengines[3]->getType() == AeroEngineType::AE_XPROP)
4316 if (pcent<60.0) angle=-5.0+pcent*1.9167;
4317 else if (pcent<110.0) angle=110.0+(pcent-60.0)*4.075;
4330 ar_dashboard->
update(dt);
4333 void Actor::calculateLocalGForces()
4335 Vector3 cam_dir = this->GetCameraDir();
4336 Vector3 cam_roll = this->GetCameraRoll();
4337 Vector3 cam_up = cam_dir.crossProduct(cam_roll);
4341 float vertacc = m_camera_gforces.dotProduct(cam_up) + gravity;
4342 float longacc = m_camera_gforces.dotProduct(cam_dir);
4343 float latacc = m_camera_gforces.dotProduct(cam_roll);
4345 m_camera_local_gforces_cur = Vector3(vertacc, longacc, latacc) / gravity;
4348 if (m_reset_timer.getMilliseconds() > 500)
4350 m_camera_local_gforces_max.makeCeil(-m_camera_local_gforces_cur);
4351 m_camera_local_gforces_max.makeCeil(+m_camera_local_gforces_cur);
4367 ar_brake = triggerValue;
4391 unsigned int vector_index,
4396 : ar_nb_optimum(7, std::numeric_limits<float>::max())
4397 , ar_nb_reference(7, std::numeric_limits<float>::max())
4398 , m_tyre_pressure(this)
4399 , ar_nb_beams_scale(std::make_pair(1.0f, 1.0f))
4400 , ar_nb_shocks_scale(std::make_pair(1.0f, 1.0f))
4401 , ar_nb_wheels_scale(std::make_pair(1.0f, 1.0f))
4402 , ar_nb_beams_k_interval(std::make_pair(0.1f, 2.0f))
4403 , ar_nb_beams_d_interval(std::make_pair(0.1f, 2.0f))
4404 , ar_nb_shocks_k_interval(std::make_pair(0.1f, 8.0f))
4405 , ar_nb_shocks_d_interval(std::make_pair(0.1f, 8.0f))
4406 , ar_nb_wheels_k_interval(std::make_pair(1.0f, 1.0f))
4407 , ar_nb_wheels_d_interval(std::make_pair(1.0f, 1.0f))
4410 , m_avg_node_position_prev(rq.asr_position)
4412 , m_avg_node_position(rq.asr_position)
4413 , ar_instance_id(actor_id)
4414 , ar_vector_index(vector_index)
4415 , m_avg_proped_wheel_radius(0.2f)
4416 , ar_filename(rq.asr_filename)
4417 , m_section_config(rq.asr_config)
4418 , m_used_actor_entry(rq.asr_cache_entry)
4419 , m_used_skin_entry(rq.asr_skin_entry)
4420 , m_working_tuneup_def(rq.asr_working_tuneup)
4423 , ar_update_physics(false)
4424 , ar_disable_aerodyn_turbulent_drag(false)
4425 , ar_engine_hydraulics_ready(true)
4426 , ar_guisettings_use_engine_max_rpm(false)
4427 , ar_hydro_speed_coupling(false)
4428 , ar_collision_relevant(false)
4429 , ar_is_police(false)
4430 , ar_rescuer_flag(false)
4431 , ar_forward_commands(false)
4432 , ar_import_commands(false)
4433 , ar_toggle_ropes(false)
4434 , ar_toggle_ties(false)
4435 , ar_physics_paused(false)
4438 , m_hud_features_ok(false)
4439 , m_slidenodes_locked(false)
4440 , m_net_initialized(false)
4441 , m_water_contact(false)
4442 , m_water_contact_old(false)
4443 , m_has_command_beams(false)
4444 , m_custom_particles_enabled(false)
4445 , m_beam_break_debug_enabled(false)
4446 , m_beam_deform_debug_enabled(false)
4447 , m_trigger_debug_enabled(false)
4448 , m_disable_default_sounds(false)
4449 , m_disable_smoke(false)
4524 for (
int i = 0; i <
ar_flares.size(); i++)
4526 if (
ar_flares[i].controlnumber == number)
4535 for (
int i = 0; i <
ar_flares.size(); i++)
4575 return Ogre::MaterialPtr();
4580 std::vector<std::string> names;
4583 names.push_back(it->first);
4596 return Ogre::Vector3::ZERO;
4627 std::stringstream buf;
4629 buf <<
"[nodes]" << std::endl;
4639 <<
", loaded:" << (int)(
ar_nodes[i].nd_loaded_mass)
4641 <<
" wheel_rim:" << (int)
ar_nodes[i].nd_rim_node
4643 <<
" (set_node_defaults)"
4657 buf <<
"[beams]" << std::endl;
4661 <<
" " << std::setw(4) << i
4665 <<
" (set_beam_defaults/scale)"
4666 <<
" spring:" << std::setw(8) <<
ar_beams[i].
k
4667 <<
", damp:" << std::setw(8) <<
ar_beams[i].
d
4677 Ogre::DataStreamPtr outStream = Ogre::ResourceGroupManager::getSingleton().createResource(fileName,
RGN_LOGS,
true);
4678 std::string text = buf.str();
4679 outStream->write(text.c_str(), text.length());
4687 if (state.eventlock_present)
4690 if (ev_active && (ev_active != state.event_active_prev))
4692 state.anim_active = !state.anim_active;
4698 state.anim_active = ev_active;
4700 state.event_active_prev = ev_active;