void update_person_animation (entity *en) { person *raw; int wrapped, state; float frequency, remainder; ASSERT( en ); raw = (person *) get_local_entity_data (en); //update character animation get_keyframed_animation_state (raw->person_animation_state, &state, &remainder); if (get_local_entity_int_value (en, INT_TYPE_ALIVE)) { if (state != PERSON_ANIM_NONE) { frequency = 1.0 / person_animation_database[state].duration; wrapped = update_entity_simple_keyframed_value (en, &remainder, frequency); if ( (wrapped) && (!person_animation_database[state].repeat) ) { int state_selector; // set new animation that isn't same as previous state_selector = rand16 () % 4; switch ( state_selector ) { case 0: state = ( state == PERSON_ANIM_STAND1 ) ? PERSON_ANIM_STAND2 : PERSON_ANIM_STAND1; break; case 1: state = ( state == PERSON_ANIM_STAND2 ) ? PERSON_ANIM_STAND3 : PERSON_ANIM_STAND2; break; case 2: state = ( state == PERSON_ANIM_STAND3 ) ? PERSON_ANIM_STAND4 : PERSON_ANIM_STAND3; break; case 3: state = ( state == PERSON_ANIM_STAND4 ) ? PERSON_ANIM_STAND1 : PERSON_ANIM_STAND4; break; } remainder = 0.0; raw->person_animation_state = state + remainder; ASSERT ( raw->person_animation_state < NUM_PERSON_ANIMS ); } else { raw->person_animation_state = state + remainder; ASSERT ( raw->person_animation_state < NUM_PERSON_ANIMS ); } } } else { raw->person_animation_state += 1.4 * get_entity_movement_delta_time (); if (raw->person_animation_state >= 1.0) { raw->person_animation_state = 1.0; } } }
void ship_vehicle_death_movement (entity *en) { ship_vehicle *raw; float speed, heading, pitch, roll; vec3d *pos, *velocity, new_pos; raw = get_local_entity_data (en); // // work out new position // velocity = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_MOTION_VECTOR); pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); new_pos.x = pos->x + (velocity->x * get_entity_movement_delta_time()); new_pos.y = pos->y + (velocity->y * get_entity_movement_delta_time()); new_pos.z = pos->z + (velocity->z * get_entity_movement_delta_time()); // // update velocity // velocity->x -= (velocity->x * 0.2 * get_entity_movement_delta_time ()); velocity->z -= (velocity->z * 0.2 * get_entity_movement_delta_time ()); velocity->y -= (SHIP_SINK_RATE * get_entity_movement_delta_time ()); speed = get_3d_vector_magnitude (velocity); set_local_entity_float_value (en, FLOAT_TYPE_VELOCITY, speed); // // update attitude // heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); pitch = get_pitch_from_attitude_matrix (raw->vh.mob.attitude); pitch += (SHIP_SINK_DELTA_PITCH_RATE * get_entity_movement_delta_time()); roll = get_roll_from_attitude_matrix (raw->vh.mob.attitude); roll += (SHIP_SINK_DELTA_ROLL_RATE * get_entity_movement_delta_time()); get_3d_transformation_matrix (raw->vh.mob.attitude, heading, pitch, roll); // // set new position // set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_FIRE); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_EXPLOSION_TRAIL); // // remove ship if totally obscured (i.e. sunk) // if (get_comms_model () == COMMS_MODEL_SERVER) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d d; float obscured_altitude; bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (en, INT_TYPE_OBJECT_3D_SHAPE)); d.x = bounding_box->xmax - bounding_box->xmin; d.y = bounding_box->ymax - bounding_box->ymin; d.z = bounding_box->zmax - bounding_box->zmin; obscured_altitude = -(0.5 * get_3d_vector_magnitude (&d)); if (new_pos.y < obscured_altitude) { // // ship is no longer visible // destroy_client_server_entity_family (en); } } }
void handle_ground_stabilisation (void) { // loke 030322 // handle the ground stabilisation // improved stabilization thealx 130218 if (eo_ground_stabilised) { vec3d *velocity; matrix3x3 attitude; float accel, delta_pitch, delta_roll, heading, anglex, angley, correctionx; float horizontal_pan_offset, vertical_pan_offset; velocity = get_local_entity_vec3d_ptr (get_gunship_entity (), VEC3D_TYPE_MOTION_VECTOR); accel = velocity->y * get_entity_movement_delta_time(); get_local_entity_attitude_matrix (get_gunship_entity (), attitude); heading = atan2 (attitude [2][0], attitude [2][2]); delta_pitch = pitch - asin (attitude [2][1]); pitch = asin (attitude [2][1]); delta_roll = roll - atan2 (-attitude [0][1], attitude [1][1]); roll = atan2 (-attitude [0][1], attitude [1][1]); if (eo_azimuth > (PI / 2)) { anglex = PI - eo_azimuth; correctionx = - cos (anglex); } else if (eo_azimuth < (- PI / 2)) { anglex = - PI - eo_azimuth; correctionx = - cos (anglex); } else { anglex = eo_azimuth; correctionx = cos (anglex); } angley = eo_elevation; // GCsDriver start 180 deg. bug workaround // problem : // when crossing 180 deg stabilised view switches focus to 109 or 250 deg // crossing 0 / 360 deg is fine // solution : ? // sth like this should do but what`s the C equivalent ? // horizontal_pan_offset = mod((eo_ground_stabilisation_value_heading - heading), 2*pi); // workaround : // if we cross border we have to invert the rad // this gives just a little "glitch" when crossing 180 AND 0/360 deg // glitch width depends on turn rate (and distance centered point to 180/0 line) if ((eo_ground_stabilisation_value_heading > 0)&&(heading < 0)) { eo_ground_stabilisation_value_heading *= -1; anglex *= -1; } else if ((eo_ground_stabilisation_value_heading < 0)&&(heading > 0)) { eo_ground_stabilisation_value_heading *= -1; anglex *= -1; } // GCsDriver end 180 deg. bug workaround horizontal_pan_offset = (eo_ground_stabilisation_value_heading - heading) * cos(angley) + delta_roll * sin(angley) * correctionx + sin(anglex) * sin(delta_pitch) * eo_elevation; vertical_pan_offset = (eo_ground_stabilisation_value_pitch - pitch) * correctionx - delta_roll * sin(anglex) - 0.00028 * accel; eo_azimuth += horizontal_pan_offset; if (eo_azimuth > 0) { eo_azimuth = min (eo_azimuth, eo_max_azimuth); } else { eo_azimuth = max (eo_azimuth, eo_min_azimuth); } eo_elevation += vertical_pan_offset; if (vertical_pan_offset > 0) { eo_elevation = min (eo_elevation, eo_max_elevation); } else { eo_elevation = max (eo_elevation, eo_min_elevation); } eo_ground_stabilisation_value_heading = heading; eo_ground_stabilisation_value_pitch = pitch; } }
void ship_vehicle_movement (entity *en) { ship_vehicle *raw; entity *guide, *current_waypoint; vec3d wp_pos, wp_vec, new_pos; float roll, pitch, heading, sqr_range, turn_rate, required_heading, delta_heading, current_velocity, new_velocity; raw = get_local_entity_data (en); // // abort if mobile is not moving (i.e. landed, or dead) // if (!get_local_entity_int_value (en, INT_TYPE_MOBILE_MOVING)) { return; } // // abort if the mobile has no PRIMARY guide (also stops ships from moving if just engaging) // guide = get_local_entity_primary_guide (en); if (!guide) { return; } current_waypoint = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (current_waypoint); current_velocity = raw->vh.mob.velocity; // // GET WAYPOINT POSITION // ship_movement_get_waypoint_position (en, &wp_pos); wp_vec.x = wp_pos.x - raw->vh.mob.position.x; wp_vec.y = 0; wp_vec.z = wp_pos.z - raw->vh.mob.position.z; sqr_range = ((wp_vec.x * wp_vec.x) + (wp_vec.z * wp_vec.z)); #if DEBUG_MODULE create_vectored_debug_3d_object (&wp_pos, (vec3d *) &raw->vh.mob.attitude [1], OBJECT_3D_RED_ARROW, 0, 0.20); #endif // ???? if (fabs (sqr_range) < 1 * CENTIMETRE) { wp_vec.z = 0; wp_vec.y = 0; wp_vec.z = 1; } //////////////////////////////////////// // // angles // //////////////////////////////////////// // heading normalise_3d_vector (&wp_vec); heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); required_heading = atan2 (wp_vec.x, wp_vec.z); { float angle, range, v; range = sqrt (sqr_range); v = sqrt (0.5 * range * vehicle_database [raw->vh.mob.sub_type].g_max); angle = ((raw->vh.mob.attitude [2][0] * wp_vec.x) + (raw->vh.mob.attitude [2][2] * wp_vec.z)); if (angle < 0.707) // 45 degs. { // wp behind ship #if DEBUG_MODULE debug_log ("SH_MOVE: ship cannot reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = bound (v, 0.0, get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY)); } else { #if DEBUG_MODULE debug_log ("SH_MOVE: ship can reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY); } } turn_rate = 0.0; if (raw->vh.mob.velocity != 0.0) { turn_rate = fabs (vehicle_database [raw->vh.mob.sub_type].g_max / raw->vh.mob.velocity); } delta_heading = required_heading - heading; if (delta_heading <= -PI) { delta_heading += PI2; } if (delta_heading >= PI) { delta_heading -= PI2; } delta_heading = bound (delta_heading, -turn_rate, turn_rate); heading += delta_heading * get_entity_movement_delta_time (); pitch = 0.0; roll = 0.0; //////////////////////////////////////// // // attitude // //////////////////////////////////////// get_3d_transformation_matrix (raw->vh.mob.attitude, heading, rad (pitch), rad (roll)); //////////////////////////////////////// // // velocity // //////////////////////////////////////// { float maximum_acceleration, required_acceleration; required_acceleration = (new_velocity - raw->vh.mob.velocity); maximum_acceleration = get_local_entity_float_value (en, FLOAT_TYPE_MAX_ACCELERATION); raw->vh.mob.velocity += min (required_acceleration, maximum_acceleration) * get_entity_movement_delta_time (); } //////////////////////////////////////// // // position // //////////////////////////////////////// new_pos.x = raw->vh.mob.position.x + (raw->vh.mob.velocity * raw->vh.mob.zv.x * get_entity_movement_delta_time ()); new_pos.y = 0.0; new_pos.z = raw->vh.mob.position.z + (raw->vh.mob.velocity * raw->vh.mob.zv.z * get_entity_movement_delta_time ()); bound_position_to_map_volume (&new_pos); // // Calculate motion vector for view system // raw->vh.mob.motion_vector.x = (new_pos.x - raw->vh.mob.position.x) * get_one_over_delta_time (); raw->vh.mob.motion_vector.y = 0.0; raw->vh.mob.motion_vector.z = (new_pos.z - raw->vh.mob.position.z) * get_one_over_delta_time (); new_pos.y = 0.0; set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); }