static int load_local_pylon_entities (char *name) { entity *last_entity, *last_last_entity, *new_entity; entity_sub_types sub_type; int type, node_count, *node_link_count, path_count, node_loop, path_loop, start, end, link_count, link_loop; vec3d *node_positions, pos; FILE *pylon_node_file_ptr, *pylon_link_file_ptr; char filename [1024]; session_list_data_type *current_session; // // Create "Node" Pylons // ASSERT (get_valid_current_game_session ()); ASSERT (name); current_session = get_current_game_session (); sprintf (filename, "%s//route//%s.nde", current_session->data_path, name); if (file_exist (filename)) { pylon_node_file_ptr = safe_fopen (filename, "rb"); fread (&node_count, sizeof (int), 1, pylon_node_file_ptr); node_positions = malloc_heap_mem (sizeof (vec3d) * node_count); node_link_count = malloc_heap_mem (sizeof (int) * node_count); for (node_loop = 0 ; node_loop < node_count ; node_loop ++) { fread (&pos, sizeof (vec3d), 1, pylon_node_file_ptr); node_positions [node_loop].x = pos.x; node_positions [node_loop].y = pos.y; node_positions [node_loop].z = pos.z; node_link_count [node_loop] = 0; } fclose (pylon_node_file_ptr); // // Create "Link" Pylons // sprintf (filename, "%s//route//%s.wp", current_session->data_path, name); pylon_link_file_ptr = safe_fopen (filename, "rb"); fread (&path_count, sizeof (int), 1, pylon_link_file_ptr); new_entity = NULL; for (path_loop = 0 ; path_loop < path_count ; path_loop ++) { fread (&start, sizeof (int), 1, pylon_link_file_ptr); fread (&end, sizeof (int), 1, pylon_link_file_ptr); fread (&type, sizeof (int), 1, pylon_link_file_ptr); fread (&link_count, sizeof (int), 1, pylon_link_file_ptr); node_link_count [start] += 1; node_link_count [end] += 1; if (link_count > 0) { last_entity = NULL; last_last_entity = NULL; for (link_loop = 0 ; link_loop < link_count ; link_loop ++) { fread (&pos, sizeof (vec3d), 1, pylon_link_file_ptr); if (link_loop == 0) { sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_START_TERMINATOR; } else if (link_loop == link_count - 1) { sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_END_TERMINATOR; } else { sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_STANDARD; } new_entity = create_local_entity ( ENTITY_TYPE_PYLON, ENTITY_INDEX_DONT_CARE, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type), ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_HEADING, 0), ENTITY_ATTR_PTR_VALUE (PTR_TYPE_SUCC, last_entity), ENTITY_ATTR_END ); calculate_pylon_heading (last_last_entity, last_entity, new_entity, &node_positions [start], &node_positions [end]); last_last_entity = last_entity; last_entity = new_entity; } // last pylon in the link calculate_pylon_heading (last_last_entity, last_entity, NULL, &node_positions [start], &node_positions [end]); } } for (node_loop = 0 ; node_loop < node_count ; node_loop ++) { // // create node entities here // } fclose (pylon_link_file_ptr); free_mem (node_positions); free_mem (node_link_count); return TRUE; } return FALSE; }
entity *create_local_sound_effect_entity ( int index, entity *parent, entity_sides side, entity_sub_types sub_type, sound_channel_types channel, sound_locality_types locality, vec3d *position, float amp, int valid, int looping, int sample_count, sound_sample_indices *sample_indices ) { entity *en; vec3d pos; int panning, create_stack_attributes; ASSERT (parent); create_stack_attributes = force_local_entity_create_stack_attributes; if (get_comms_data_flow () == COMMS_DATA_FLOW_RX) { set_force_local_entity_create_stack_attributes (TRUE); } panning = TRUE; if (position) { pos = *position; } else { position = get_local_entity_vec3d_ptr (parent, VEC3D_TYPE_POSITION); if (position) { pos = *position; } else { pos.x = MID_MAP_X; pos.y = MID_MAP_Y; pos.z = MID_MAP_Z; panning = FALSE; } } // // special cases for speech // switch (sub_type) { case ENTITY_SUB_TYPE_EFFECT_SOUND_RADIO_MESSAGE: { if (get_global_gunship_side () == side) { amp = adjust_radio_message_amplification (amp, &pos); } else { amp = 0.0; } panning = FALSE; break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_CPG_MESSAGE: case ENTITY_SUB_TYPE_EFFECT_SOUND_WARNING_MESSAGE: { if (parent == get_gunship_entity ()) { amp = 1.0; } else { amp = 0.0; } panning = FALSE; break; } } // // create sound // en = create_local_entity ( ENTITY_TYPE_SOUND_EFFECT, index, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type), ENTITY_ATTR_PARENT (LIST_TYPE_SPECIAL_EFFECT, parent), ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z), ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_CHANNEL, channel), ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_EFFECT_LOOPING, looping), ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_EFFECT_PANNING, panning), ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_LOCALITY, locality), ENTITY_ATTR_INT_VALUE (INT_TYPE_VALID_SOUND_EFFECT, valid), ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_AMPLIFICATION, amp), ENTITY_ATTR_END ); set_local_sound_effect_sample_indices (en, sample_count, sample_indices); #if DEBUG_MODULE debug_log ("SOUNDEFF : created effect %s (%d), parent %s (%d), next %d, looping %d, valid %d", application_sound_effects [sample_indices [0]].name, get_local_entity_index (en), get_local_entity_type_name (parent), get_local_entity_index (parent), looping, valid); #endif set_force_local_entity_create_stack_attributes (create_stack_attributes); return en; }
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; }