static void update_server (entity *en) { cargo *raw; int loop; raw = get_local_entity_data (en); if (raw->mob.alive) { //////////////////////////////////////// for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { get_3d_terrain_point_data (raw->mob.position.x, raw->mob.position.z, &raw->terrain_info); basic_cargo_movement (en); } //////////////////////////////////////// } else { for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { basic_cargo_death_movement (en); } } }
static void update_recognition_guide_camera (camera *raw, object_3d_camera_index_numbers index) { entity *en; object_3d_instance *inst3d; viewpoint vp; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // get camera position and attitude // inst3d = (object_3d_instance *) get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT); ASSERT (inst3d); set_3d_exclusive_instance ( inst3d ); get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position); get_local_entity_attitude_matrix (en, inst3d->vp.attitude); get_object_3d_camera_position (inst3d, index, 0, 0.0, &vp); raw->position = vp.position; memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3)); // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + 0.5f); } // // motion vector // get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
void update_overview_camera (camera *raw) { entity *en; vec3d rel_camera_position; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // get camera attitude // get_3d_transformation_matrix (raw->attitude, get_local_entity_float_value (en, FLOAT_TYPE_HEADING) + rad (180.0), rad (-15.0), 0.0); // // get camera position // rel_camera_position.x = 0.0; rel_camera_position.y = 0.0; rel_camera_position.z = -get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position); get_local_entity_target_point (en, &raw->position); raw->position.x += rel_camera_position.x; raw->position.y += rel_camera_position.y; raw->position.z += rel_camera_position.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + 0.5f); } // // motion vector // get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
static void update_server (entity *en) { entity *parent, *next_segment, *prev_segment; entity_sub_types sub_type; vec3d *pos; float terrain_height; terrain_3d_point_data terrain_info; // // notify the segments neighbours as applicable // parent = get_local_entity_parent (en, LIST_TYPE_SEGMENT); ASSERT (parent); next_segment = get_local_entity_child_succ (en, LIST_TYPE_SEGMENT); if (next_segment) { notify_local_entity (ENTITY_MESSAGE_COLLISION, parent, next_segment); } prev_segment = get_local_entity_child_pred (en, LIST_TYPE_SEGMENT); if (prev_segment) { notify_local_entity (ENTITY_MESSAGE_COLLISION, parent, prev_segment); } sub_type = get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE); if (sub_type == ENTITY_SUB_TYPE_FIXED_BRIDGE_UNSUPPORTED_MID_SECTION) { // // make the segment drop to the floor ( removing it from the update list when it hits ) // pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); pos->y -= ( 10.0 * get_delta_time() ); memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); terrain_height = get_3d_terrain_point_data (pos->x, pos->z, &terrain_info); if (get_terrain_type_class (terrain_info.terrain_type) == TERRAIN_CLASS_WATER) { terrain_height -= 1.0; } if ( pos->y <= terrain_height ) { pos->y = terrain_height; delete_local_entity_from_parents_child_list (en, LIST_TYPE_UPDATE); if (get_comms_model () == COMMS_MODEL_SERVER) { create_client_server_object_hit_ground_explosion_effect (en, terrain_info.terrain_type); } } } else { // // segment is supported, and so should be instantly removed from the update list // ( only put there in the first place so that neighbours would be notified ) // delete_local_entity_from_parents_child_list (en, LIST_TYPE_UPDATE); } }
void reset_static_camera (camera *raw) { entity *en; vec3d pos, v; matrix3x3 m; float heading, z_min, z_max, radius, length; int fast_airborne; ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); radius = -(((z_max - z_min) * CHASE_CAMERA_RESET_ZOOM * CHASE_CAMERA_RESET_ZOOM) + z_min); fast_airborne = FALSE; if (get_local_entity_int_value (en, INT_TYPE_AIRBORNE_AIRCRAFT)) { if (get_local_entity_vec3d_magnitude (en, VEC3D_TYPE_MOTION_VECTOR) >= knots_to_metres_per_second (10.0)) { fast_airborne = TRUE; } } if (fast_airborne) { get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &v); normalise_3d_vector (&v); v.x *= radius; v.y *= radius; v.z *= radius; } else { heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); get_3d_transformation_matrix (m, heading, CHASE_CAMERA_RESET_PITCH, 0.0); v.x = 0.0; v.y = 0.0; v.z = radius; multiply_matrix3x3_vec3d (&v, m, &v); } get_local_entity_target_point (en, &pos); raw->position.x = pos.x + v.x; raw->position.y = pos.y + v.y; raw->position.z = pos.z + v.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // attitude // v.x = pos.x - raw->position.x; v.y = pos.y - raw->position.y; v.z = pos.z - raw->position.z; length = (v.x * v.x) + (v.y * v.y) + (v.z * v.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&v, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &v); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // raw->motion_vector.x = 0.0; raw->motion_vector.y = 0.0; raw->motion_vector.z = 0.0; }
static void update_client (entity *en) { helicopter *raw; int loop; aircraft_damage_types damage_type; raw = get_local_entity_data (en); update_local_entity_view_interest_level (en); update_local_helicopter_rotor_sounds (en); damage_type = aircraft_critically_damaged (en); if (raw->ac.mob.alive) { switch (raw->player) { //////////////////////////////////////// case ENTITY_PLAYER_AI: //////////////////////////////////////// { //////////////////////////////////////// for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { helicopter_death_movement (en); } else { if (!get_local_entity_int_value (en, INT_TYPE_LANDED)) { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); } helicopter_movement (en); } } //////////////////////////////////////// //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_rotors (en); update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); } // //////////////////////////////////////// break; } //////////////////////////////////////// case ENTITY_PLAYER_LOCAL: //////////////////////////////////////// { if (en != get_gunship_entity ()) { // // Client might be waiting for server to set old gunship to AI controlled. // return; } if (raw->invulnerable_timer > 0.0) { raw->invulnerable_timer -= get_delta_time (); } update_current_flight_dynamics_fuel_weight (); if ((!fire_continuous_weapon) && (get_local_entity_sound_type_valid (en, weapon_database [raw->ac.selected_weapon].launch_sound_effect_sub_type))) { pause_client_server_continuous_weapon_sound_effect (en, raw->ac.selected_weapon); } //helicopter_death_movement (en); //////////////////////////////////////// if ((!get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) && (!get_local_entity_int_value (en, INT_TYPE_EJECTED))) { update_flight_dynamics (); transmit_entity_comms_message (ENTITY_COMMS_UPDATE, en); } else { if (get_local_entity_int_value (en, INT_TYPE_LANDED)) { if (get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) { set_current_flight_dynamics_rotor_brake (TRUE); set_current_flight_dynamics_auto_pilot (FALSE); current_flight_dynamics->input_data.collective.value = 0.0; } } if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED)) || (get_local_entity_int_value (en, INT_TYPE_LANDED))) { set_current_flight_dynamics_auto_pilot (FALSE); } for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { helicopter_death_movement (en); } else { if (!get_local_entity_int_value (en, INT_TYPE_LANDED)) { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); } helicopter_movement (en); if (get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) { set_dynamics_entity_values (get_gunship_entity ()); } } } } //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); update_avionics (); update_cockpits (); update_aircraft_decoy_release (en); } // //////////////////////////////////////// // // Check if gunship has a task - if not then set gunship entity to NULL // if (!get_local_entity_parent (en, LIST_TYPE_FOLLOWER)) { if (!get_local_entity_int_value (en, INT_TYPE_EJECTED)) { if (en == get_gunship_entity ()) { set_gunship_entity (NULL); } } } break; } //////////////////////////////////////// case ENTITY_PLAYER_REMOTE: //////////////////////////////////////// { //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); } if ((get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { // no need for death_movement as if the remote_player is damaged it will default back to manual flight. if (get_local_entity_int_value (en, INT_TYPE_EJECTED)) { helicopter_death_movement (en); } else { if (!get_local_entity_int_value (en, INT_TYPE_LANDED)) { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); } helicopter_movement (en); } } } else { interpolate_entity_position (en); } // //////////////////////////////////////// break; } } } else { if (get_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_DEAD) { } else { for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { helicopter_death_movement (en); } } } }
static void update_server (entity *en) { entity *group; helicopter *raw; int loop; aircraft_damage_types damage_type; raw = get_local_entity_data (en); update_local_entity_view_interest_level (en); update_local_helicopter_rotor_sounds (en); damage_type = aircraft_critically_damaged (en); if (raw->ac.mob.alive) { switch (raw->player) { //////////////////////////////////////// case ENTITY_PLAYER_AI: //////////////////////////////////////// { //////////////////////////////////////// for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { helicopter_death_movement (en); } else { if (!get_local_entity_int_value (en, INT_TYPE_LANDED)) { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); } helicopter_movement (en); } } // provide resync for AI wingmen group = get_local_entity_parent (en, LIST_TYPE_MEMBER); if (group) { if ((get_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE) != OPERATIONAL_STATE_LANDED) && (get_local_entity_int_value (group, INT_TYPE_MULTIPLAYER_GROUP))) { transmit_entity_comms_message (ENTITY_COMMS_UPDATE, en); } } //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_rotors (en); update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_rudder (en); update_aircraft_target_scan (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); update_aircraft_weapon_fire (en); update_aircraft_decoy_release (en); } // //////////////////////////////////////// break; } //////////////////////////////////////// case ENTITY_PLAYER_LOCAL: //////////////////////////////////////// { ASSERT (en == get_gunship_entity ()); if (raw->invulnerable_timer > 0.0) { raw->invulnerable_timer -= get_delta_time (); } update_current_flight_dynamics_fuel_weight (); update_current_flight_dynamics_flight_time (); //////////////////////////////////////// if ((!get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) && (!get_local_entity_int_value (en, INT_TYPE_EJECTED))) { update_flight_dynamics (); update_player_helicopter_waypoint_distance (en); } else { if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED)) || (get_local_entity_int_value (en, INT_TYPE_LANDED))) { set_current_flight_dynamics_auto_pilot (FALSE); if (get_local_entity_int_value (en, INT_TYPE_LANDED)) { set_current_flight_dynamics_rotor_brake (TRUE); current_flight_dynamics->input_data.collective.value = 0.0; } } for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { if (get_local_entity_int_value (en, INT_TYPE_EJECTED)) { helicopter_death_movement (en); } else { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); helicopter_movement (en); if (get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) { set_dynamics_entity_values (en); } } } } //////////////////////////////////////// transmit_entity_comms_message (ENTITY_COMMS_UPDATE, en); //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); update_avionics (); update_cockpits (); update_aircraft_decoy_release (en); } // //////////////////////////////////////// // // Check if gunship has a task - if not then set gunship entity to NULL // if (!get_local_entity_parent (en, LIST_TYPE_FOLLOWER)) { if (!get_local_entity_int_value (en, INT_TYPE_EJECTED)) { if (en == get_gunship_entity ()) { set_gunship_entity (NULL); } } } break; } //////////////////////////////////////// case ENTITY_PLAYER_REMOTE: //////////////////////////////////////// { //////////////////////////////////////// if (raw->invulnerable_timer > 0.0) { raw->invulnerable_timer -= get_delta_time (); } if ((get_local_entity_int_value (en, INT_TYPE_AUTO_PILOT)) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { if ((damage_type == AIRCRAFT_DAMAGE_CRITICAL) || (get_local_entity_int_value (en, INT_TYPE_EJECTED))) { helicopter_death_movement (en); } else { if (!get_local_entity_int_value (en, INT_TYPE_LANDED)) { get_3d_terrain_point_data (raw->ac.mob.position.x, raw->ac.mob.position.z, &raw->ac.terrain_info); } helicopter_movement (en); } } #if DEBUG_MODULE debug_log ("HC_UPDT: SERVER: moving client %d using AUTO PILOT", get_local_entity_index (en)); #endif } else { interpolate_entity_position (en); update_player_helicopter_waypoint_distance (en); } //////////////////////////////////////// // // ORDER IS CRITICAL // if (raw->ac.mob.alive) { update_aircraft_loading_doors (en); update_aircraft_cargo_doors (en); update_aircraft_undercarriage (en); update_aircraft_weapon_system_ready (en); update_entity_weapon_systems (en); update_entity_weapon_system_weapon_and_target_vectors (en); } // //////////////////////////////////////// break; } } } else { if (get_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_DEAD) { raw->ac.death_timer -= get_delta_time (); if (raw->ac.death_timer <= 0.0) { if (get_local_entity_int_value (en, INT_TYPE_PLAYER) == ENTITY_PLAYER_AI) { // // don't destroy helicopters while they are still occupied by players (otherwise avionics / pilot-entity etc. don't get deinitialised) // destroy_client_server_entity_family (en); } else { raw->ac.death_timer = 0.0; } } } else { for (loop = 0; loop < get_entity_movement_iterations (); loop ++) { helicopter_death_movement (en); } } } }
void update_cinematic_camera_continued (camera *raw) { entity *en; object_3d_instance *inst3d; viewpoint vp; float normalised_timer; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // get camera position and attitude // switch (raw->cinematic_camera_index) { //////////////////////////////////////// case OBJECT_3D_INVALID_CAMERA_INDEX: //////////////////////////////////////// { float combined_heading, z_min, z_max; vec3d rel_camera_position; combined_heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); combined_heading += raw->cinematic_camera_heading; get_3d_transformation_matrix (raw->attitude, combined_heading, raw->cinematic_camera_pitch, 0.0); z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); rel_camera_position.x = 0.0; rel_camera_position.y = 0.0; rel_camera_position.z = -(((z_max - z_min) * 0.1) + z_min); multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position); get_local_entity_target_point (en, &raw->position); raw->position.x += rel_camera_position.x; raw->position.y += rel_camera_position.y; raw->position.z += rel_camera_position.z; break; } //////////////////////////////////////// case OBJECT_3D_CAMERA_SCENIC_MOVING: //////////////////////////////////////// { normalised_timer = raw->cinematic_camera_timer / raw->cinematic_camera_lifetime; inst3d = get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT); get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position); get_local_entity_attitude_matrix (en, inst3d->vp.attitude); get_object_3d_camera_position (inst3d, raw->cinematic_camera_index, raw->cinematic_camera_depth, normalised_timer, &vp); raw->position = vp.position; memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3)); break; } //////////////////////////////////////// case OBJECT_3D_CAMERA_SCENIC_STATIC: //////////////////////////////////////// { normalised_timer = 0.0; inst3d = get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT); get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position); get_local_entity_attitude_matrix (en, inst3d->vp.attitude); get_object_3d_camera_position (inst3d, raw->cinematic_camera_index, raw->cinematic_camera_depth, normalised_timer, &vp); raw->position = vp.position; memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3)); break; } } // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + 0.5); } // // motion vector // get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
void reset_drop_camera (camera *raw) { entity *en; vec3d pos, v; matrix3x3 m; float heading, z_min, z_max; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // place camera behind object to prevent going inside object (especially when the object is stationary) // heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); get_3d_transformation_matrix (m, heading, CHASE_CAMERA_RESET_PITCH, 0.0); z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); v.x = 0.0; v.y = 0.0; v.z = -(((z_max - z_min) * CHASE_CAMERA_RESET_ZOOM * CHASE_CAMERA_RESET_ZOOM) + z_min); multiply_matrix3x3_vec3d (&v, m, &v); get_local_entity_target_point (en, &pos); raw->position.x = pos.x + v.x; raw->position.y = pos.y + v.y; raw->position.z = pos.z + v.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // motion vector // raw->motion_vector.x = 0.0; raw->motion_vector.y = 0.0; raw->motion_vector.z = 0.0; }
void draw_downwash_effect(entity *en) { vec3d *position, pos; terrain_3d_point_data terrain_info; float main_rotor_radius, main_rotor_rpm, min_altitude; int number_of_main_rotors; terrain_types type_of_terrain; downwash_types type_of_downwash; ASSERT( en ); ASSERT (get_local_entity_type (en) == ENTITY_TYPE_HELICOPTER); if (!get_local_entity_int_value (en, INT_TYPE_ALIVE)) { return; } if (get_local_entity_int_value (en, INT_TYPE_OBJECT_DRAWN_ONCE_THIS_FRAME)) { return; } if (get_time_acceleration () == TIME_ACCELERATION_PAUSE) { return; } memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); main_rotor_rpm = get_local_entity_float_value (en, FLOAT_TYPE_MAIN_ROTOR_RPM); position = get_local_entity_vec3d_ptr(en, VEC3D_TYPE_POSITION); pos.x = position->x; pos.y = position->y - aircraft_database [get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)].centre_of_gravity_to_ground_distance; pos.z = position->z; get_3d_terrain_point_data (pos.x, pos.z, &terrain_info); min_altitude = get_3d_terrain_point_data_elevation (&terrain_info); //Xhit: main_rotor_radius is got here because DOWNWASH_EFFECT_MAX_ALTITUDE depends on it. (030328) main_rotor_radius = aircraft_database [get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)].main_rotor_radius; if((main_rotor_rpm > 1.0) && ((pos.y - min_altitude) < DOWNWASH_EFFECT_MAX_ALTITUDE)) { number_of_main_rotors = (int) aircraft_database [get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)].number_of_main_rotors; type_of_terrain = get_3d_terrain_point_data_type(&terrain_info); switch( get_terrain_type_class(type_of_terrain) ) { case TERRAIN_CLASS_LAND: { if(number_of_main_rotors > 1) type_of_downwash = DOWNWASH_TYPE_LAND_DUAL_ROTORS; else type_of_downwash = DOWNWASH_TYPE_LAND; create_downwash_effect(type_of_downwash, &pos, main_rotor_radius, main_rotor_rpm, min_altitude); break; } case TERRAIN_CLASS_WATER: { if(number_of_main_rotors > 1) type_of_downwash = DOWNWASH_TYPE_WATER_DUAL_ROTORS; else type_of_downwash = DOWNWASH_TYPE_WATER; create_downwash_effect(type_of_downwash, &pos, main_rotor_radius, main_rotor_rpm, min_altitude); break; } //Xhit: No downwash effect for FORESTS. (030328) case TERRAIN_CLASS_FOREST: default: { break; } } } return; }
int create_downwash_effect_component(downwash_component *this_downwash_component, downwash_types downwash_type, vec3d *position, int *entity_index_list, float main_rotor_radius, float main_rotor_rpm, float min_altitude) { int loop, count, terrain_type, trail_type; short int quadrant_x, quadrant_z; unsigned char alpha_percentage; float lifetime, lifetime_min, lifetime_max, scale_min, scale_max, scale, angle, radius, relative_radius, height, altitude, half_altitude, main_rotor_radius_minus_altitude; vec3d pos, offset, iv; terrain_3d_point_data terrain_info; entity *new_entity; memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); count = this_downwash_component->trail_count; if ( count < 1 ) { return 0; } // Xhit: This is the altitude of the helicopter relative to the ground level. (030328) altitude = position->y - min_altitude; half_altitude = (altitude / 2.0); main_rotor_radius_minus_altitude = main_rotor_radius - altitude; scale_min = this_downwash_component->scale_min; scale_max = this_downwash_component->scale_max; lifetime_min = this_downwash_component->lifetime_min; lifetime_max = this_downwash_component->lifetime_max; // Xhit: initialising quadrant variables (030328) quadrant_x = 1; quadrant_z = 1; // // create smoke trails // for ( loop = 0 ; loop < count ; loop ++ ) { lifetime = lifetime_min + fabs( ( lifetime_max - lifetime_min ) * sfrand1() ); angle = frand1() * PI_OVER_TWO; relative_radius = main_rotor_radius * frand1(); scale = relative_radius + scale_min; if(scale > scale_max) scale = scale_max; switch(downwash_type) { case DOWNWASH_TYPE_LAND: case DOWNWASH_TYPE_LAND_DUAL_ROTORS: { //Xhit: If altitude bigger than main rotor radius then the smoke should be centered beneath the helicopter. (030328) if(altitude >= main_rotor_radius) { radius = relative_radius; height = (half_altitude * (radius / main_rotor_radius) + half_altitude) * frand1(); }else { radius = relative_radius + main_rotor_radius_minus_altitude; height = (half_altitude * ((radius - main_rotor_radius_minus_altitude) / main_rotor_radius) + half_altitude + scale ) * frand1(); } break; } case DOWNWASH_TYPE_WATER: case DOWNWASH_TYPE_WATER_DUAL_ROTORS: { if(altitude >= main_rotor_radius) { radius = relative_radius; }else { radius = relative_radius + main_rotor_radius_minus_altitude; } // Xhit: Changed to 2 instead of main_rotor_radius so smoke is created just over water level (030515) height = 2 * frand1(); break; } default: { debug_fatal("DOWNWASH : trying to create an unrecogniseable downwash effect"); break; } } //Xhit: If main rotor(s) only (not displaced main rotors) then. (030328) if((this_downwash_component->create_in_all_quadrants) && (loop < 4)) { //Xhit: This cryptical thing is to determine in which quadrant this sprite is going to be created. (030328) // ^z // | // 1|0 x // -+---> // 3|2 // // loop = 0 -> x= 1, z= 1; loop = 1 -> x= -1, z= 1; // loop = 2 -> x= 1, z= -1; loop = 3 -> x= -1, z= -1; quadrant_x = 1 | -(loop & 1); quadrant_z = 1 | -(loop & 2); offset.x = quadrant_x * radius * ( cos ( angle ) ); offset.y = height; offset.z = quadrant_z * radius * ( sin ( angle ) ); }else //Xhit: If scattered downwash effect and if the heli got more than one main rotor (on different axis) then // add two more trails at the sides of the heli. (030328) if((this_downwash_component->create_in_all_quadrants) && (loop >= 4) && (count == 6)) { //Xhit: loop = 4 -> x= 1; loop = 5 -> x= -1; (030328) quadrant_x = 1 | -(loop & 1); relative_radius = main_rotor_radius * frand1(); offset.x = quadrant_x * radius; offset.y = height; offset.z = frand1() * (main_rotor_radius / 2); }else { debug_fatal("DOWNWASH : trying to create an unrecogniseable downwash effect"); } pos.x = position->x + offset.x ; pos.z = position->z + offset.z; //Xhit: This is necessary if it's going to work on tilting terrain. (030328) get_3d_terrain_point_data (pos.x, pos.z, &terrain_info); pos.y = get_3d_terrain_point_data_elevation (&terrain_info); pos.y = pos.y + offset.y; bound_position_to_map_volume( &pos ); //Xhit: Decide which trail type is going to be used, this makes mapping to type of downwash effect fast. (030328) terrain_type = get_3d_terrain_point_data_type(&terrain_info); trail_type = get_terrain_surface_type(terrain_type) + SMOKE_LIST_TYPE_DOWNWASH_START; #if DEBUG_MODULE debug_log("DOWNWASH.C: terrain_type: %d, trail_type: %d", terrain_type, trail_type); #endif iv.x = pos.x - position->x; iv.y = relative_radius; iv.z = pos.z - position->z; //Xhit: If heli on ground then let the dust-smoke fade in according to increasing main_rotor_rpm // otherwise set it according to the altitude of the heli (higher = less dust smoke) (030328) if(altitude < 1.0) { alpha_percentage = (unsigned char)(main_rotor_rpm); }else { //Xhit: "+ 1.0" is to guarantee that alpha_percentage > 0. (030328) alpha_percentage = (unsigned char)((1.0 - (altitude / (DOWNWASH_EFFECT_MAX_ALTITUDE + 1.0))) * 100); } new_entity = create_local_entity ( ENTITY_TYPE_SMOKE_LIST, entity_index_list[ loop ], ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_DOWNWASH), ENTITY_ATTR_INT_VALUE (INT_TYPE_SMOKE_TYPE, trail_type), ENTITY_ATTR_INT_VALUE (INT_TYPE_COLOUR_ALPHA, alpha_percentage), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_GENERATOR_LIFETIME, this_downwash_component->generator_lifetime), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_FREQUENCY, this_downwash_component->frequency), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_SMOKE_LIFETIME, lifetime), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_SCALE, scale), ENTITY_ATTR_VEC3D (VEC3D_TYPE_INITIAL_VELOCITY, iv.x, iv.y, iv.z), ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z), ENTITY_ATTR_END ); entity_index_list[ loop ] = get_local_entity_index( new_entity ); } return count; }
int check_position_line_of_sight (entity *source, entity *target, vec3d *source_position, vec3d *target_position, mobile_los_check_criteria criteria) { entity *collision_en; vec3d increment, collision_point, normal, #if LINE_DEBUG_MODULE old_position, #endif check_position, direction; float target_range, collision_distance, number_of_terrain_checks, terrain_elevation; terrain_3d_point_data terrain_info; ASSERT (source); ASSERT (target); ASSERT (source_position); ASSERT (target_position); direction.x = target_position->x - source_position->x; direction.y = target_position->y - source_position->y; direction.z = target_position->z - source_position->z; target_range = sqrt ((direction.x * direction.x) + (direction.z * direction.z)); normalise_3d_vector (&direction); //////////////////////////////////////////////////////////////// // COARSE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_COURSE_TERRAIN) { number_of_terrain_checks = target_range / LOS_COARSE_CHECK_DISTANCE; increment.x = direction.x * LOS_COARSE_CHECK_DISTANCE; increment.y = direction.y * LOS_COARSE_CHECK_DISTANCE; increment.z = direction.z * LOS_COARSE_CHECK_DISTANCE; check_position = *source_position; memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed COURSE terrain LOS", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_SOURCE_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_SOURCE_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_SOURCE_END; check_position = *source_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // TARGET END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_TARGET_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_TARGET_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_TARGET_END; check_position = *target_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x -= increment.x; check_position.y -= increment.y; check_position.z -= increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_OBJECTS) { check_position.x = source_position->x + (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = source_position->y + (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = source_position->z + (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, source_position, &check_position, &collision_point, &normal ); if (collision_en) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } //////////////////////////////////////////////////////////////// // TARGET END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_OBJECTS) { check_position.x = target_position->x - (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = target_position->y - (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = target_position->z - (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, target_position, &check_position, &collision_point, &normal ); if (collision_en) { collision_distance = get_sqr_3d_range (&collision_point, target_position); if (collision_distance > (LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END * LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END)) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } } return TRUE; }
void set_reverse_tactical_camera_values (entity *source, entity *target) { camera *raw; int airborne; object_3d_index_numbers object_3d_index; object_3d_bounds *bounding_box; float length, radius, z_min, z_max, rad_alt, dx, dy, dz; vec3d source_position, target_position, direction; ASSERT (source); ASSERT (target); ASSERT (get_camera_entity ()); raw = get_local_entity_data (get_camera_entity ()); // // get camera position // if (get_local_entity_int_value (target, INT_TYPE_IDENTIFY_FIXED)) { object_3d_index = get_local_entity_int_value (target, INT_TYPE_OBJECT_3D_SHAPE); bounding_box = get_object_3d_bounding_box (object_3d_index); dx = bounding_box->xmax - bounding_box->xmin; dy = bounding_box->ymax; dz = bounding_box->zmax - bounding_box->zmin; radius = sqrt ((dx * dx) + (dy * dy) + (dz * dz)) * 2.0; } else { z_min = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); radius = ((z_max - z_min) * 0.05) + z_min; } get_local_entity_target_point (source, &source_position); get_local_entity_target_point (target, &target_position); airborne = FALSE; if (get_local_entity_int_value (target, INT_TYPE_AIRBORNE_AIRCRAFT)) { if (point_inside_map_area (&target_position)) { rad_alt = max (target_position.y - get_3d_terrain_elevation (target_position.x, target_position.z), 0.0); if (rad_alt > z_min) { airborne = TRUE; } } } if (airborne) { direction.x = target_position.x - source_position.x; direction.y = target_position.y - source_position.y; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.y = 0.0; direction.z = -1.0; } } else { direction.x = target_position.x - source_position.x; direction.y = 0.0; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.z = -1.0; } direction.y = 0.5; normalise_3d_vector (&direction); } raw->position.x = target_position.x + (direction.x * radius); raw->position.y = target_position.y + (direction.y * radius); raw->position.z = target_position.z + (direction.z * radius); // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // get camera attitude // direction.x = target_position.x - raw->position.x; direction.y = target_position.y - raw->position.y; direction.z = target_position.z - raw->position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &direction); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // get_local_entity_vec3d (target, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
entity *create_client_server_entity_fixed_wing (int index, entity_sub_types sub_type, entity *group, vec3d *position) { entity *new_entity; fixed_wing *raw; ASSERT (get_comms_model() == COMMS_MODEL_SERVER); // // create fixed wing entity // new_entity = create_client_server_entity ( ENTITY_TYPE_FIXED_WING, index, ENTITY_ATTR_PARENT (LIST_TYPE_MEMBER, group), ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type), ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, position->x, position->y, position->z), ENTITY_ATTR_END ); // // create and attach special effects // { sound_sample_indices sound_sample_index; // // damage smoke // attach_fixed_wing_meta_smoke_lists (new_entity); // // sound effects // sound_sample_index = aircraft_database [sub_type].continuous_sound_effect_index; create_client_server_sound_effect_entity ( new_entity, ENTITY_SIDE_NEUTRAL, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1, SOUND_CHANNEL_SOUND_EFFECT, SOUND_LOCALITY_ALL, NULL, // position 1.0, // amplification FALSE, // valid sound effect TRUE, // looping 1, // sample count &sound_sample_index // sample index list ); sound_sample_index = SOUND_SAMPLE_INDEX_JET_AFTERBURNER; create_client_server_sound_effect_entity ( new_entity, ENTITY_SIDE_NEUTRAL, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2, SOUND_CHANNEL_SOUND_EFFECT, SOUND_LOCALITY_ALL, NULL, // position 1.0, // amplification FALSE, // valid sound effect TRUE, // looping 1, // sample count &sound_sample_index // sample index list ); } // // initialise terrain elevation cache // raw = get_local_entity_data (new_entity); get_3d_terrain_point_data (position->x, position->z, &raw->ac.terrain_info); return new_entity; }
void update_chase_camera (camera *raw) { entity *en; float combined_heading, z_min, z_max; vec3d rel_camera_position; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // adjust camera heading // if (adjust_view_left_key || joystick_pov_left) { raw->chase_camera_heading += CHASE_CAMERA_ROTATE_RATE * get_delta_time (); } else if (adjust_view_right_key || joystick_pov_right) { raw->chase_camera_heading -= CHASE_CAMERA_ROTATE_RATE * get_delta_time (); } raw->chase_camera_heading = wrap_angle (raw->chase_camera_heading); // // adjust camera pitch // if (adjust_view_up_key || joystick_pov_up) { raw->chase_camera_pitch -= CHASE_CAMERA_ROTATE_RATE * get_delta_time (); raw->chase_camera_pitch = max (CHASE_CAMERA_ROTATE_DOWN_LIMIT, raw->chase_camera_pitch); } else if (adjust_view_down_key || joystick_pov_down) { raw->chase_camera_pitch += CHASE_CAMERA_ROTATE_RATE * get_delta_time (); raw->chase_camera_pitch = min (CHASE_CAMERA_ROTATE_UP_LIMIT, raw->chase_camera_pitch); } if (adjust_view_zoom_in_key) { raw->chase_camera_zoom -= CHASE_CAMERA_ZOOM_RATE * get_delta_time (); raw->chase_camera_zoom = max (CHASE_CAMERA_ZOOM_IN_LIMIT, raw->chase_camera_zoom); } else if (adjust_view_zoom_out_key) { raw->chase_camera_zoom += CHASE_CAMERA_ZOOM_RATE * get_delta_time (); raw->chase_camera_zoom = min (CHASE_CAMERA_ZOOM_OUT_LIMIT, raw->chase_camera_zoom); } // // get camera attitude // if (get_local_entity_int_value (en, INT_TYPE_ALIVE) && raw->chase_camera_lock_rotate) { combined_heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); } else { combined_heading = 0.0; } combined_heading += raw->chase_camera_heading; get_3d_transformation_matrix (raw->attitude, combined_heading, raw->chase_camera_pitch, 0.0); // // get camera position // if (in_flight_zoom_test) { z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE_TEST); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE_TEST); } else { z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); } ASSERT (z_min < z_max); rel_camera_position.x = 0.0; rel_camera_position.y = 0.0; rel_camera_position.z = -(((z_max - z_min) * raw->chase_camera_zoom * raw->chase_camera_zoom) + z_min); multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position); get_local_entity_target_point (en, &raw->position); raw->position.x += rel_camera_position.x; raw->position.y += rel_camera_position.y; raw->position.z += rel_camera_position.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // motion vector // get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; routed_vehicle *raw; entity_sub_types group_sub_type; float heading; vec3d *face_normal; //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// validate_local_create_entity_index (index); #if DEBUG_MODULE debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_CREATE, NULL, type, index); #endif en = get_free_entity (index); if (en) { //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = malloc_fast_mem (sizeof (routed_vehicle)); set_local_entity_data (en, raw); //////////////////////////////////////// // // INITIALISE ALL ENTITY DATA TO 'WORKING' DEFAULT VALUES // // DO NOT USE ACCESS FUNCTIONS // // DO NOT USE RANDOM VALUES // //////////////////////////////////////// memset (raw, 0, sizeof (routed_vehicle)); // // mobile // raw->vh.mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->vh.mob.position.x = MID_MAP_X; raw->vh.mob.position.y = MID_MAP_Y; raw->vh.mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->vh.mob.attitude); raw->vh.mob.alive = TRUE; raw->vh.mob.side = ENTITY_SIDE_UNINITIALISED; raw->vh.operational_state = OPERATIONAL_STATE_UNKNOWN; // // vehicle // raw->vh.object_3d_shape = OBJECT_3D_INVALID_OBJECT_INDEX; raw->vh.weapon_config_type = WEAPON_CONFIG_TYPE_UNINITIALISED; raw->vh.selected_weapon = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; raw->vh.weapon_vector.x = 0.0; raw->vh.weapon_vector.y = 0.0; raw->vh.weapon_vector.z = 1.0; raw->vh.weapon_to_target_vector.x = 0.0; raw->vh.weapon_to_target_vector.y = 0.0; raw->vh.weapon_to_target_vector.z = -1.0; raw->vh.loading_door_state = VEHICLE_LOADING_DOORS_OPEN_FLOAT_VALUE; // // routed // //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->vh.member_link.parent); ASSERT (get_local_entity_type (raw->vh.member_link.parent) == ENTITY_TYPE_GROUP); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// raw->sub_route = NULL; // // side // if (raw->vh.mob.side == ENTITY_SIDE_UNINITIALISED) { raw->vh.mob.side = get_local_entity_int_value (raw->vh.member_link.parent, INT_TYPE_SIDE); } ASSERT (raw->vh.mob.side != ENTITY_SIDE_NEUTRAL); // // sub_type // if (raw->vh.mob.sub_type == ENTITY_SUB_TYPE_UNINITIALISED) { group_sub_type = get_local_entity_int_value (raw->vh.member_link.parent, INT_TYPE_ENTITY_SUB_TYPE); if (raw->vh.mob.side == ENTITY_SIDE_BLUE_FORCE) { raw->vh.mob.sub_type = group_database[group_sub_type].default_blue_force_sub_type; } else { raw->vh.mob.sub_type = group_database[group_sub_type].default_red_force_sub_type; } } ASSERT (entity_sub_type_vehicle_valid (raw->vh.mob.sub_type)); // // 3D shape // if (raw->vh.object_3d_shape == OBJECT_3D_INVALID_OBJECT_INDEX) { raw->vh.object_3d_shape = vehicle_database[raw->vh.mob.sub_type].default_3d_shape; } // // weapon config // if (raw->vh.weapon_config_type == WEAPON_CONFIG_TYPE_UNINITIALISED) { raw->vh.weapon_config_type = vehicle_database[raw->vh.mob.sub_type].default_weapon_config_type; } ASSERT (weapon_config_type_valid (raw->vh.weapon_config_type)); // // damage levels // raw->vh.damage_level = vehicle_database[raw->vh.mob.sub_type].initial_damage_level; // // radar dish rotation (ok to use a random number as this is for visual effect only) // raw->vh.radar_rotation_state = frand1 (); //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// // // 3D object // raw->vh.inst3d = construct_3d_object (raw->vh.object_3d_shape); set_routed_vehicle_id_number (en); set_initial_rotation_angle_of_routed_vehicle_wheels (raw->vh.inst3d); // // align with terrain // get_3d_terrain_point_data (raw->vh.mob.position.x, raw->vh.mob.position.z, &raw->vh.terrain_info); heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); face_normal = get_3d_terrain_point_data_normal (&raw->vh.terrain_info); get_3d_transformation_matrix_from_face_normal_and_heading (raw->vh.mob.attitude, face_normal, heading); // // weapon config // raw->vh.weapon_package_status_array = malloc_fast_mem (SIZE_WEAPON_PACKAGE_STATUS_ARRAY); memset (raw->vh.weapon_package_status_array, 0, SIZE_WEAPON_PACKAGE_STATUS_ARRAY); load_local_entity_weapon_config (en); // // update force info // add_to_force_info (get_local_force_entity (raw->vh.mob.side), en); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_MEMBER, raw->vh.member_link.parent, raw->vh.member_link.child_pred); // // insert into LIST_TYPE_MEMBER before LIST_TYPE_VIEW // insert_local_entity_into_parents_child_list (en, LIST_TYPE_VIEW, get_camera_entity (), get_local_entity_view_list_pred (en)); insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->vh.mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } return (en); }
void reset_satellite_camera (camera *raw) { entity *en; vec3d pos, v; matrix3x3 m; float heading, z_min, z_max, length; ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); //ASSERT (z_min < z_max); heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); get_3d_transformation_matrix (m, heading, CHASE_CAMERA_RESET_PITCH, 0.0); v.x = 0.0; v.y = 0.0; v.z = 0.0; multiply_matrix3x3_vec3d (&v, m, &v); get_local_entity_target_point (en, &pos); raw->position.x = pos.x + v.x; raw->position.y = pos.y + v.y; raw->position.z = pos.z + v.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } raw->motion_vector.y = raw->position.y; raw->position.y += 5000; // // attitude // v.x = pos.x - raw->position.x; v.y = pos.y - raw->position.y; v.z = pos.z - raw->position.z; length = (v.x * v.x) + (v.y * v.y) + (v.z * v.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&v, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &v); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // raw->motion_vector.x = 0.0; raw->motion_vector.z = 0.0; raw->fly_by_camera_timer = frand1() * 150 + 80; // parasiting on the struct, can't get my own data... }