int create_downwash_effect(downwash_types type, vec3d *position, float main_rotor_radius, float main_rotor_rpm, float min_altitude) { int loop, count, num_components, comp, index_counter, *entity_index_list; downwash_component *this_downwash_component; ASSERT (type >= 0); ASSERT (type < NUM_DOWNWASH_TYPES); ASSERT (type != DOWNWASH_TYPE_NONE); // // create an array of entity index numbers and fill them all with ENTITY_INDEX_DONT_CARE // count = count_entities_in_downwash (type); ASSERT (count); entity_index_list = (int *) malloc_fast_mem (sizeof (int) * count); //Xhit replaced ENTITY_INDEX_DONT_CARE with ENTITY_INDEX_CREATE_LOCAL (030428) //This and the changes made to the entity heap and some smoke functions //clears the MP-bug caused by that local entities were not allowed to be created on a client for ( loop = 0 ; loop < count ; loop ++ ) { entity_index_list [loop] = ENTITY_INDEX_CREATE_LOCAL; } index_counter = 0; num_components = downwash_database[ type ].number_of_components; for ( comp = 0 ; comp < num_components ; comp ++ ) { this_downwash_component = &(downwash_database[ type ].component[ comp ]); index_counter += create_downwash_effect_component( this_downwash_component, type, position, &entity_index_list[ index_counter ], main_rotor_radius, main_rotor_rpm, min_altitude); } free_mem (entity_index_list); return 0; }
void parse_filename (char *text, int max_length) { char *kb, *pm, *parsed_text; int length; ASSERT (text); ASSERT (max_length > 0); parsed_text = malloc_fast_mem (strlen (text) + 1); pm = parsed_text; kb = text; length = 0; while ((*kb) && (length < max_length)) { if (valid_filename_symbol (*kb)) { *pm = *kb; pm ++; length ++; } kb ++; } // // terminate new string // *pm = '\0'; // // copy text back to original location // strcpy (text, parsed_text); }
int add_message_to_campaign_log (int index) { int hours, minutes, seconds; char *s; message_log_type *message; rgb_colour *col = NULL; message = get_message_log (index); ASSERT (message); if (message->type == MESSAGE_TEXT_PILOT_STRING) { get_digital_clock_int_values (message->time_of_day, &hours, &minutes, &seconds); s = (char *) malloc_fast_mem (strlen (message->string) + 20); sprintf (s, "[%02d:%02d] %s", hours, minutes, message->string); col = &(message->colour); ASSERT (col); add_to_pop_up_list (s, chat_message_list, NULL, index, -1, *col); free_mem (s); return TRUE; } else { return FALSE; } }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; sound_effect *raw; //////////////////////////////////////// // // 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 = (sound_effect *) malloc_fast_mem (sizeof (sound_effect)); 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 (sound_effect)); raw->effect_index = (sound_sample_indices*) SOUND_SAMPLE_INDEX_NONE; raw->amplification = 1.0; raw->pitch = 1.0; //Werewolf sound pitch mod raw->sound_channel = SOUND_CHANNEL_SOUND_EFFECT; // // effect // raw->eff.position.x = MID_MAP_X; raw->eff.position.y = MID_MAP_Y; raw->eff.position.z = MID_MAP_Z; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (entity_sub_type_effect_valid (raw->eff.sub_type)); ASSERT (raw->effect_index == (sound_sample_indices*) SOUND_SAMPLE_INDEX_NONE); // samples haven't been specified at this point ASSERT (raw->eff.special_effect_link.parent); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// /* if (!raw->looping) { float rate, size; rate = (float)(application_sound_effects [raw->effect_index].rate); size = (float)(application_sound_effects [raw->effect_index].size); if (rate <= 0.0) { debug_log ("SE_CREAT : Sound effect rate invalid ( index = %s, rate = %d )", application_sound_effects [raw->effect_index].name, rate); } raw->effect_lifetime = size / rate; } */ #if DEBUG_MODULE debug_log ("SE_CREAT : Created Sound effect %d (parent (%d), lifetime = %f (%d))", get_local_entity_safe_index (en), get_local_entity_safe_index (raw->eff.special_effect_link.parent), raw->effect_lifetime, raw->valid_sound_effect); #endif //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_SPECIAL_EFFECT, raw->eff.special_effect_link.parent, NULL); if (raw->valid_sound_effect) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity(), raw->eff.update_link.child_pred); } } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; guide *raw; //////////////////////////////////////// // // 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 = (guide *) malloc_fast_mem (sizeof (guide)); 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 (guide)); raw->sub_type = ENTITY_SUB_TYPE_GUIDE_NAVIGATION_DIRECT; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->guide_link.parent); ASSERT (raw->current_waypoint_link.parent); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_GUIDE, raw->guide_link.parent, NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_CURRENT_WAYPOINT, raw->current_waypoint_link.parent, NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; cargo *raw; //////////////////////////////////////// // // 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 = (cargo *) malloc_fast_mem (sizeof (cargo)); 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 (cargo)); // // mobile // raw->mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->mob.position.x = MID_MAP_X; raw->mob.position.y = MID_MAP_Y; raw->mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->mob.attitude); raw->mob.alive = TRUE; raw->mob.side = ENTITY_SIDE_UNINITIALISED; // // cargo // //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// if (raw->cargo_link.parent) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_CARGO, raw->cargo_link.parent, NULL); } insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->mob.position), NULL); //insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; waypoint *raw; vec3d v; //////////////////////////////////////// // // 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 (waypoint)); 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 (waypoint)); raw->position.x = MID_MAP_X; raw->position.z = MID_MAP_Z; raw->position.y = MID_MAP_Y; raw->sub_type = ENTITY_SUB_TYPE_WAYPOINT_NAVIGATION; raw->waypoint_formation = FORMATION_ROW_LEFT; raw->position_type = POSITION_TYPE_ABSOLUTE; raw->heading = 0.0; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->waypoint_link.parent); get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &v); ASSERT (point_inside_map_volume (&v)); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// if (raw->task_dependent_link.parent) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_TASK_DEPENDENT, raw->task_dependent_link.parent, NULL); } insert_local_entity_into_parents_child_list (en, LIST_TYPE_WAYPOINT, raw->waypoint_link.parent, raw->waypoint_link.child_pred); #if DEBUG_MODULE insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->position), NULL); #endif } return (en); }
void set_local_sound_effect_sample_indices (entity *en, int count, sound_sample_indices *indices) { sound_effect *raw; int loop; ASSERT (en); ASSERT (count > 0); ASSERT (indices); raw = get_local_entity_data (en); ASSERT (!raw->effect_index); // // copy sample indices // raw->sound_effect_sequence_count = count; raw->effect_index = malloc_fast_mem (sizeof (sound_sample_indices) * count); memcpy (raw->effect_index, indices, sizeof (sound_sample_indices) * count); // // determine playing time // raw->effect_lifetime = 0; if (!raw->looping) { float rate, size; for (loop = 0; loop < count; loop ++) { ASSERT (indices [loop] != SOUND_SAMPLE_INDEX_NONE); rate = (float)(application_sound_effects [indices [loop]].rate); size = (float)(application_sound_effects [indices [loop]].size); if (rate <= 0.0) { debug_log ("SOUNDEFF : Sound effect rate invalid ( index = %s, rate = %d )", application_sound_effects [indices [loop]].name, rate); } else { raw->effect_lifetime += (size / rate); } } ASSERT (raw->effect_lifetime < 40.0); raw->effect_lifetime = min (raw->effect_lifetime, 40.0); } }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; scenic *raw; //////////////////////////////////////// // // 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 (scenic)); 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 (scenic)); // // fixed // raw->fix.position.x = MID_MAP_X; raw->fix.position.y = MID_MAP_Y; raw->fix.position.z = MID_MAP_Z; raw->fix.sub_type = ENTITY_SUB_TYPE_FIXED_UNKNOWN; raw->fix.object_3d_shape = OBJECT_3D_INVALID_OBJECT_INDEX; raw->fix.alive = TRUE; raw->fix.side = ENTITY_SIDE_NEUTRAL; // // scenic // if (fixed_3d_object_database[raw->fix.object_3d_shape].valid_entry) { raw->damage_level = fixed_3d_object_database[raw->fix.object_3d_shape].initial_damage; } else { raw->damage_level = 500; } //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// if (raw->fix.object_3d_shape == OBJECT_3D_INVALID_OBJECT_INDEX) { raw->fix.object_3d_shape = fixed_database[raw->fix.sub_type].default_3d_shape; } //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->fix.position), NULL); } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; camera *raw; //////////////////////////////////////// // // 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); ASSERT (!get_camera_entity ()); if (en) { //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = (camera *) malloc_fast_mem (sizeof (camera)); 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 (camera)); raw->position.x = MID_MAP_X; raw->position.y = MID_MAP_Y; raw->position.z = MID_MAP_Z; raw->offset.x = 0; raw->offset.y = 0; raw->offset.z = 0; raw->offset_movement.x = 0; raw->offset_movement.y = 0; raw->offset_movement.z = 0; raw->turbulence_offset.x = 0.0; raw->turbulence_offset.y = 0.0; raw->turbulence_offset.z = 0.0; raw->turbulence_movement.x = 0.0; raw->turbulence_movement.y = 0.0; raw->turbulence_movement.z = 0.0; get_identity_matrix3x3 (raw->attitude); raw->camera_mode = CAMERA_MODE_CHASE; raw->chase_camera_lock_rotate = TRUE; reset_chase_camera_position (raw); reset_cinematic_camera_for_new_view_entity (raw); //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); set_camera_entity (en); } return (en); }
void unpack_vehicle_data (entity *en, vehicle *raw, pack_modes mode) { int package; ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { // // unpack mobile data // unpack_mobile_data (en, &raw->mob, mode); // // unpack vehicle data // raw->object_3d_shape = unpack_int_value (en, INT_TYPE_OBJECT_3D_SHAPE); raw->inst3d = construct_3d_object (raw->object_3d_shape); if (mode == PACK_MODE_SERVER_SESSION) { ///////////////////////////////////////////////////////////////// if (unpack_int_value (en, INT_TYPE_VALID)) { unpack_list_root (en, LIST_TYPE_TASK_DEPENDENT, &raw->task_dependent_root); } ///////////////////////////////////////////////////////////////// } ///////////////////////////////////////////////////////////////// if (unpack_int_value (en, INT_TYPE_VALID)) { unpack_list_root (en, LIST_TYPE_LAUNCHED_WEAPON, &raw->launched_weapon_root); } ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// if (unpack_int_value (en, INT_TYPE_VALID)) { unpack_list_root (en, LIST_TYPE_MOVEMENT_DEPENDENT, &raw->movement_dependent_root); } ///////////////////////////////////////////////////////////////// unpack_list_link (en, LIST_TYPE_FOLLOWER, &raw->follower_link); // gunship_target_link unpack_list_link (en, LIST_TYPE_MEMBER, &raw->member_link); ///////////////////////////////////////////////////////////////// if (unpack_int_value (en, INT_TYPE_VALID)) { unpack_list_link (en, LIST_TYPE_MOVEMENT_DEPENDENT, &raw->movement_dependent_link); } ///////////////////////////////////////////////////////////////// // view_link if (mode == PACK_MODE_SERVER_SESSION) { unpack_list_link (en, LIST_TYPE_TAKEOFF_QUEUE, &raw->takeoff_queue_link); } raw->operational_state = unpack_int_value (en, INT_TYPE_OPERATIONAL_STATE); raw->sleep = unpack_float_value (en, FLOAT_TYPE_SLEEP); if (mode == PACK_MODE_SERVER_SESSION) { raw->distance = unpack_float_value (en, FLOAT_TYPE_DISTANCE); // only needed by server? } ///////////////////////////////////////////////////////////////// if (raw->operational_state == OPERATIONAL_STATE_LANDED) { raw->loading_door_state = unpack_float_value (en, FLOAT_TYPE_LOADING_DOOR_STATE); } ///////////////////////////////////////////////////////////////// // radar_rotation_state if (mode == PACK_MODE_SERVER_SESSION) { raw->death_timer = unpack_float_value (en, FLOAT_TYPE_DEATH_TIMER); raw->target_fire_timer = unpack_float_value (en, FLOAT_TYPE_TARGET_FIRE_TIMER); raw->target_scan_timer = unpack_float_value (en, FLOAT_TYPE_TARGET_SCAN_TIMER); } // view_interest_level // weapon_burst_timer raw->weapon_system_ready_state = unpack_float_value (en, FLOAT_TYPE_WEAPON_SYSTEM_READY_STATE); if (mode == PACK_MODE_SERVER_SESSION) { raw->decoy_release_timer = unpack_float_value (en, FLOAT_TYPE_DECOY_RELEASE_TIMER); } //////////////////////////////////////// raw->weapon_config_type = (weapon_config_types) unpack_int_value (en, INT_TYPE_WEAPON_CONFIG_TYPE); raw->weapon_package_status_array = (weapon_package_status *) malloc_fast_mem (SIZE_WEAPON_PACKAGE_STATUS_ARRAY); memset (raw->weapon_package_status_array, 0, SIZE_WEAPON_PACKAGE_STATUS_ARRAY); for (package = 0; package < NUM_WEAPON_PACKAGES; package++) { if (weapon_config_database[raw->weapon_config_type][package].sub_type == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { break; } raw->weapon_package_status_array[package].number = unpack_int_value (en, INT_TYPE_WEAPON_PACKAGE_NUMBER); raw->weapon_package_status_array[package].damaged = unpack_int_value (en, INT_TYPE_WEAPON_PACKAGE_DAMAGED); if (weapon_config_database[raw->weapon_config_type][package].rotate) { raw->weapon_package_status_array[package].weapon_system_heading = unpack_float_value (en, FLOAT_TYPE_WEAPON_SYSTEM_HEADING); raw->weapon_package_status_array[package].weapon_system_pitch = unpack_float_value (en, FLOAT_TYPE_WEAPON_SYSTEM_PITCH); } // muzzle_flash_timer } reset_entity_weapon_config_animation (en); raw->selected_weapon = unpack_int_value (en, INT_TYPE_SELECTED_WEAPON); //////////////////////////////////////// // sound_effect_data raw->formation_position = unpack_int_value (en, INT_TYPE_FORMATION_POSITION); // selected_weapon_system_ready // weapon_and_target_vectors_valid // gunship_radar_los_clear // los_to_target raw->lights_on = unpack_int_value (en, INT_TYPE_LIGHTS_ON); // cpg_identified raw->group_member_number = unpack_int_value (en, INT_TYPE_GROUP_MEMBER_NUMBER); // id_number_significant_digits raw->damage_level = unpack_int_value (en, INT_TYPE_DAMAGE_LEVEL); // id_number raw->weapon_vector.x = 0.0; raw->weapon_vector.y = 0.0; raw->weapon_vector.z = 1.0; raw->weapon_to_target_vector.x = 0.0; raw->weapon_to_target_vector.y = 0.0; raw->weapon_to_target_vector.z = -1.0; // terrain_info break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { // // cannot update entity at this level as the update may not apply to all entity types below // break; } } }
void unpack_local_session_data (pack_modes mode) { session *raw; entity *en; int index; ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: //////////////////////////////////////// { en = get_session_entity (); ASSERT (en); raw = (session *) get_local_entity_data (en); raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); // special_effect_root // update_link raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->lightning_timer = unpack_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync raw->time_of_day_acceleration = unpack_float_value (en, FLOAT_TYPE_TIME_OF_DAY_ACCELERATION); raw->fog_of_war_maximum_value = unpack_float_value (en, FLOAT_TYPE_FOG_OF_WAR_MAXIMUM_VALUE); // // rain effect // raw->weather_radius = unpack_float_value (en, FLOAT_TYPE_WEATHER_RADIUS); raw->weather_mode_transitional_period = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_PERIOD); raw->weather_mode_transitional_status = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_STATUS); raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); raw->target_weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_TARGET_WEATHER_MODE); unpack_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &raw->weather_position); unpack_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &raw->weather_velocity); // // wind effect // raw->wind_effect_radius = unpack_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS); raw->wind_gusting_value = unpack_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE); raw->wind_minimum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MINIMUM_SPEED); raw->wind_maximum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MAXIMUM_SPEED); unpack_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &raw->wind_direction_vector); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &raw->wind_effect_position); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &raw->wind_effect_velocity); // raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_medal = unpack_int_value (en, INT_TYPE_CAMPAIGN_MEDAL); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); raw->auto_assign_gunship = unpack_int_value (en, INT_TYPE_AUTO_ASSIGN_GUNSHIP); raw->infinite_fuel = unpack_int_value (en, INT_TYPE_INFINITE_FUEL); raw->infinite_weapons = unpack_int_value (en, INT_TYPE_INFINITE_WEAPONS); raw->suppress_ai_fire = unpack_int_value (en, INT_TYPE_SUPPRESS_AI_FIRE); raw->invulnerable_from_collisions = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_COLLISIONS); raw->invulnerable_from_weapons = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_WEAPONS); raw->cheats_enabled = unpack_int_value (en, INT_TYPE_CHEATS_ENABLED); raw->skip_night_time = unpack_int_value (en, INT_TYPE_SKIP_NIGHT_TIME); raw->weather_increasing = unpack_int_value (en, INT_TYPE_WEATHER_INCREASING); raw->wind_increasing = unpack_int_value (en, INT_TYPE_WIND_INCREASING); raw->local_weather_model = unpack_int_value (en, INT_TYPE_LOCAL_WEATHER_MODEL); break; } //////////////////////////////////////// case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { // // create entity // ASSERT (!get_session_entity ()); index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, ENTITY_TYPE_SESSION); raw = (session *) malloc_fast_mem (sizeof (session)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (session)); // // unpack data (in exactly the same order as the data was packed) // raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); raw->session_complete = unpack_int_value (en, INT_TYPE_SESSION_COMPLETE); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); unpack_list_root (en, LIST_TYPE_SPECIAL_EFFECT, &raw->special_effect_root); // update_link raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->lightning_timer = unpack_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync raw->time_of_day_acceleration = unpack_float_value (en, FLOAT_TYPE_TIME_OF_DAY_ACCELERATION); raw->fog_of_war_maximum_value = unpack_float_value (en, FLOAT_TYPE_FOG_OF_WAR_MAXIMUM_VALUE); // // rain effect // raw->weather_radius = unpack_float_value (en, FLOAT_TYPE_WEATHER_RADIUS); raw->weather_mode_transitional_period = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_PERIOD); raw->weather_mode_transitional_status = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_STATUS); raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); raw->target_weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_TARGET_WEATHER_MODE); unpack_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &raw->weather_position); unpack_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &raw->weather_velocity); // // wind effect // raw->wind_effect_radius = unpack_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS); raw->wind_gusting_value = unpack_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE); raw->wind_minimum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MINIMUM_SPEED); raw->wind_maximum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MAXIMUM_SPEED); unpack_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &raw->wind_direction_vector); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &raw->wind_effect_position); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &raw->wind_effect_velocity); // raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_medal = unpack_int_value (en, INT_TYPE_CAMPAIGN_MEDAL); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); raw->auto_assign_gunship = unpack_int_value (en, INT_TYPE_AUTO_ASSIGN_GUNSHIP); raw->infinite_fuel = unpack_int_value (en, INT_TYPE_INFINITE_FUEL); raw->infinite_weapons = unpack_int_value (en, INT_TYPE_INFINITE_WEAPONS); raw->suppress_ai_fire = unpack_int_value (en, INT_TYPE_SUPPRESS_AI_FIRE); raw->invulnerable_from_collisions = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_COLLISIONS); raw->invulnerable_from_weapons = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_WEAPONS); raw->cheats_enabled = unpack_int_value (en, INT_TYPE_CHEATS_ENABLED); raw->skip_night_time = unpack_int_value (en, INT_TYPE_SKIP_NIGHT_TIME); raw->weather_increasing = unpack_int_value (en, INT_TYPE_WEATHER_INCREASING); raw->wind_increasing = unpack_int_value (en, INT_TYPE_WIND_INCREASING); raw->local_weather_model = unpack_int_value (en, INT_TYPE_LOCAL_WEATHER_MODEL); // // link into system // // // need to insert session into update list after camera entity // ASSERT (get_camera_entity ()); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), get_camera_entity ()); set_session_entity (en); set_display_campaign_timer_valid (FALSE); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { // // create entity // ASSERT (!get_session_entity ()); index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, ENTITY_TYPE_SESSION); raw = (session *) malloc_fast_mem (sizeof (session)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (session)); // // unpack data (in exactly the same order as the data was packed) // raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); // update_link // tour of duty time raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync // time_of_day_acceleration // weather radius // weather_mode_transitional_period // weather_mode_transitional_status raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); // target_weather_mode // weather position // weather velocity raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); // infinite_weapons // skip_night_time // weather increasing set_session_entity (en); break; } } }
void assign_keysite_tasks (entity *keysite, task_category_types category) { entity *task, *group, *force, **task_list; float *sort_order; int loop, task_type, task_count, assign_count, group_type, keysite_type, non_critical_task_count; static int idle_group_count [NUM_ENTITY_SUB_TYPE_GROUPS]; ASSERT (keysite); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); if (!task) { return; } keysite_type = get_local_entity_int_value (keysite, INT_TYPE_ENTITY_SUB_TYPE); force = get_local_entity_parent (keysite, LIST_TYPE_KEYSITE_FORCE); ASSERT (force); // // Count tasks at keysite // task_count = 0; task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); while (task) { if (get_local_entity_int_value (task, INT_TYPE_TASK_CATEGORY) == category) { task_count ++; } task = get_local_entity_child_succ (task, LIST_TYPE_UNASSIGNED_TASK); } if (task_count == 0) { return; } // // Count up number of idle groups across the map (air registry only) // memset (idle_group_count, 0, sizeof (int) * NUM_ENTITY_SUB_TYPE_GROUPS); group = get_local_entity_first_child (force, LIST_TYPE_AIR_REGISTRY); while (group) { if (get_local_entity_int_value (group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE) { group_type = get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE); idle_group_count [group_type] ++; } group = get_local_entity_child_succ (group, LIST_TYPE_AIR_REGISTRY); } // // Sort tasks // ASSERT (task_count > 0); task_list = ( entity * * ) malloc_fast_mem (sizeof (entity *) * task_count); sort_order = ( float * ) malloc_fast_mem (sizeof (float) * task_count); task_count = 0; task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); while (task) { if (get_local_entity_int_value (task, INT_TYPE_TASK_CATEGORY) == category) { task_list [task_count] = task; sort_order [task_count] = get_local_entity_float_value (task, FLOAT_TYPE_TASK_PRIORITY); if (get_local_entity_int_value (task, INT_TYPE_CRITICAL_TASK)) { sort_order [task_count] *= 2.0; } task_count ++; } task = get_local_entity_child_succ (task, LIST_TYPE_UNASSIGNED_TASK); } quicksort_entity_list (task_list, task_count, sort_order); // // Assign tasks // assign_count = max (keysite_database [keysite_type].assign_task_count, 1u); non_critical_task_count = keysite_database [keysite_type].reserve_task_count; for (loop = 0; loop < task_count; loop ++) { if (assign_count == 0) { break; } task = task_list [loop]; // // Check for player lock // if (get_local_entity_parent (task, LIST_TYPE_PILOT_LOCK)) { continue; } // // Reserve non-critical tasks for player // if (!get_local_entity_int_value (task, INT_TYPE_CRITICAL_TASK)) { if (get_local_entity_float_value (task, FLOAT_TYPE_EXPIRE_TIMER) > KEYSITE_TASK_ASSIGN_TIMER) { if (non_critical_task_count > 0) { non_critical_task_count --; continue; } } } task_type = get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE); group = get_suitable_registered_group (task, idle_group_count); if (group) { if (assign_primary_task_to_group (group, task)) { ai_log ("ASSIGN: (%d/%d) Assigned group %s (%d) to task %s (%d) from keysite %s (%s)", assign_count, keysite_database [keysite_type].assign_task_count, entity_sub_type_group_names [get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE)], get_local_entity_index (group), entity_sub_type_task_names [task_type], get_local_entity_index (task), get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), entity_side_short_names [get_local_entity_int_value (keysite, INT_TYPE_SIDE)]); // // Only Assign n tasks per keysite // assign_count --; } else { #if DEBUG_MODULE debug_log ("ASSIGN: not assigning group %s (%d) to task %s (%d) from keysite %s", entity_sub_type_group_names [get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE)], get_local_entity_index (group), entity_sub_type_task_names [task_type], get_local_entity_index (task), get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME)); #endif } } } free_mem (task_list); free_mem (sort_order); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; weapon *raw; int seed; viewpoint vp; //////////////////////////////////////// // // 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) { float dispersion; //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = (weapon *) malloc_fast_mem (sizeof (weapon)); 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 (weapon)); // // mobile // raw->mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->mob.position.x = MID_MAP_X; raw->mob.position.y = MID_MAP_Y; raw->mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->mob.attitude); raw->mob.alive = TRUE; // // weapon // raw->kill_code = WEAPON_KILL_CODE_OK; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (entity_sub_type_weapon_valid (raw->mob.sub_type)); ASSERT (raw->launched_weapon_link.parent); ASSERT (raw->burst_size > 0); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// if (weapon_database[raw->mob.sub_type].acquire_parent_forward_velocity) { raw->mob.velocity = get_local_entity_float_value (raw->launched_weapon_link.parent, FLOAT_TYPE_VELOCITY); } else { // // overwrite attribute // raw->mob.velocity = 0.0; } raw->mob.velocity += weapon_database[raw->mob.sub_type].muzzle_velocity; seed = get_client_server_entity_random_number_seed (en); raw->mob.velocity += weapon_database[raw->mob.sub_type].muzzle_velocity_max_error * frand1x (&seed); raw->weapon_lifetime = weapon_database[raw->mob.sub_type].burn_time; raw->decoy_timer = get_decoy_timer_start_value (weapon_database[raw->mob.sub_type].decoy_type); // // detach weapon from launcher (get position and attitude) // detach_local_entity_weapon (raw->launched_weapon_link.parent, raw->mob.sub_type, raw->burst_size, &vp); raw->mob.position = vp.position; // arneh - add dispersion as random rotation in heading and pitch up to max error angle dispersion = weapon_database[raw->mob.sub_type].max_range_error_ratio; if (dispersion > 0.0) { matrix3x3 m; float heading = dispersion * sfrand1norm(), pitch = dispersion * sfrand1norm(); get_3d_transformation_matrix(m, heading, pitch, 0.0); multiply_matrix3x3_matrix3x3(raw->mob.attitude, vp.attitude, m); } else memcpy (raw->mob.attitude, vp.attitude, sizeof (matrix3x3)); // // interest level // set_local_entity_float_value (raw->launched_weapon_link.parent, FLOAT_TYPE_VIEW_INTEREST_LEVEL, DEFAULT_VIEW_INTEREST_LEVEL); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_LAUNCHED_WEAPON, raw->launched_weapon_link.parent, NULL); if (raw->mob.target_link.parent) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_TARGET, raw->mob.target_link.parent, NULL); } insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); if (tacview_is_logging()) write_tacview_new_unit(en); // // check if the weapon camera is primed and this weapon has been launched by the external view entity // if (get_camera_entity ()) { if (get_local_entity_int_value (get_camera_entity (), INT_TYPE_WEAPON_CAMERA_PRIMED)) { if (raw->launched_weapon_link.parent == get_external_view_entity ()) { if (get_local_entity_int_value (en, INT_TYPE_VIEWABLE_WEAPON)) { notify_local_entity (ENTITY_MESSAGE_SET_CAMERA_ACTION, get_camera_entity (), NULL, CAMERA_ACTION_WEAPON); set_local_entity_int_value (get_camera_entity (), INT_TYPE_WEAPON_CAMERA_PRIMED, FALSE); } } } } } return (en); }
void create_client_server_entity_weapon (entity *launcher, entity_sub_types weapon_sub_type, int weapon_index, int burst_size, int *smoke_trail_indices) { entity *force, *target, *weapon; meta_smoke_list_types smoke_trail_type; int i, num_smoke_trail_entities, valid_sound_effect, current_weapon_count, new_weapon_count; ASSERT (launcher); ASSERT (entity_sub_type_weapon_valid (weapon_sub_type)); // // get target // if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS))) { target = get_local_entity_parent (launcher, LIST_TYPE_TARGET); /* if (weapon_database[weapon_sub_type].hellfire_flight_profile) { if (get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH)) { target = NULL; } } */ } else { target = NULL; } if (get_comms_model () == COMMS_MODEL_SERVER) { //////////////////////////////////////// // // SERVER/TX and SERVER/RX // //////////////////////////////////////// ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE); ASSERT (burst_size == BURST_SIZE_DONT_CARE); ASSERT (!smoke_trail_indices); // NOTE: The clients' weapon counters lag the servers' so it is possible that the // client may unknowingly attempt to create more weapons than are available. // This is prone to happen during rapid firing. current_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type); if (current_weapon_count > 0) { int loal_mode = weapon_database[weapon_sub_type].hellfire_flight_profile && get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH); if (get_comms_data_flow () == COMMS_DATA_FLOW_RX) { set_force_local_entity_create_stack_attributes (TRUE); } // // get burst size wrt rate of fire // if (weapon_database[weapon_sub_type].rate_of_fire != FIRE_SINGLE_WEAPON) { float time_per_shot = weapon_database[weapon_sub_type].inverse_rate_of_fire * ONE_MINUTE; unsigned int* last_shot = NULL; switch (launcher->type) { case ENTITY_TYPE_HELICOPTER: last_shot = &((helicopter*)get_local_entity_data(launcher))->ac.weapon_salvo_timer; break; case ENTITY_TYPE_FIXED_WING: last_shot = &((fixed_wing*)get_local_entity_data(launcher))->ac.weapon_salvo_timer; break; case ENTITY_TYPE_ANTI_AIRCRAFT: last_shot = &((anti_aircraft*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_PERSON: last_shot = &((person*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_ROUTED_VEHICLE: last_shot = &((routed_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_SHIP_VEHICLE: last_shot = &((ship_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; } if (last_shot) { unsigned int current_time = get_system_time(); float elapsed_time = 1; if (*last_shot > 0) { if (current_time < *last_shot) return; elapsed_time = (current_time - *last_shot) * 0.001; } else elapsed_time = get_delta_time(); burst_size = (int)(weapon_database[weapon_sub_type].rate_of_fire * ONE_OVER_ONE_MINUTE * elapsed_time); if (burst_size < 1) { if (*last_shot == 0) // first shot in salvo always get fired burst_size = 1; else return; } if (*last_shot) *last_shot += (int)(burst_size * time_per_shot * 1000.0); else *last_shot = current_time; } else { ASSERT(FALSE); burst_size = 1; } } else { burst_size = 1; } // // set burst timer // valid_sound_effect = FALSE; if (get_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER) == 0.0) { set_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER, weapon_database[weapon_sub_type].burst_duration); valid_sound_effect = TRUE; } // // create weapon // weapon = create_local_entity ( ENTITY_TYPE_WEAPON, ENTITY_INDEX_DONT_CARE, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_MISSILE_PHASE, MISSILE_PHASE1), ENTITY_ATTR_INT_VALUE (INT_TYPE_LOCK_ON_AFTER_LAUNCH, loal_mode), ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher), ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target), ENTITY_ATTR_END ); if (weapon) { // // send FIRE message to force (unless it's a decoy/cargo/debris being launched) // if ((target) && (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS)))) { force = get_local_force_entity ((entity_sides) get_local_entity_int_value (target, INT_TYPE_SIDE)); if (force) { notify_local_entity (ENTITY_MESSAGE_ENTITY_FIRED_AT, force, launcher, target); } } // // create sound effect(s) // if (valid_sound_effect) { create_weapon_launched_sound_effects (launcher, weapon_sub_type); } // // create smoke trail // smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE); if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d exhaust_offset; num_smoke_trail_entities = count_entities_in_meta_smoke_list (smoke_trail_type); ASSERT (num_smoke_trail_entities > 0); smoke_trail_indices = (int *) malloc_fast_mem (sizeof (int) * num_smoke_trail_entities); for (i = 0; i < num_smoke_trail_entities; i++) { smoke_trail_indices[i] = ENTITY_INDEX_DONT_CARE; } bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE)); if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT)) { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = 0.0; } else { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = bounding_box->zmin; } create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices); } transmit_entity_comms_message ( ENTITY_COMMS_CREATE_WEAPON, NULL, launcher, weapon_sub_type, get_local_entity_safe_index (weapon), burst_size, smoke_trail_indices ); if (smoke_trail_indices) { free_mem (smoke_trail_indices); } // // out of weapons (if infinite weapons then reload else select next weapon) // new_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type); if (new_weapon_count <= 0) { #if !DEMO_VERSION if (get_local_entity_int_value (get_session_entity (), INT_TYPE_INFINITE_WEAPONS)) { weapon_config_types config_type; config_type = (weapon_config_types) get_local_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE); set_client_server_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE, config_type); } else #endif { // // play weapon out of ammo speech // play_entity_weapon_out_speech (launcher, weapon_sub_type); // // select next weapon // /* if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS))) { entity_sub_types next_weapon_sub_type; if (get_local_entity_int_value (launcher, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { next_weapon_sub_type = get_next_available_weapon_sub_type (launcher); } else { next_weapon_sub_type = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; } set_client_server_entity_int_value (launcher, INT_TYPE_SELECTED_WEAPON, next_weapon_sub_type); } */ } } else { int report_ammo_low_count; report_ammo_low_count = weapon_database[weapon_sub_type].report_ammo_low_count; if ((current_weapon_count > report_ammo_low_count) && (new_weapon_count <= report_ammo_low_count)) { // // play weapon low speech // play_entity_weapon_low_speech (launcher, weapon_sub_type); } else { // // weapon launch speech // play_entity_weapon_launched_speech (launcher, weapon_sub_type); } } } set_force_local_entity_create_stack_attributes (FALSE); } else { pause_client_server_continuous_weapon_sound_effect (launcher, weapon_sub_type); } } else { if (get_comms_data_flow () == COMMS_DATA_FLOW_TX) { //////////////////////////////////////// // // CLIENT/TX // //////////////////////////////////////// ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE); ASSERT (burst_size == BURST_SIZE_DONT_CARE); ASSERT (!smoke_trail_indices); // NOTE: The clients' weapon counters lag the servers' so it is possible that the // client may unknowingly attempt to create more weapons than are available. // This is prone to happen during rapid firing. if (get_local_entity_weapon_available (launcher, weapon_sub_type)) { transmit_entity_comms_message ( ENTITY_COMMS_CREATE_WEAPON, NULL, launcher, weapon_sub_type, ENTITY_INDEX_DONT_CARE, burst_size, NULL ); } } else { //////////////////////////////////////// // // CLIENT/RX // //////////////////////////////////////// ASSERT (weapon_index != ENTITY_INDEX_DONT_CARE); ASSERT (burst_size > 0); set_force_local_entity_create_stack_attributes (TRUE); weapon = create_local_entity ( ENTITY_TYPE_WEAPON, weapon_index, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size), ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher), ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target), ENTITY_ATTR_END ); ASSERT (weapon); // // create smoke trail // smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE); if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d exhaust_offset; ASSERT (smoke_trail_indices); bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE)); if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT)) { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = 0.0; } else { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = bounding_box->zmin; } create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices); } else { ASSERT (!smoke_trail_indices); } set_force_local_entity_create_stack_attributes (FALSE); } } }
void unpack_routed_vehicle_meta_smoke_lists (entity *en, pack_modes mode) { object_3d_instance *inst3d; int item, loop, count, point, *entity_index_list; meta_smoke_list_types type; object_3d_sub_object_index_numbers attachment_point; if (get_local_entity_int_value (en, INT_TYPE_ALIVE)) { inst3d = (object_3d_instance *) get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT); if (inst3d) { #if DEBUG_MODULE debug_log ("ROUTED : Unpacking smoke for %s ( %d )", vehicle_database [get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)].full_name, en); #endif item = 0; while (TRUE) { type = attached_meta_smoke_list_table [item].type; if (type == -1) { break; } else { for (point = 0; point < MAX_META_SMOKE_LIST_ATTACHMENT_POINTS; point ++) { attachment_point = attached_meta_smoke_list_table [item].attachment_point [point]; if (attachment_point == -1) { break; } else { count = count_sub_object_type_depth (inst3d, attachment_point); if (count >0) { count *= count_entities_in_meta_smoke_list (type); entity_index_list = (int *) malloc_fast_mem (sizeof (int) * count); for (loop = 0; loop < count; loop ++) { if (mode == PACK_MODE_SERVER_SESSION) { entity_index_list [loop] = ENTITY_INDEX_DONT_CARE; } else { entity_index_list [loop] = unpack_entity_safe_index (); } #if DEBUG_MODULE debug_log ("ROUTED : Index %d = %d", loop, entity_index_list [loop]); #endif } register_attach_meta_smoke_list_to_object (en, type, attachment_point, entity_index_list, count); free_mem (entity_index_list); } } } } item ++; } } } }
static void unpack_local_data (entity *en, entity_types type, pack_modes mode) { ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { int index; routed_vehicle *raw; node_link_data *route_data; // // create entity // index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, type); raw = (routed_vehicle *) malloc_fast_mem (sizeof (routed_vehicle)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (routed_vehicle)); // // unpack vehicle data (in exactly the same order as the data was packed) // unpack_vehicle_data (en, &raw->vh, mode); if (unpack_int_value (en, INT_TYPE_VALID)) { raw->vh.mob.velocity = 0.0; raw->desired_velocity = 0.0; } else { raw->vh.mob.velocity = unpack_float_value (en, FLOAT_TYPE_LOW_VELOCITY); raw->desired_velocity = unpack_float_value (en, FLOAT_TYPE_DESIRED_VELOCITY); } // // unpack routed data // if (unpack_int_value (en, INT_TYPE_VALID)) { raw->sub_waypoint_count = unpack_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT); raw->waypoint_next_index = unpack_int_value (en, INT_TYPE_WAYPOINT_NEXT_INDEX); raw->waypoint_this_index = unpack_int_value (en, INT_TYPE_WAYPOINT_THIS_INDEX); } // // turn lights on if necessary // set_vehicle_headlight_state (en, raw->vh.lights_on); // // setup waypoint route pointer // #if DEBUG_MODULE debug_log ("ROUTED ENTITY PACK: client setting up waypoint list pointer"); #endif route_data = get_road_sub_route (raw->waypoint_this_index, raw->waypoint_next_index, &index, NULL); if ((route_data) && (route_data->link_positions)) { raw->sub_route = route_data; } else { if ((raw->waypoint_this_index + raw->waypoint_next_index) != 0) { debug_log ("RV_PACK: WARNING NO SUB ROUTE FOUND BETWEEN %d AND %d", raw->waypoint_this_index, raw->waypoint_next_index); } } // // radar dish rotation (ok to use a random number as this is for visual effect only) // raw->vh.radar_rotation_state = frand1 (); set_routed_vehicle_id_number (en); set_initial_rotation_angle_of_routed_vehicle_wheels (raw->vh.inst3d); // // link into system // insert_local_entity_into_parents_child_list (en, LIST_TYPE_VIEW, get_camera_entity (), NULL); 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); add_to_force_info (get_local_force_entity ((entity_sides) raw->vh.mob.side), en); // // attached smoke lists must be unpacked after the entity is linked into the world // unpack_routed_vehicle_meta_smoke_lists (en, mode); unpack_mobile_local_sound_effects (en, mode); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { // // always use access functions to set the data // vec3d position; matrix3x3 attitude; int sub_waypoint_count; // // unpack all data (even if the echoed data is to be ignored) // unpack_vec3d (en, VEC3D_TYPE_POSITION, &position); unpack_attitude_matrix (en, attitude); sub_waypoint_count = unpack_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT); set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &position); set_local_entity_attitude_matrix (en, attitude); set_local_entity_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT, sub_waypoint_count); // Vehicle is moving so sleep must equal 0 set_local_entity_float_value (en, FLOAT_TYPE_SLEEP, 0.0); break; } } }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; sprite *raw; #if DEBUG_MODULE debug_log ("SPRITE: create"); #endif //////////////////////////////////////// // // 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 (sprite)); 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 (sprite)); // // effect // raw->eff.position.x = MID_MAP_X; raw->eff.position.y = MID_MAP_Y; raw->eff.position.z = MID_MAP_Z; // // sprite // raw->effect_lifetime = 0.0; raw->start_scale = 1.0; raw->end_scale = 1.0; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->animation_frequency >= 0.0); ASSERT (raw->sprite_lifetime > 0.0); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// if (raw->eff.special_effect_link.parent) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_SPECIAL_EFFECT, raw->eff.special_effect_link.parent, NULL); } insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->eff.position), NULL); } return (en); }
void unpack_local_force_data (entity *en, pack_modes mode) { int count, loop; force *raw; campaign_criteria_type *last_campaign_criteria, *campaign_criteria; ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); ASSERT (en); raw = (force *) get_local_entity_data (en); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: //////////////////////////////////////// { unpack_string (en, STRING_TYPE_FORCE_NAME, raw->force_name); // keysite_force // pilot root unpack_list_root (en, LIST_TYPE_DIVISION, &raw->division_root); unpack_list_root (en, LIST_TYPE_CAMPAIGN_OBJECTIVE, &raw->campaign_objective_root); // air_registry_root // ground_registry_root // sea_registry_root // unpack_list_root (en, LIST_TYPE_INDEPENDENT_GROUP, &raw->independent_group_root); // force_link // update link // task generation ////////////////////////////////////////////// for (loop = 0; loop < NUM_ENTITY_SUB_TYPE_TASKS; loop ++) { raw->task_generation [loop].valid = unpack_int_value (en, INT_TYPE_VALID); raw->task_generation [loop].created = unpack_int_value (en, INT_TYPE_TASK_GENERATION); } ///////////////////////////////////////////////////////////////// // campaign criteria //////////////////////////////////////////// count = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_COUNT); last_campaign_criteria = NULL; while (count) { campaign_criteria = (campaign_criteria_type *) malloc_heap_mem (sizeof (campaign_criteria_type)); memset (campaign_criteria, 0, sizeof (campaign_criteria_type)); campaign_criteria->criteria_type = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_TYPE); campaign_criteria->valid = unpack_int_value (en, INT_TYPE_VALID); campaign_criteria->result = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_RESULT); campaign_criteria->value1 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value2 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value3 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value4 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->next = last_campaign_criteria; raw->campaign_criteria = campaign_criteria; last_campaign_criteria = campaign_criteria; count --; } ///////////////////////////////////////////////////////////////// // force_info_criteria for (loop = 0; loop < NUM_FORCE_INFO_CATAGORIES; loop ++) { raw->force_info_current_hardware [loop] = unpack_int_value (en, INT_TYPE_VALUE); raw->force_info_reserve_hardware [loop] = unpack_int_value (en, INT_TYPE_VALUE); } ///////////////////////////////////////////////////////////////// for (loop = 0; loop < NUM_ENTITY_SUB_TYPE_GROUPS; loop ++) { raw->kills [loop] = unpack_int_value (en, INT_TYPE_VALUE); raw->losses [loop] = unpack_int_value (en, INT_TYPE_VALUE); // raw->group_count [loop] = unpack_int_value (en, INT_TYPE_VALUE); } raw->sleep = unpack_float_value (en, FLOAT_TYPE_SLEEP); raw->force_attitude = unpack_int_value (en, INT_TYPE_FORCE_ATTITUDE); // sector_count raw->colour = unpack_int_value (en, INT_TYPE_COLOUR); raw->side = unpack_int_value (en, INT_TYPE_SIDE); break; } //////////////////////////////////////// case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { // // create entity // debug_assert (get_free_entity (get_local_entity_safe_index (en))); set_local_entity_type (en, ENTITY_TYPE_FORCE); raw = (force *) malloc_fast_mem (sizeof (force)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (force)); // // unpack data (in exactly the same order as the data was packed) // unpack_string (en, STRING_TYPE_FORCE_NAME, raw->force_name); // keysite_force unpack_list_root (en, LIST_TYPE_PILOT, &raw->pilot_root); unpack_list_root (en, LIST_TYPE_DIVISION, &raw->division_root); unpack_list_root (en, LIST_TYPE_CAMPAIGN_OBJECTIVE, &raw->campaign_objective_root); // air_registry_root // ground_registry_root // sea_registry_root // unpack_list_root (en, LIST_TYPE_INDEPENDENT_GROUP, &raw->independent_group_root); unpack_list_link (en, LIST_TYPE_FORCE, &raw->force_link); // update_link //////////////////////////////////////////// // task_generation for (loop = 0; loop < NUM_ENTITY_SUB_TYPE_TASKS; loop ++) { raw->task_generation [loop].valid = unpack_int_value (en, INT_TYPE_VALID); raw->task_generation [loop].created = unpack_int_value (en, INT_TYPE_TASK_GENERATION); } //////////////////////////////////////////// //////////////////////////////////////////// // campaign criteria raw->campaign_criteria = NULL; count = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_COUNT); while (count) { count --; campaign_criteria = (campaign_criteria_type *) malloc_heap_mem (sizeof (campaign_criteria_type)); memset (campaign_criteria, 0, sizeof (campaign_criteria_type)); campaign_criteria->next = raw->campaign_criteria; raw->campaign_criteria = campaign_criteria; campaign_criteria->criteria_type = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_TYPE); campaign_criteria->valid = unpack_int_value (en, INT_TYPE_VALID); campaign_criteria->result = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_RESULT); campaign_criteria->value1 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value2 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value3 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); campaign_criteria->value4 = unpack_int_value (en, INT_TYPE_CAMPAIGN_CRITERIA_VALUE); } ///////////////////////////////////////////////////////////////// //////////////////////////////////////////// // force_info_criteria for (loop = 0; loop < NUM_FORCE_INFO_CATAGORIES; loop ++) { raw->force_info_current_hardware [loop] = unpack_int_value (en, INT_TYPE_VALUE); raw->force_info_reserve_hardware [loop] = unpack_int_value (en, INT_TYPE_VALUE); } // force_info_criteria for (loop = 0; loop < NUM_ENTITY_SUB_TYPE_GROUPS; loop ++) { raw->kills [loop] = unpack_int_value (en, INT_TYPE_VALUE); raw->losses [loop] = unpack_int_value (en, INT_TYPE_VALUE); // raw->group_count [loop] = unpack_int_value (en, INT_TYPE_VALUE); } raw->sleep = unpack_float_value (en, FLOAT_TYPE_SLEEP); raw->force_attitude = unpack_int_value (en, INT_TYPE_FORCE_ATTITUDE); raw->sector_count = unpack_int_value (en, INT_TYPE_FORCE_SECTOR_COUNT); raw->colour = unpack_int_value (en, INT_TYPE_COLOUR); raw->side = unpack_int_value (en, INT_TYPE_SIDE); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { // // create entity // debug_assert (get_free_entity (get_local_entity_safe_index (en))); set_local_entity_type (en, ENTITY_TYPE_FORCE); raw = (force *) malloc_fast_mem (sizeof (force)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (force)); // // unpack data (in exactly the same order as the data was packed) // unpack_string (en, STRING_TYPE_FORCE_NAME, raw->force_name); // keysite_force_root unpack_list_root (en, LIST_TYPE_PILOT, &raw->pilot_root); unpack_list_link (en, LIST_TYPE_FORCE, &raw->force_link); // update_link // task_generation // campaign_criteria // force_info_catagories // sleep raw->force_attitude = unpack_int_value (en, INT_TYPE_FORCE_ATTITUDE); raw->colour = unpack_int_value (en, INT_TYPE_COLOUR); raw->side = unpack_int_value (en, INT_TYPE_SIDE); break; } } }
unsigned int assign_engage_tasks_to_group (entity *group, unsigned int valid_members) { entity *task, *guide, *target, *member, *single_member, *persuer, **guide_list; unsigned int member_number; int best_count, best_guide, loop, criteria, task_count, *assigned_count; float range, *priority; vec3d *member_pos, *target_pos; ASSERT (group); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); if (!valid_members) { return valid_members; } // // count up engage tasks // task_count = 0; guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK); while (guide) { if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS) { task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); ASSERT (task); ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE); if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS) { task_count ++; } } guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK); } #if DEBUG_MODULE debug_log ("ENGAGE: =========================="); debug_log ("ENGAGE: %d suitable tasks", task_count); #endif if (task_count == 0) { return valid_members; } ////////////////////////////////////////////////////////////////// // // prioritize engage tasks // ////////////////////////////////////////////////////////////////// // // get target priority // guide_list = (entity * *) malloc_fast_mem (sizeof (entity *) * task_count); priority = (float *) malloc_fast_mem (sizeof (float) * task_count); assigned_count = (int *) malloc_fast_mem (sizeof (int) * task_count); #if DEBUG_MODULE debug_log ("ENGAGE: ======RAW LIST======"); #endif single_member = NULL; // check if we have a single member, if so assign that member to single_member for (member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); member; member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER)) { member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER)); if (member_number & valid_members) { if (single_member) // we already have a valid member, so there is more than one { single_member = NULL; break; } else single_member = member; } } loop = 0; guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK); while (guide) { if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS) { task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); ASSERT (task); ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE); if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS) { target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); ASSERT (target); if (!target) { notify_local_entity (ENTITY_MESSAGE_TASK_TERMINATED, task, group, TASK_TERMINATED_ABORTED); free_mem (guide_list); free_mem (priority); free_mem (assigned_count); return valid_members; } guide_list [loop] = guide; if (get_local_entity_int_value (group, INT_TYPE_AIRCRAFT_GROUP)) { priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_AIR_ATTACK); } else { priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_GROUND_ATTACK); } #if DEBUG_MODULE debug_log ("ENGAGE: (%d) Target : %s, Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), priority [loop]); #endif loop ++; } } guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK); } ASSERT (loop == task_count); // // sort the tasks according to their priority // quicksort_entity_list (guide_list, task_count, priority); #if DEBUG_MODULE debug_log ("ENGAGE: ======SORTED======"); for (loop = 0; loop < task_count; loop ++) { task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); debug_log ("ENGAGE: (%d) Target : %s (%d), Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target), priority [loop]); } #endif // // consider other entities attacking the same targets // memset (assigned_count, 0, sizeof (int) * task_count); for (loop = 0; loop < task_count; loop ++) { task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); persuer = get_local_entity_first_child (target, LIST_TYPE_TARGET); while (persuer) { assigned_count [loop] ++; persuer = get_local_entity_child_succ (persuer, LIST_TYPE_TARGET); } } ////////////////////////////////////////////////////////////////// // // assign new engage tasks // // for each member, run through the task list (most important first) // try to assign one member per task, but as tasks run out group members can "team-up" // ////////////////////////////////////////////////////////////////// member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); while ((member) && (valid_members)) { // // Only assign AI entities to ENGAGE tasks // if (get_local_entity_int_value (member, INT_TYPE_PLAYER) == ENTITY_PLAYER_AI) { if (get_local_entity_int_value (member, INT_TYPE_ENGAGE_ENEMY)) { member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER)); if (member_number & valid_members) { member_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION); if (get_local_entity_int_value (member, INT_TYPE_IDENTIFY_AIRCRAFT)) { criteria = BEST_WEAPON_CRITERIA_MINIMAL; } else { criteria = BEST_WEAPON_RANGE_CHECK | BEST_WEAPON_LOS_CHECK; } best_guide = -1; best_count = INT_MAX; for (loop = 0; loop < task_count; loop ++) { if (assigned_count [loop] < best_count) { guide = guide_list [loop]; task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); if (target == member) { // // Don't try to attack yourself ! // continue; } // // Range Check // if (criteria & BEST_WEAPON_RANGE_CHECK) { // range handled by weapon selection range = 0.0; } else { target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); range = get_sqr_2d_range (target_pos, member_pos); } if (range < MAX_ENGAGE_RANGE) { // // Weapon Check // if (get_best_weapon_for_target (member, target, criteria) != ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { best_count = assigned_count [loop]; best_guide = loop; } } } } if (best_guide != -1) { guide = guide_list [best_guide]; task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); if (assign_new_task_to_group_member (group, member, task, NULL)) { valid_members &= (~member_number); assigned_count [best_guide] ++; #if DEBUG_MODULE debug_log ("ENGAGE: Assigning %s (%d) to target %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target)); #endif } } else { #if DEBUG_MODULE debug_log ("ENGAGE: Couldn't assign %s (%d) to engage task", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member)); #endif } } } } member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } free_mem (guide_list); free_mem (priority); free_mem (assigned_count); return valid_members; }
int update_pilot_high_score_table (void) { int count, num_pilots; entity *force_en, *pilot_en; pilot_score_type *full_table; // // clear table // debug_log ("PILOT: Updating High Score Table"); initialise_pilot_high_score_table (); num_pilots = 0; // // count up player pilots // ASSERT (get_session_entity ()); force_en = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (force_en) { pilot_en = get_local_entity_first_child (force_en, LIST_TYPE_PILOT); while (pilot_en) { num_pilots ++; pilot_en = get_local_entity_child_succ (pilot_en, LIST_TYPE_PILOT); } force_en = get_local_entity_child_succ (force_en, LIST_TYPE_FORCE); } if (num_pilots == 0) { return 0; } // // create arrays of player pilots and their scores // full_table = (pilot_score_type *) malloc_fast_mem (sizeof (pilot_score_type) * num_pilots); count = 0; force_en = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (force_en) { pilot_en = get_local_entity_first_child (force_en, LIST_TYPE_PILOT); while (pilot_en) { full_table [count].kills = get_local_entity_int_value (pilot_en, INT_TYPE_KILLS); full_table [count].side = (entity_sides) get_local_entity_int_value (pilot_en, INT_TYPE_SIDE); full_table [count].valid = TRUE; strcpy (full_table [count].name, get_local_entity_string (pilot_en, STRING_TYPE_PILOTS_NAME)); debug_log ("PILOT: Adding %s (kills %d) to High Score Table", full_table [count].name, full_table [count].kills); count ++; pilot_en = get_local_entity_child_succ (pilot_en, LIST_TYPE_PILOT); } force_en = get_local_entity_child_succ (force_en, LIST_TYPE_FORCE); } ASSERT (count == num_pilots); // // quicksort the list // qs_table (full_table, 0, num_pilots - 1); // // add first n items to the high score table // count = min (num_pilots, NUM_TABLE_ENTRIES); memcpy (pilot_high_score_table, full_table, sizeof (pilot_score_type) * count); free_mem (full_table); return count; }
static entity *create_local (entity_types type, int index, char *pargs) { char name [STRING_TYPE_KEYSITE_NAME_MAX_LENGTH]; entity *group, *force, *sector, *en; keysite *raw; //////////////////////////////////////// // // 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 (keysite)); 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 (keysite)); sprintf (name, "KEYSITE %d", (int) en % 100); strncpy (raw->keysite_name, name, STRING_TYPE_KEYSITE_NAME_MAX_LENGTH); // // fixed // raw->position.x = MID_MAP_X; raw->position.y = MID_MAP_Y; raw->position.z = MID_MAP_Z; raw->alive = TRUE; raw->keysite_usable_state = KEYSITE_STATE_USABLE; raw->in_use = FALSE; raw->object_index = OBJECT_3D_INVALID_OBJECT_INDEX; raw->side = ENTITY_SIDE_NEUTRAL; raw->supplies.ammo_supply_level = 0.0; raw->supplies.fuel_supply_level = 0.0; raw->assign_timer = frand1 () * KEYSITE_TASK_ASSIGN_TIMER; // SERVER ONLY - OK TO USE RANDOM raw->sleep = frand1 () * KEYSITE_UPDATE_SLEEP_TIMER; // SERVER ONLY - OK TO USE RANDOM //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->side != ENTITY_SIDE_NEUTRAL); ASSERT (entity_sub_type_keysite_valid (raw->sub_type)); ASSERT (keysite_database [raw->sub_type].minimum_efficiency < 1.0); // the following is currently required for the campaign to progress properly... ASSERT (keysite_database [raw->sub_type].repairable == keysite_database [raw->sub_type].troop_insertion_target); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// update_keysite_cargo (en, raw->supplies.ammo_supply_level, ENTITY_SUB_TYPE_CARGO_AMMO, CARGO_AMMO_SIZE); update_keysite_cargo (en, raw->supplies.fuel_supply_level, ENTITY_SUB_TYPE_CARGO_FUEL, CARGO_FUEL_SIZE); //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// force = get_local_entity_parent (en, LIST_TYPE_KEYSITE_FORCE); debug_assert (get_local_entity_type (force) == ENTITY_TYPE_FORCE); ASSERT (force); sector = get_local_sector_entity (&raw->position); ASSERT (sector); insert_local_entity_into_parents_child_list (en, LIST_TYPE_KEYSITE_FORCE, force, NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, sector, NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); set_local_entity_int_value (sector, INT_TYPE_KEYSITE_COUNT, get_local_entity_int_value (sector, INT_TYPE_KEYSITE_COUNT) + 1); if (raw->in_use) { update_imap_sector_side (en, TRUE); update_imap_importance_level (en, TRUE); update_keysite_distance_to_friendly_base (en, raw->side); } //////////////////////////////////////// // // CREATE SUB ENTITIES // //////////////////////////////////////// // for site buildings group = create_local_entity ( ENTITY_TYPE_GROUP, ENTITY_INDEX_DONT_CARE, ENTITY_ATTR_PARENT (LIST_TYPE_BUILDING_GROUP, en), ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, raw->position.x, raw->position.y, raw->position.z), ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, ENTITY_SUB_TYPE_GROUP_BUILDINGS), ENTITY_ATTR_END ); #if DEBUG_MODULE { int sx, sz; get_x_sector (sx, raw->position.x); get_z_sector (sz, raw->position.z); debug_log ("KS_CREAT: Side %s creating keysite %s (type %d) index %d at %f, %f (%d, %d)", entity_side_short_names [raw->side], raw->keysite_name, raw->sub_type, get_local_entity_index (en), raw->position.x, raw->position.z, sx, sz); } #endif } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; bridge *raw; #if DEBUG_MODULE debug_log ("BRIDGE: create %d", index); #endif //////////////////////////////////////// // // 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 (bridge)); 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 (bridge)); raw->alive = TRUE; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (entity_sub_type_bridge_valid (raw->sub_type)); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// } return (en); }
static void unpack_local_data (entity *en, entity_types type, pack_modes mode) { ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { int loop, index; sound_effect *raw; // // create entity // index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, type); raw = malloc_heap_mem (sizeof (sound_effect)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (sound_effect)); // // unpack effect data (in exactly the same order as the data was packed) // unpack_effect_data( en, &raw->eff, mode ); // // unpack sound data // raw->sound_effect_sequence_count = unpack_int_value (en, INT_TYPE_SOUND_EFFECT_SEQUENCE_COUNT); ASSERT (raw->sound_effect_sequence_count > 0); raw->effect_index = malloc_fast_mem (sizeof (sound_sample_indices) * raw->sound_effect_sequence_count); for (loop = 0; loop < raw->sound_effect_sequence_count; loop ++) { raw->effect_index [loop] = unpack_int_value (en, INT_TYPE_SOUND_EFFECT_INDEX); } raw->amplification = unpack_float_value (en, FLOAT_TYPE_AMPLIFICATION); raw->effect_lifetime = unpack_float_value (en, FLOAT_TYPE_EFFECT_LIFETIME); raw->valid_effect_lifetime = unpack_float_value (en, FLOAT_TYPE_VALID_EFFECT_LIFETIME); //sound_effect_data raw->sound_channel = unpack_int_value (en, INT_TYPE_SOUND_CHANNEL); raw->sound_locality = unpack_int_value (en, INT_TYPE_SOUND_LOCALITY); raw->valid_sound_effect = unpack_int_value (en, INT_TYPE_VALID_SOUND_EFFECT); raw->looping = unpack_int_value (en, INT_TYPE_SOUND_EFFECT_LOOPING); raw->panning = unpack_int_value (en, INT_TYPE_SOUND_EFFECT_PANNING); // // link into system // // sound effect needs a parent //ASSERT (raw->eff.special_effect_link.parent); if (unpack_int_value (en, INT_TYPE_VALID)) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } #if DEBUG_MODULE debug_log ("SE_PACK: Unpacked %d - Sub-type %d", get_local_entity_safe_index (en), raw->eff.sub_type); #endif break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { // // always use access functions to set the data // break; } } }
static void unpack_local_data (entity *en, entity_types type, pack_modes mode) { ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { int index; pilot *raw; // // create entity // index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, type); raw = malloc_fast_mem (sizeof (pilot)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (pilot)); // // unpack data (in exactly the same order as the data was packed) // raw->sub_type = unpack_int_value (en, INT_TYPE_ENTITY_SUB_TYPE); unpack_string (en, STRING_TYPE_PILOTS_NAME, raw->pilots_name); raw->rank = unpack_int_value (en, INT_TYPE_PILOT_RANK); raw->kills = unpack_int_value (en, INT_TYPE_KILLS); raw->unique_id = unpack_int_value (en, INT_TYPE_UNIQUE_ID); raw->crew_role = CREW_ROLE_PILOT; unpack_list_root (en, LIST_TYPE_PILOT_LOCK, &raw->pilot_lock_root); unpack_list_link (en, LIST_TYPE_AIRCREW, &raw->aircrew_link); unpack_list_link (en, LIST_TYPE_PILOT, &raw->pilot_link); unpack_list_link (en, LIST_TYPE_PLAYER_TASK, &raw->player_task_link); raw->side = unpack_int_value (en, INT_TYPE_SIDE); raw->difficulty_level = unpack_int_value (en, INT_TYPE_DIFFICULTY_LEVEL); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { int index; pilot *raw; // // create entity // index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, type); raw = malloc_fast_mem (sizeof (pilot)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (pilot)); // // unpack data (in exactly the same order as the data was packed) // raw->sub_type = unpack_int_value (en, INT_TYPE_ENTITY_SUB_TYPE); unpack_string (en, STRING_TYPE_PILOTS_NAME, raw->pilots_name); raw->rank = unpack_int_value (en, INT_TYPE_PILOT_RANK); raw->kills = unpack_int_value (en, INT_TYPE_KILLS); raw->unique_id = unpack_int_value (en, INT_TYPE_UNIQUE_ID); raw->crew_role = CREW_ROLE_PILOT; // aircrew_link unpack_list_link (en, LIST_TYPE_PILOT, &raw->pilot_link); raw->side = unpack_int_value (en, INT_TYPE_SIDE); break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { // // always use access functions to set the data // break; } } }
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); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; fixed_wing *raw; entity_sub_types group_sub_type; //////////////////////////////////////// // // 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 (fixed_wing)); 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 (fixed_wing)); // // mobile // raw->ac.mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->ac.mob.position.x = MID_MAP_X; raw->ac.mob.position.y = MID_MAP_Y; raw->ac.mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->ac.mob.attitude); raw->ac.mob.alive = TRUE; raw->ac.mob.side = ENTITY_SIDE_UNINITIALISED; raw->ac.operational_state = OPERATIONAL_STATE_UNKNOWN; // // aircraft // raw->ac.object_3d_shape = OBJECT_3D_INVALID_OBJECT_INDEX; raw->ac.weapon_config_type = WEAPON_CONFIG_TYPE_UNINITIALISED; raw->ac.selected_weapon = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; raw->ac.weapon_vector.x = 0.0; raw->ac.weapon_vector.y = 0.0; raw->ac.weapon_vector.z = 1.0; raw->ac.weapon_to_target_vector.x = 0.0; raw->ac.weapon_to_target_vector.y = 0.0; raw->ac.weapon_to_target_vector.z = -1.0; raw->ac.loading_door_state = AIRCRAFT_LOADING_DOORS_OPEN_FLOAT_VALUE; raw->ac.undercarriage_state = AIRCRAFT_UNDERCARRIAGE_DOWN_FLOAT_VALUE; raw->ac.air_radar_contact_timeout = AIR_RADAR_CONTACT_TIMEOUT_INVALID; // // fixed_wing // //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->ac.member_link.parent); ASSERT (get_local_entity_type (raw->ac.member_link.parent) == ENTITY_TYPE_GROUP); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// // // side // if (raw->ac.mob.side == ENTITY_SIDE_UNINITIALISED) { raw->ac.mob.side = get_local_entity_int_value (raw->ac.member_link.parent, INT_TYPE_SIDE); } ASSERT (raw->ac.mob.side != ENTITY_SIDE_NEUTRAL); // // sub_type // if (raw->ac.mob.sub_type == ENTITY_SUB_TYPE_UNINITIALISED) { group_sub_type = get_local_entity_int_value (raw->ac.member_link.parent, INT_TYPE_ENTITY_SUB_TYPE); if (raw->ac.mob.side == ENTITY_SIDE_BLUE_FORCE) { raw->ac.mob.sub_type = group_database[group_sub_type].default_blue_force_sub_type; } else { raw->ac.mob.sub_type = group_database[group_sub_type].default_red_force_sub_type; } } ASSERT (entity_sub_type_aircraft_valid (raw->ac.mob.sub_type)); // // 3D shape // if (raw->ac.object_3d_shape == OBJECT_3D_INVALID_OBJECT_INDEX) { raw->ac.object_3d_shape = aircraft_database[raw->ac.mob.sub_type].default_3d_shape; } // // weapon config // if (raw->ac.weapon_config_type == WEAPON_CONFIG_TYPE_UNINITIALISED) { raw->ac.weapon_config_type = aircraft_database[raw->ac.mob.sub_type].default_weapon_config_type; } ASSERT (weapon_config_type_valid (raw->ac.weapon_config_type)); // // damage levels // raw->ac.damage_level = aircraft_database[raw->ac.mob.sub_type].initial_damage_level; //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// // // 3D object // raw->ac.inst3d = construct_3d_object (raw->ac.object_3d_shape); set_fixed_wing_id_number (en); initialise_fixed_wing_propellors (en); #if RECOGNITION_GUIDE raw->ac.loading_door_state = AIRCRAFT_LOADING_DOORS_CLOSED_FLOAT_VALUE; #endif // // weapon config // raw->ac.weapon_package_status_array = malloc_fast_mem (SIZE_WEAPON_PACKAGE_STATUS_ARRAY); memset (raw->ac.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->ac.mob.side), en); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_MEMBER, raw->ac.member_link.parent, raw->ac.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->ac.mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } return (en); }