diff --git a/animtrees/animated_props.atr b/animtrees/animated_props.atr new file mode 100644 index 0000000..ac61f6a --- /dev/null +++ b/animtrees/animated_props.atr @@ -0,0 +1,126 @@ +oil_pump +oil_pump_2 + +tree_desertpalm01_strongwind +tree_desertpalm01_still +tree_desertpalm02_strongwind +tree_desertpalm02_still +tree_desertpalm03_strongwind +tree_desertpalm03_still +palmtree_tall1_sway + +palmtree_tall1_still +palmtree_tall2_sway +palmtree_tall2_still +palmtree_tall3_sway +palmtree_tall3_still +palmtree_med1_sway +palmtree_med1_still +palmtree_med2_sway +palmtree_med2_still +palmtree_bushy1_sway +palmtree_bushy1_still +palmtree_bushy2_sway +palmtree_bushy2_still +palmtree_bushy3_sway +palmtree_bushy3_still +palmtree_mp_tall1_sway +palmtree_mp_tall2_sway +palmtree_mp_tall3_sway +palmtree_mp_med1_sway +palmtree_mp_med2_sway +palmtree_mp_bushy1_sway +palmtree_mp_bushy2_sway +palmtree_mp_bushy3_sway +ICBM_turbofan50_spin +ICBM_turbofan64_spin +ICBM_turbofan176_spin +launchfacility_b_emergencylight +me_statue_destroy_base_01 +oilrig_derrick_collapse +invasion_square_flag_medium_wind01 +invasion_square_flag_medium_wind02 +hanging_clothes_apron_wind_medium +hanging_clothes_long_sleeve_wind_medium +hanging_clothes_sheet_wind_medium +hanging_clothes_short_sleeve_wind_medium +foliage_pacific_fern01_sway +foliage_pacific_fern02_sway +foliage_pacific_palms08_sway +foliage_pacific_tropic_shrub01_sway +jeepride_shrubgroup_02_sway + +foliage_tree_oak_1_sway +foliage_dead_pine_med_sway +foliage_dead_pine_lg_sway +foliage_red_pine_sm_sway +foliage_red_pine_lg_sway +foliage_red_pine_xl_sway +foliage_red_pine_xxl_sway +foliage_cod5_tree_jungle_01_sway +foliage_cod5_tree_jungle_02_sway +foliage_cod5_tree_jungle_03_sway + +wallfan_streamers +windsock_wind_medium +highrise_fencetarp_01_wind +highrise_fencetarp_02_wind +highrise_fencetarp_03_wind +highrise_fencetarp_04_wind +highrise_fencetarp_05_wind +highrise_fencetarp_06_wind +highrise_fencetarp_07_wind +highrise_fencetarp_08_wind +highrise_fencetarp_09_wind +highrise_fencetarp_10_wind +afghan_camo_tarp_wind + +foliage_pacific_bushtree01_sway +foliage_tree_river_birch_med_a_sway +foliage_cod5_tree_pine05_large_sway +foliage_tree_river_birch_xl_a_sway +foliage_tree_birch_yellow_1_sway +foliage_desertbrush_1_sway +foliage_red_pine_med_sway + +roofvent_rotate +training_basketball_ball +gulag_rescueB_pistol_reshoot +airport_ending_climbin_makarov_weapon +laptop_chair_idle +laptop_chair_runin + +Wind_Turbine_Rotate +Wind_Turbine_Stop + +nx_pinetree_react0_Idle +nx_pinetree_react0_North +nx_pinetree_react0_East +nx_pinetree_react0_West +nx_pinetree_react0_South +nx_pinetree_react0_static + +nx_pr_color_tv_sign_sway + +nx_tarp_hanging_01 +nx_tarp_hanging_02 +nx_tarp_hanging_03 +nx_tarp_hanging_04 +nx_tarp_hanging_05 +nx_tarp_hanging_06 +nx_tarp_hanging_07 +nx_tarp_hanging_08 +nx_tarp_cementsack_pallet + +nx_pr_exfil_swinging_flag_slow_01 +nx_pr_exfil_swinging_flag_slow_02 +nx_pr_exfil_swinging_flag_slow_03 +nx_pr_exfil_swinging_flag_slow_04 +nx_pr_exfil_swinging_flag_slow_05 +nx_pr_exfil_swinging_flag_slow_06 + +nx_pr_exfil_swinging_flag_fast_01 +nx_pr_exfil_swinging_flag_fast_02 +nx_pr_exfil_swinging_flag_fast_03 +nx_pr_exfil_swinging_flag_fast_04 +nx_pr_exfil_swinging_flag_fast_06 \ No newline at end of file diff --git a/animtrees/destructibles.atr b/animtrees/destructibles.atr new file mode 100644 index 0000000..312f8dd --- /dev/null +++ b/animtrees/destructibles.atr @@ -0,0 +1,50 @@ +vehicle_80s_sedan1_flattire_LB +vehicle_80s_sedan1_flattire_LF +vehicle_80s_sedan1_flattire_RB +vehicle_80s_sedan1_flattire_RF +vehicle_80s_sedan1_destroy + +vehicle_mig29_destroy +vehicle_motorcycle_destroy_01 +vehicle_motorcycle_destroy_02 + +vehicle_snowmobile_destroy_01 + +light_fluorescent_swing +light_fluorescent_null +light_fluorescent_swing_02 + +light_fluorescent_single_null +light_fluorescent_single_swing +light_fluorescent_single_swing_02 +light_fluorescent_single_swing_03 + +gaspump01_hose + +locker_broken_both_doors_1 +locker_broken_both_doors_2 +locker_broken_both_doors_3 +locker_broken_both_doors_4 +locker_broken_door1_fast +locker_broken_door1_slow +locker_broken_door2_fast +locker_broken_door2_slow + +ex_airconditioner_fan + +me_fanceil1_spin +me_fanceil1_spin_stop + +wall_fan_rotate +wall_fan_wobble +wall_fan_stop + +chicken_cage_loop_01 +chicken_cage_loop_02 +chicken_cage_death +chicken_cage_death_02 + +generator_vibration +generator_explode +generator_explode_02 +generator_explode_03 \ No newline at end of file diff --git a/animtrees/multiplayer.atr b/animtrees/multiplayer.atr new file mode 100644 index 0000000..b9f9f67 --- /dev/null +++ b/animtrees/multiplayer.atr @@ -0,0 +1,989 @@ +// +// Player xanims refix convention: +// +// Torso only animation are prefixed with pt_ +// Legs only animations are prefixed with pl_ +// Full body animations (both) are prefixed with pb_ +// + +code +{ + main + { + // + // Torso Animations + // + torso + { + // Temp placeholder anims + pt_chicken_dance // Animation which indicates another animation is not completed yet + pt_chicken_dance_crouch // ditto for this one + + // + // Shooting anims + // + pt_moon_stand_shoot + pt_stand_shoot_ares + pt_stand_shoot_RPG + pt_stand_shoot + pt_stand_shoot_auto + pt_stand_shoot_ads + pt_stand_shoot_auto_ads + pt_stand_shoot_akimbo + pt_stand_shoot_mg + pt_stand_shoot_ads_mg + pt_crouch_shoot + pt_crouch_shoot_auto + pt_crouch_shoot_ads + pt_crouch_shoot_auto_ads + pt_crouch_shoot_akimbo + + pt_stand_shoot_pistol + pt_stand_shoot_ads_pistol + pt_crouch_shoot_pistol + pt_crouch_shoot_ads_pistol + + // Pistol needs aim/alert torso animations for use with regular lower body animations. + pt_stand_alert_pistol + pt_stand_ads_pistol + pt_crouch_alert_pistol + pt_crouch_ads_pistol + + pt_stand_grenade_throw + pt_stand_grenade_pullpin + pt_crouch_grenade_throw + pt_stand_stickgrenade_throw + pt_stand_throw_knife + pt_prone_throw_knife + +// crouch_grenade_throw + pt_prone_grenade_throw + pt_prone_grenade_pullpin + pt_rifle_fire_prone + pt_rifle_fire_ads + pt_rifle_fire + pt_crouch_rifle_fire_ads + pt_crouch_rifle_fire + pt_prone_shoot_RPG + pt_stand_shoot_shotgun + pt_hold_throw + pt_hold_prone_throw + pt_shield_knife_throw + pt_shield_grenade_throw + + // + // Reload anims + // + + pt_reload_stand_RPG + pt_reload_crouch_pistol + pt_reload_stand_pistol + pt_reload_prone_pistol + + pt_reload_crouch_rifle + pt_reload_stand_rifle + pt_reload_stand_mg + pt_reload_prone_rifle + pt_reload_stand_auto + pt_reload_stand_auto_mp40 + pt_reload_stand_auto_fg42 + pt_reload_stand_auto_sten + pt_reload_prone_auto + pt_reload_prone_RPG + pt_reload_prone_akimbo + pt_reload_crouchwalk + pt_reload_crouchwalk_pistol + pt_reload_stand_akimbo + pt_reload_crouch_akimbo + + + // + // Prone anims + // + + pt_prone_shoot + pt_prone_shoot_pistol + pt_prone_shoot_auto + pt_prone_shoot_akimbo + + // + // held object anims + // + + pt_hold_setup + + // + // Melee anims + // + + pt_melee_right2right_1 + pt_melee_right2right_2 + pt_melee_right2left + pt_melee_left2left_1 + pt_melee_left2right + + pt_melee_crouch_left2left + pt_melee_crouch_left2right + pt_melee_crouch_right2left + + pt_melee_pistol_1 + pt_melee_pistol_2 + pt_melee_pistol_3 + pt_melee_pistol_4 + + pt_melee_prone + pt_melee_prone_pistol + pt_melee_shield + + + // + // swap anims + // + + pt_stand_putaway_shield + pt_stand_pullout_shield + pt_stand_pullout_remotecontroller + pt_stand_core_pullout + + // + // pullout poses + // + + pt_crouch_pullout_pose + pt_stand_pullout_pose + pt_prone_pullout_pose + + // shellshock anims + pb_stand_shellshock + pb_crouch_shellshock + pt_shield_shellshock + pt_akimbo_shellshock + + // + // Flinch + // + + pt_flinch_forward // PI - RIFLE + pt_flinch_back + pt_flinch_left + pt_flinch_right + pt_flinch_pistol_left // PI - PISTOL + pt_flinch_pistol_forward + pt_flinch_pistol_back + pt_flinch_pistol_right + pt_flinch_grenade_right + pt_flinch_grenade_left + pt_flinch_grenade_forward + pt_flinch_grenade_back + + pt_laststand_pullout_pose + pt_laststand_reload_RPG + pt_laststand_fire + pt_laststand_fire_akimbo + pt_laststand_fire_RPG + pt_laststand_reload + pt_laststand_reload_akimbo + + //pain test + minorpain_chest_front + minorpain_chest_right + minorpain_chest_left + } + + // + // Legs Animations (also full body anims) + // + legs + { + // + // Idle anims + // + + pb_stand_alert_RPG + pb_stand_alert_mg + pb_stand_alert + pb_stand_alert_ares + pb_stand_ads + pb_stand_ads_mg + pb_stand_grenade_idle + pb_stand_grenade_pullpin + pb_stand_stickgrenade_idle + pb_stand_alert_pistol + pb_stand_ads_pistol + pb_stand_alert_unarmed + pb_stand__shoot_ads_pistol + pb_rifle_idleA_ads + pb_rifle_idleB_ads + pb_crouch_grenade_idle + pb_crouch_stickgrenade_idle + pb_crouch_grenade_pullpin + pb_prone_pullout_knife + + pb_crouch_alert + pb_crouch_ads + pb_crouch_alert_pistol + pb_crouch_ads_pistol + pb_crouch_alert_unarmed + pb_prone_hold + pb_stand_alert_akimbo + pb_crouch_alert_akimbo + pb_stand_alert_shield + pb_crouch_alert_shield + + + pb_chicken_dance // Animation which indicates another animation is not completed yet + pb_chicken_dance_crouch // ditto for this one + + pb_prone_bombplant + pb_stand_bombplant + pb_crouch_bombplant + pb_crouch_remotecontroller + pb_prone_remotecontroller + pb_stand_remotecontroller + pb_hold_idle + pb_crouch_hold_idle + pb_crouch_alert_RPG + pb_crouch_ads_RPG + pb_stand_ads_RPG + pb_prone_aim_RPG + pb_prone_aim_sniper + pb_stand_pullout_knife + pb_shield_grenade_pullpin + pb_shield_knife_pullout + + + // + // Movement anims + // + + pb_pistol_run_fast + pb_run_fast + pb_run_rifle + pb_run_smg + pb_run_heavy + pb_run_forward_m + pb_run_right_m + pb_run_left_m + pb_run_back_m + + pb_crouchwalk_loop + pb_sprint + pb_sprint_B + pb_sprint_gundown + pb_sprint_stickgrenade + pb_sprint_grenade + pb_sprint_RPG + pb_sprint_pistol + pb_sprint_hold + pb_sprint_akimbo + + pb_runjump_takeoff + pb_runjump_land + pb_standjump_takeoff + pb_standjump_land + pb_runjump_takeoff_pistol + pb_runjump_land_pistol + pb_standjump_takeoff_pistol + pb_standjump_land_pistol + + pb_combatrun_forward_loop + pb_combatrun_back_loop + pb_combatrun_left_loop + pb_combatrun_right_loop + pb_combatrun_forward_loop_pistol + pb_combatrun_back_loop_pistol + pb_combatrun_left_loop_pistol + pb_combatrun_right_loop_pistol + pb_combatrun_forward_loop_unarmed + pb_combatrun_forward_loop_heavy + pb_combatrun_forward_loop_light + pb_combatrun_forward_loop_rifles + pb_combatrun_forward_loop_stickgrenade + pb_combatrun_left_loop_grenade + pb_combatrun_right_loop_grenade + pb_combatrun_back_loop_grenade + + pb_combatrun_forward_RPG + pb_combatrun_back_RPG + pb_combatrun_left_RPG + pb_combatrun_right_RPG + pb_walk_forward_RPG_ads + pb_walk_back_RPG_ads + pb_walk_left_RPG_ads + pb_walk_right_RPG_ads + + pb_walk_forward_akimbo + pb_walk_back_akimbo + pb_walk_left_akimbo + pb_walk_right_akimbo + + pb_walk_forward_ares + pb_walk_back_ares + pb_walk_left_ares + pb_walk_right_ares + + pb_walk_forward_mg + pb_sprint_mg + pb_combatrun_forward_mg + pb_combatrun_right_mg + pb_combatrun_left_mg + pb_combatrun_back_mg + + pb_combatrun_forward_ares + pb_combatrun_back_ares + pb_combatrun_left_ares + pb_combatrun_right_ares + + pb_moon_run_forward + pb_moon_run_back + pb_moon_run_left + pb_moon_run_right + pb_moon_run_jump_takeoff + pb_moon_run_jump_land + pb_moon_stand_jump_land + pb_moon_stand_alert + pb_moon_sprint_forward + + pb_crouch_run_forward + pb_crouch_run_back + pb_crouch_run_left + pb_crouch_run_right + pb_crouch_run_forward_pistol + pb_crouch_run_forward_grenade + pb_crouch_run_forward_stickgrenade + pb_crouch_run_back_pistol + pb_crouch_run_left_pistol + pb_crouch_run_right_pistol + pb_crouch_walk_forward_pistol + pb_crouch_walk_back_pistol + pb_crouch_walk_left_pistol + pb_crouch_walk_right_pistol + pb_crouch_run_forward_unarmed + pb_crouch_run_back_grenade + pb_crouch_run_left_grenade + pb_crouch_run_right_grenade + + pb_crouch_shoot_run_forward + pb_crouch_shoot_run_back + pb_crouch_shoot_run_left + pb_crouch_shoot_run_right + pb_crouch_walk_forward_unarmed + + pb_crouch_grenade_throw + pb_stand_grenade_throw + pb_stand_stickgrenade_throw + + pb_stand_shoot_walk_forward + pb_stand_shoot_walk_back + pb_stand_shoot_walk_left + pb_stand_shoot_walk_right + pb_stand_shoot_walk_forward_unarmed // Not really shooting. Named the same as rifle anim so it'd sort alphabetically. + pb_combatwalk_forward_loop_pistol + pb_combatwalk_back_loop_pistol + pb_combatwalk_left_loop_pistol + pb_combatwalk_right_loop_pistol + pb_walk_right // these have the gun down like in the idle... + pb_walk_left + pb_walk_back + pb_walk_forward + + pb_pull_stand_intro + pb_pull_stand_loop + pb_pull_stand_end + pb_hold_run + pb_hold_run_back + pb_hold_run_right + pb_hold_run_left + pb_crouch_hold_run + pb_crouch_hold_run_back + pb_crouch_hold_run_left + pb_crouch_hold_run_right + + pb_crouch_walk_forward_shield + pb_crouch_walk_back_shield + pb_crouch_walk_left_shield + pb_crouch_walk_right_shield + + pb_crouch_run_back_RPG + pb_crouch_run_forward_RPG + pb_crouch_run_left_RPG + pb_crouch_run_right_RPG + + pb_crouch_walk_right_RPG + pb_crouch_walk_left_RPG + pb_crouch_walk_forward_RPG + pb_crouch_walk_back_RPG + + pb_prone_crawl_hold + pb_prone_crawl_back_hold + pb_prone_crawl_left_hold + pb_prone_crawl_right_hold + + pb_prone_crawl_akimbo + pb_prone_crawl_back_akimbo + pb_prone_crawl_left_akimbo + pb_prone_crawl_right_akimbo + + pb_combatrun_forward_akimbo + pb_combatrun_right_akimbo + pb_combatrun_left_akimbo + pb_combatrun_back_akimbo + + pb_crouch_walk_right_akimbo + pb_crouch_walk_left_akimbo + pb_crouch_walk_forward_akimbo + pb_crouch_walk_back_akimbo + + pb_walk_forward_shield + pb_walk_left_shield + pb_walk_right_shield + pb_walk_back_shield + pb_combatrun_forward_shield + pb_combatrun_left_shield + pb_combatrun_right_shield + pb_combatrun_back_shield + pb_sprint_shield + + +// pb_wounded_walk_loop // the temp ladder climbing anim + + // + // Ladder Climbing anims + // + + pb_climbdown + pb_climbup + + // + // Prone anims + // + + pb_prone_crawl + pb_prone_grenade_crawl + pb_prone_crawl_left + pb_prone_crawl_right + pb_prone_crawl_back + pb_prone_aim + pb_prone_aim_akimbo + pb_prone_aim_pistol + pb_prone_aim_grenade + pb_prone_grenade_crawl_left + pb_prone_grenade_crawl_right + pb_prone_crawl_pistol + pb_prone_crawl_pistol_back + pb_prone_pistol_crawl_left + pb_prone_pistol_crawl_right + pb_prone_grenade_crawl_back + pb_crouch2prone + pb_prone2crouch + pb_prone2crouchrun + pb_prone2crouch_shield + + // + // Last stand anims + // + + pb_laststand_death + pb_laststand_idle + pb_laststand_crawl + pb_laststand_crawl_back + pb_laststand_crawl_right + pb_laststand_crawl_left + pt_laststand_melee + pb_laststand_idle_RPG + pb_laststand_crawl_RPG + pb_laststand_crawl_right_RPG + pb_laststand_crawl_left_RPG + pb_laststand_crawl_back_RPG + pb_laststand_idle_akimbo + pb_laststand_crawl_akimbo + pb_laststand_crawl_right_akimbo + pb_laststand_crawl_left_akimbo + pb_laststand_crawl_back_akimbo + pb_laststand_crawl_back_shield + pb_laststand_crawl_shield + pb_laststand_idle_shield + pb_laststand_crawl_right_shield + pb_laststand_crawl_left_shield + pb_deadhands_idle + pb_deadhands_crawl_back + pb_deadhands_crawl_forward + pb_deadhands_crawl_left + pb_deadhands_crawl_right + + + + + // + // Mantle anims + // + + mp_mantle_up_57 + mp_mantle_up_51 + mp_mantle_up_45 + mp_mantle_up_39 + mp_mantle_up_33 + mp_mantle_up_27 + mp_mantle_up_21 + mp_mantle_over_high + mp_mantle_over_mid + mp_mantle_over_low + + mp_mantle_up_57_fr + mp_mantle_up_51_fr + mp_mantle_up_45_fr + mp_mantle_up_39_fr + mp_mantle_up_33_fr + mp_mantle_up_27_fr + mp_mantle_up_21_fr + mp_mantle_over_high_fr + mp_mantle_over_mid_fr + mp_mantle_over_low_fr + + // + // DTP_MOVE ANIMS + // + pb_dive_prone + pb_dive_prone_pistol + pb_dw_dive_prone + pb_hold_dive_prone + pb_rpg_dive_prone + + // + // DTP_LAND ANIMS + // + pb_dive_prone_land + pb_pistol_dive_prone_land + pb_dw_dive_prone_land + pb_hold_dive_prone_land + pb_rpg_dive_prone_land + + // + // MG42 anims + // + standSAWgunner_aim : complete nonloopsync + { + standSAWgunner_aim_15down + { + pb_saw_gunner_aim_down_right45 + pb_saw_gunner_aim_down_right30 + pb_saw_gunner_aim_down_right15 + pb_saw_gunner_aim_down_center + pb_saw_gunner_aim_down_left15 + pb_saw_gunner_aim_down_left30 + pb_saw_gunner_aim_down_left45 + } + + standSAWgunner_aim_level + { + pb_saw_gunner_aim_level_right45 + pb_saw_gunner_aim_level_right30 + pb_saw_gunner_aim_level_right15 + pb_saw_gunner_aim_level_center + pb_saw_gunner_aim_level_left15 + pb_saw_gunner_aim_level_left30 + pb_saw_gunner_aim_level_left45 + } + + standSAWgunner_aim_15up + { + pb_saw_gunner_aim_up_right45 + pb_saw_gunner_aim_up_right30 + pb_saw_gunner_aim_up_right15 + pb_saw_gunner_aim_up_center + pb_saw_gunner_aim_up_left15 + pb_saw_gunner_aim_up_left30 + pb_saw_gunner_aim_up_left45 + } + } + + proneSAWgunner_aim : complete nonloopsync + { + proneSAWgunner_aim_15down + { + pb_saw_gunner_prone_aim_down_left40 + pb_saw_gunner_prone_aim_down_left20 + pb_saw_gunner_prone_aim_down_center + pb_saw_gunner_prone_aim_down_right20 + pb_saw_gunner_prone_aim_down_right40 + } + + proneSAWgunner_aim_level + { + pb_saw_gunner_prone_aim_level_left40 + pb_saw_gunner_prone_aim_level_left20 + pb_saw_gunner_prone_aim_level_center + pb_saw_gunner_prone_aim_level_right20 + pb_saw_gunner_prone_aim_level_right40 + } + + proneSAWgunner_aim_15up + { + pb_saw_gunner_prone_aim_up_left40 + pb_saw_gunner_prone_aim_up_left20 + pb_saw_gunner_prone_aim_up_center + pb_saw_gunner_prone_aim_up_right20 + pb_saw_gunner_prone_aim_up_right40 + } + } + + crouchSAWgunner_aim : complete nonloopsync + { + crouchSAWgunner_aim_15down + { + pb_saw_gunner_lowwall_aim_down_left45 + pb_saw_gunner_lowwall_aim_down_left30 + pb_saw_gunner_lowwall_aim_down_left15 + pb_saw_gunner_lowwall_aim_down_center + pb_saw_gunner_lowwall_aim_down_right15 + pb_saw_gunner_lowwall_aim_down_right30 + pb_saw_gunner_lowwall_aim_down_right45 + } + + crouchSAWgunner_aim_level + { + pb_saw_gunner_lowwall_aim_level_left45 + pb_saw_gunner_lowwall_aim_level_left30 + pb_saw_gunner_lowwall_aim_level_left15 + pb_saw_gunner_lowwall_aim_level_center + pb_saw_gunner_lowwall_aim_level_right15 + pb_saw_gunner_lowwall_aim_level_right30 + pb_saw_gunner_lowwall_aim_level_right45 + } + + crouchSAWgunner_aim_15up + { + pb_saw_gunner_lowwall_aim_up_left45 + pb_saw_gunner_lowwall_aim_up_left30 + pb_saw_gunner_lowwall_aim_up_left15 + pb_saw_gunner_lowwall_aim_up_center + pb_saw_gunner_lowwall_aim_up_right15 + pb_saw_gunner_lowwall_aim_up_right30 + pb_saw_gunner_lowwall_aim_up_right45 + } + } + + proneMG42_fire : complete loopsync + { + proneMG42_fire_15down + { + pb_proneMG42gunner_fire_40left_15down + pb_proneMG42gunner_fire_20left_15down + pb_proneMG42gunner_fire_forward_15down + pb_proneMG42gunner_fire_20right_15down + pb_proneMG42gunner_fire_40right_15down + } + + proneMG42_fire_level + { + pb_proneMG42gunner_fire_40left_level + pb_proneMG42gunner_fire_20left_level + pb_proneMG42gunner_fire_forward_level + pb_proneMG42gunner_fire_20right_level + pb_proneMG42gunner_fire_40right_level + } + + proneMG42_fire_15up + { + pb_proneMG42gunner_fire_40left_15up + pb_proneMG42gunner_fire_20left_15up + pb_proneMG42gunner_fire_forward_15up + pb_proneMG42gunner_fire_20right_15up + pb_proneMG42gunner_fire_40right_15up + } + } + + proneMG42_aim : complete nonloopsync + { + proneMG42_aim_15down + { + pb_proneMG42gunner_aim_40left_15down + pb_proneMG42gunner_aim_20left_15down + pb_proneMG42gunner_aim_forward_15down + pb_proneMG42gunner_aim_20right_15down + pb_proneMG42gunner_aim_40right_15down + } + + proneMG42_aim_level + { + pb_proneMG42gunner_aim_40left_level + pb_proneMG42gunner_aim_20left_level + pb_proneMG42gunner_aim_forward_level + pb_proneMG42gunner_aim_20right_level + pb_proneMG42gunner_aim_40right_level + } + + proneMG42_aim_15up + { + pb_proneMG42gunner_aim_40left_15up + pb_proneMG42gunner_aim_20left_15up + pb_proneMG42gunner_aim_forward_15up + pb_proneMG42gunner_aim_20right_15up + pb_proneMG42gunner_aim_40right_15up + } + } + + + standMG42_fire : complete loopsync + { + standMG42_fire_15down + { + pb_standMG42gunner_fire_45left_15down + pb_standMG42gunner_fire_30left_15down + pb_standMG42gunner_fire_15left_15down + pb_standMG42gunner_fire_forward_15down + pb_standMG42gunner_fire_15right_15down + pb_standMG42gunner_fire_30right_15down + pb_standMG42gunner_fire_45right_15down + } + + standMG42_fire_level + { + pb_standMG42gunner_fire_45left_level + pb_standMG42gunner_fire_30left_level + pb_standMG42gunner_fire_15left_level + pb_standMG42gunner_fire_forward_level + pb_standMG42gunner_fire_15right_level + pb_standMG42gunner_fire_30right_level + pb_standMG42gunner_fire_45right_level + } + + standMG42_fire_15up + { + pb_standMG42gunner_fire_45left_15up + pb_standMG42gunner_fire_30left_15up + pb_standMG42gunner_fire_15left_15up + pb_standMG42gunner_fire_forward_15up + pb_standMG42gunner_fire_15right_15up + pb_standMG42gunner_fire_30right_15up + pb_standMG42gunner_fire_45right_15up + } + } + + standMG42_aim : complete nonloopsync + { + standMG42_aim_15down + { + pb_standMG42gunner_aim_45left_15down + pb_standMG42gunner_aim_30left_15down + pb_standMG42gunner_aim_15left_15down + pb_standMG42gunner_aim_forward_15down + pb_standMG42gunner_aim_15right_15down + pb_standMG42gunner_aim_30right_15down + pb_standMG42gunner_aim_45right_15down + } + + standMG42_aim_level + { + pb_standMG42gunner_aim_45left_level + pb_standMG42gunner_aim_30left_level + pb_standMG42gunner_aim_15left_level + pb_standMG42gunner_aim_forward_level + pb_standMG42gunner_aim_15right_level + pb_standMG42gunner_aim_30right_level + pb_standMG42gunner_aim_45right_level + } + + standMG42_aim_15up + { + pb_standMG42gunner_aim_45left_15up + pb_standMG42gunner_aim_30left_15up + pb_standMG42gunner_aim_15left_15up + pb_standMG42gunner_aim_forward_15up + pb_standMG42gunner_aim_15right_15up + pb_standMG42gunner_aim_30right_15up + pb_standMG42gunner_aim_45right_15up + } + } + + + // + // Death + // + + pb_explosion_death_B1 + pb_explosion_death_B2 + pb_explosion_death_B3 + pb_explosion_death_F1 + pb_explosion_death_L1 + pb_explosion_death_L2 + pb_explosion_death_R1 + + pb_explosion_rundeath_B1 + pb_explosion_rundeath_B2 + pb_explosion_rundeath_F1 + pb_explosion_rundeath_F2 + pb_explosion_rundeath_F3 + pb_explosion_rundeath_L1 + pb_explosion_rundeath_R1 + + pb_shotgun_death_back1 + pb_shotgun_death_back2 + pb_shotgun_death_legs + pb_shotgun_death_spinL + pb_shotgun_death_spinR + pb_shotgun_death_front + + pb_explosive_round_death_leg + pb_explosive_round_death_jaw + pb_explosive_round_death_chestB + pb_explosive_round_death_chestA + + + // prone + pb_prone_death_quickdeath + + // Crouch + pb_crouch_death_headshot_front + pb_crouch_death_clutchchest + pb_crouch_death_flip + pb_crouch_death_fetal + pb_crouch_death_falltohands + // Crouch run + pb_crouchrun_death_drop + pb_crouchrun_death_crumple + // stand + pb_stand_death_spin + pb_stand_death_legs + pb_stand_death_lowerback + pb_stand_death_lowertorso + pb_stand_death_head_collapse + pb_stand_death_neckdeath_thrash + pb_stand_death_neckdeath + pb_stand_death_nervedeath + pb_stand_death_frontspin // Hit from front in head, upper chest or right shoulder. + pb_stand_death_headchest_topple // Hit in head or chest from any direction. Falls back, one leg goes up. + pb_stand_death_chest_blowback + pb_stand_death_chest_spin + pb_stand_death_shoulder_stumble + pb_stand_death_head_straight_back + pb_stand_death_tumbleback + pb_stand_death_kickup + pb_stand_death_stumbleforward + pb_stand_death_leg + pb_stand_death_leg_kickup + pb_stand_death_headshot_slowfall + pb_stand_death_shoulderback + // run + pb_death_run_forward_crumple + pb_death_run_onfront + pb_death_run_stumble + pb_death_run_back + pb_death_run_left + pb_death_run_right + MP_shotgun_death_back + MP_shotgun_death_front + MP_shotgun_death_left + MP_shotgun_death_right + + + // + // Stumble + // + + pb_stumble_forward // RUNNING + pb_stumble_back + pb_stumble_left + pb_stumble_right + pb_stumble_walk_forward // WALKING + pb_stumble_walk_back + pb_stumble_walk_left + pb_stumble_walk_right + + pb_stumble_pistol_walk_right // WALKING w/pistol + pb_stumble_pistol_walk_left + pb_stumble_pistol_walk_forward + pb_stumble_pistol_walk_back + pb_stumble_pistol_right // RUNNING w/pistol + pb_stumble_pistol_left + pb_stumble_pistol_forward + pb_stumble_pistol_back + + pb_stumble_grenade_right + pb_stumble_grenade_left + pb_stumble_grenade_forward + pb_stumble_grenade_back + + + // + // dive + // + + pb_dive_right + pb_dive_right_impact + pb_dive_left + pb_dive_left_impact + pb_dive_back + pb_dive_back_impact + pb_dive_front + pb_dive_front_impact + + // + // Pain + // + + // prone + pb_prone_painA_holdchest + pb_prone_painB_holdhead + + // Crouch run +// crouchrun_painfall + + // Crouch +// crouch_pain_fallToGround // Shot from front, backs back and slightly right. + pb_crouch_pain_holdStomach // Shot in torso. +// crouch_pain_crouch2crawl_ktwist // extended pain. Ends in crawl (backwards). +// crouch_pain_crouch2crawl_grabhead // extended pain. Ends in crawl (backwards). +// crouch_pain_crouch2crawl_back // Shot from behind, falls forward to crawl. + + // Stand +// stand_pain_leghit // Shot in leg, falls to ground, writhes, up to crouch +// stand_pain_fallToHand // Shot in torso? falls to left hand, up to crouch +// stand_pain_hunch // Shot in stomach, turns left and then straight. Ends in crouch. +// stand_pain_stand2crawl_stumbleback // extended pain. Ends in crawl. + +// minorpain_head_front +// minorpain_head_back +// minorpain_head_left +// minorpain_head_right +// minorpain_chest_front +// minorpain_chest_back +// minorpain_chest_left +// minorpain_chest_right +// minorpain_leftarm_front +// minorpain_leftarm_back +// minorpain_leftarm_left +// minorpain_leftarm_right +// minorpain_rightarm_front +// minorpain_rightarm_back +// minorpain_rightarm_left +// minorpain_rightarm_right + } + } + + // + // Turning animations (played on the legs, but handled seperatly) + // + turning + { + pl_turn_90left + pl_turn_90right + pl_crouchturn_90right + pl_crouchturn_90left + + } +} + +breaching +{ + breach_player_v1 + breach_player_v2 + breach_player_v3 + breach_player_viewmodel_v2 + breach_player_viewmodel_v3 + breach_coop_player_1 + breach_coop_player_1_3rdPerson + breach_coop_player_2 + breach_coop_player_2_3rdPerson + nx_fp_lunar_endbreach_player +} \ No newline at end of file diff --git a/animtrees/vehicles.atr b/animtrees/vehicles.atr new file mode 100644 index 0000000..387309e --- /dev/null +++ b/animtrees/vehicles.atr @@ -0,0 +1,937 @@ +humvee_passenger_2_turret_minigun +humvee_turret_2_passenger_minigun + +humvee_mount_frontR_door +humvee_mount_frontL_door +humvee_mount_backL_door +humvee_mount_backR_door + + +humvee_dismount_backL_door +humvee_dismount_backR_door +humvee_dismount_frontL_door +humvee_dismount_frontR_door + +suburban_dismount_backL_door +suburban_dismount_backR_door +suburban_dismount_frontL_door +suburban_dismount_frontR_door + +DCemp_heli_crash_1 +DCemp_heli_crash_2 +DCemp_heli_crash_3 +DCemp_emp_heli_crash +DCemp_car_hit + +boneyard_jeep_evac +boneyard_UAZ_door +boneyard_UAZ_steer_straight +boneyard_UAZ_steer_left +boneyard_UAZ_steer_right + + +M60A1_tank_lower +M60A1_tank_raise +M60A1_bridge_lower +M60A1_bridge_raise +M60A1_tank_cross +roadkill_M60A1_bridge_lower +roadkill_M60A1_tank_lower +roadkill_M60A1_tank_driveup +roadkill_M60A1_bridge_driveup +roadkill_M60A1_tank_cross +roadkill_M60A1_arm_lower + +roadkill_hummer_door_soldier +roadkill_hummer_gun_getin + +nx_chinese_lgv_turret_mount +nx_chinese_lgv_turret_dismount + +nx_chinese_lgv_turret_reaction + +afchase_chopper_landing +AFchase_waterfall_zodiac_R +AFchase_waterfall_zodiac_L +AFchase_waterfall_zodiac_rocking +AFchase_waterfall_zodiac_fall +AFchase_waterfall_pavelow +AFchase_waterfall_pavelow_idle +AFchase_waterfall_player_zodiac + + + +roadkill_hummer_mount_frontR_door + +roadkill_pickup_technical_pushed + +stryker_movement +stryker_movement_backwards +stryker_cannon_fire +stryker_shell_hatch + + +bh_minigun_spin_loop +dcburning_BHrescue_BH_animatic +dcburning_BHrescue_BH + + +mi17_heli_idle +gulag_end_pavelow + +cliffhanger_icepick_fight_snowmobile +cliffhanger_truck_bm21 +cliffhanger_mig_landing_1 +cliffhanger_mig_landing_2 +mig_landing_gear_up + + +technical_driving_idle_forward +technical_driving_idle_backward + + +sniper_escape_crash_mi28_entrance +sniper_escape_crash_mi28_idle +sniper_escape_crash_mi28_crash +sniper_escape_crash_mi28_rotor_1 +sniper_escape_crash_mi28_rotor_2 +sniper_escape_crash_mi28_rotor_3 +sniper_escape_crash_mi28_rotor_4 +sniper_escape_crash_mi28_rotor_5 + +cliffhanger_crash_mi28_rotor_1 +cliffhanger_crash_mi28_rotor_2 +cliffhanger_crash_mi28_rotor_3 +cliffhanger_crash_mi28_rotor_4 +cliffhanger_crash_mi28_rotor_5 +cliffhanger_crash_mi28_crash + +mi17_heli_rotors + +blackhawk +{ + bh_cargo_path + bh_idle + bh_rotors +} + + +door_pickup_driver_climb_in +door_pickup_passenger_climb_in +door_pickup_driver_climb_out +door_pickup_passenger_climb_out +door_pickup_passenger_RL_climb_out +door_pickup_passenger_RR_climb_out +cobra_crash +cobra_crash_relative +abrams_movement +abrams_movement_backwards + +pickup_tankcrush_front +tank_tankcrush_front +sedan_tankcrush_side +tank_tankcrush_side + +cobra : additive +{ +} + +bmp +{ + bmp_doors_open + bmp_doors_close + bmp_movement + bmp_movement_backwards +} + + +BTR80 +{ + BTR80_doorsR_open + BTR80_doorsL_open + BTR80_exit_1 + BTR80_exit_2 + BTR80_exit_3 + BTR80_exit_4 + BTR80_movement + BTR80_movement_backwards +} + + +bog_b_tank_explosion +bog_b_tank_explosion2 + +cobra_copilot_idle +cobra_copilot_idle_l +cobra_copilot_idle_r + +coup_opening_car +coup_opening_car_driving +coup_ending_drag_cardoor + +vehicle_steeringwheel +{ + coup_driver_bigleft2center_car + coup_driver_bigleft_idle_car + coup_driver_bigleft_loop_car + coup_driver_bigleftloop2center_car + coup_driver_center2smallleft_car + coup_driver_center2smallright_car + coup_driver_idle_car + coup_driver_smallleft2center_car + coup_driver_smallleft2bigleft_car + coup_driver_smallleft_idle_car + coup_driver_smallright2center_car + coup_driver_smallright_idle_car + coup_driver_bigleftloop_idle_car +} + +vehicle_additives : additive +{ + coup_opening_car_driving_idle_bumpy + coup_opening_car_driving_idle_normal + coup_opening_car_driving_idle_smooth + coup_opening_car_driving_idle_static + +} + +ac130_carjack +{ + ac130_carjack_door_1a + ac130_carjack_door_1b + ac130_carjack_door_others +} + +ch46_anims +{ + sniper_escape_ch46_take_off + sniper_escape_ch46_land + sniper_escape_ch46_idle +} + +blackhawk_anims +{ + blackout_bh_evac_heli_idle + blackout_bh_evac_heli_land + blackout_bh_evac_heli_takeoff +} + +ch46_rotors +{ + sniper_escape_ch46_rotors +} + +ch46_turret +{ + ch46_turret_fire + ch46_turret_idle +} + +ch46_doors +{ + ch46_doors_open + ch46_doors_close +} + +cargoship_ch46_rescue_in +cargoship_ch46_rescue_idle +cargoship_ch46_rescue_out +cargoship_ch46_rescue_drift +cargoship_ch46_rescue_drift_idle + +armada_blackhawk_sniper_idle_loop_fastrope80 +armada_blackhawk_sniper_drop_fastrope80 +armada_blackhawk_sniper_idle_fastrope80 + +bm21 +{ + bm21_driving_idle_forward + bm21_driving_idle_backward + bm21_passenger_climbout_door + bm21_driver_climbout_door + bm21_guy_climbout_truckdoor +} + +zpu_gun_fire_a +zpu_gun_fire_b +zpu_gun_stop + +bus_driving_idle_forward +bus_driving_idle_backward +tanker_truck_driving_idle_forward +tanker_truck_driving_idle_backward +jeepride_crash_tunnel_pickup +jeepride_flip_pickup +jeepride_crash_pillar + + +uaz_drive +{ + uaz_driving_idle_forward + uaz_driving_idle_backward +} + +uaz +{ + ambush_VIP_escape_UAZ + uaz_driver_enter_from_huntedrun_door + uaz_driver_exit_into_run_door + uaz_passenger_enter_from_huntedrun_door + uaz_passenger_exit_into_run_door + uaz_rear_driver_exit_into_run_door + uaz_passenger2_exit_into_run_door + uaz_rear_driver_enter_from_huntedrun_door + uaz_passenger2_enter_from_huntedrun_door + uaz_driver_exit_into_stand_door + uaz_passenger_exit_into_stand_door + uaz_passenger2_exit_into_stand_door + uaz_rear_driver_exit_into_stand_door +} + +uaz_driver +{ + UAZ_steeringwheel_death + UAZ_steeringwheel_duck + UAZ_steeringwheel_idle + UAZ_steeringwheel_turnleft + UAZ_steeringwheel_turnright + UAZ_steeringwheel_weave +} + + + +mi28_path +{ + jeepride_mi28_flyby +} +mi28 +{ + mi28_rotors +} + +mi28_add : additive +{ + mi28_rotors_add +} + +president_crash +{ + pres_crash_suv_pres + pres_crash_suv_1 +} + +snowmobile +{ + snowmobile_vehicle_driving_idle + sm_turn + { + snowmobile_vehicle_lean_L_delta + snowmobile_vehicle_lean_R_delta + } +} + +motorcycle +{ + motorcycle_pose_lean_l_50 + motorcycle_pose_lean_r_50 + motorcycle_pose_straight + motorcycle_pose_turn_l + motorcycle_pose_turn_r + motorcycle_rider_pose_f + motorcycle_rider_pose_l + motorcycle_rider_pose_r +} + +snowmobile_player +{ + player_snowmobile_left_arm + { + player_snowmobile_drive_left_arm + { + player_snowmobile_drive_turn_left2right_L + player_snowmobile_drive_turn_right2left_L + } + + player_snowmobile_shoot_left_arm + { + player_snowmobile_gun_fire + player_snowmobile_gun_idle + + player_snowmobile_gun_pullout_root + { + player_snowmobile_gun_pullout_L + player_snowmobile_gun_pullout + player_snowmobile_gun_pullout_R + } + + player_snowmobile_gun_putaway_root + { + player_snowmobile_gun_putaway_L + player_snowmobile_gun_putaway + player_snowmobile_gun_putaway_R + } + + player_snowmobile_gun_reload + } + } + + player_snowmobile_right_arm + { + player_snowmobile_drive_turn_left2right_R + player_snowmobile_drive_turn_right2left_R + } + + snowmobile_glock + { + snowmobile_glock_fire + snowmobile_glock_last_fire + snowmobile_glock_reload + } + + player_snowmobile_drive_rpm_min + player_snowmobile_drive_rpm_max + + player_snowmobile_drive_speedometer_0 + player_snowmobile_drive_speedometer_90 + player_snowmobile_drive_speedometer_180 + + player_snowmobile_drive_throttle_add : additive + { + player_snowmobile_drive_throttle + } + + player_snowmobile_drive_throttle_add_left : additive + { + player_snowmobile_drive_throttle_left + } + + player_snowmobile_drive_throttle_add_right : additive + { + player_snowmobile_drive_throttle_right + } + + zodiac_waterfall_add_left : additive + { + AFchase_waterfall_player_zodiac_add_L + } + zodiac_waterfall_add_right : additive + { + AFchase_waterfall_player_zodiac_add_R + } + + + player_sleeve_pose + player_sleeve_flapping +} + + +rotate_X_R +rotate_X_L +rotate_Y_R +rotate_Y_L +rotate_Z_R +rotate_Z_L + +rotation +{ + rotate_body_X_R + rotate_body_X_L + rotate_body_Y_R + rotate_body_Y_L + rotate_body_Z_R + rotate_body_Z_L +} + +humvee_antennas_idle_movement +humvee_antennas_jerk_left +humvee_antennas_jerk_right + +humvee +{ + humvee_50cal_driving_idle_forward + humvee_50cal_driving_idle_backward +} + +humvee_antenna_additive : additive +{ + humvee_antenna_L_rotate_360 + humvee_antenna_R_rotate_360 +} + + +suburban +{ + player_suburban_minigun_fire2idle_L + player_suburban_minigun_fire2idle_R + player_suburban_minigun_idle_L + player_suburban_minigun_idle_R + player_suburban_minigun_idle2fire_L + player_suburban_minigun_idle2fire_R +} + +blackhawk_minigun_turret +{ + player_blackhawk_minigun_turret_fire2idle_L + player_blackhawk_minigun_turret_fire2idle_R + player_blackhawk_minigun_turret_idle_L + player_blackhawk_minigun_turret_idle_R + player_blackhawk_minigun_turret_idle2fire_L + player_blackhawk_minigun_turret_idle2fire_R + player_blackhawk_minigun_turret_hud_puton_L + player_blackhawk_minigun_turret_hud_puton_R + player_blackhawk_minigun_turret_hud_takeoff_L + player_blackhawk_minigun_turret_hud_takeoff_R +} + +chinese_lgv_turret +{ + left_hand + { + player_chinese_lgv_turret_fire2idle_L + player_chinese_lgv_turret_idle_L + player_chinese_lgv_turret_idle2fire_L + player_chinese_lgv_turret_suitshield_inject_L + player_chinese_lgv_turret_reaction_L + } + + right_hand + { + player_chinese_lgv_turret_fire2idle_R + player_chinese_lgv_turret_idle_R + player_chinese_lgv_turret_idle2fire_R + player_chinese_lgv_turret_suitshield_inject_R + player_chinese_lgv_turret_reaction_R + } +} +predator +{ + predator_flyby +} + + +cliffhanger +{ + cliff_jeep_crash +} + +antonov +{ + paratrooper_jet_opendoors +} + +oilrig +{ + oilrig_sub_1 + oilrig_sub_2 + oilrig_SDV_1 + oilrig_SDV_2 + oilrig_civ_escape_zodiac_A + oilrig_civ_escape_zodiac_B +} + +suburban_playermove_window_l_in +suburban_playermove_window_l_out +suburban_playermove_window_r_in +suburban_playermove_window_r_out + +roadkill_orders_hummer + +gulag_F15_intro_1 +gulag_F15_intro_2 +gulag_missile_intro_1 +gulag_missile_intro_2 +gulag_eject_seat_intro +gulag_missile_F15_1_A +gulag_missile_F15_1_B +gulag_missile_F15_2_A +gulag_missile_F15_2_B + +vehicle_80s_sedan1_flattire_LF +vehicle_80s_sedan1_flattire_LB +vehicle_80s_sedan1_flattire_RF +vehicle_80s_sedan1_flattire_RB +vehicle_80s_sedan1_destroy + +paradrop_cargo_vehicle + +favela_van_shootout_van +favela_opening_cardoor_open +favela_run_and_wave_cardoor + +invasion_opening_hummer2 +invasion_opening_hummer1 +invasion_opening_BTR +invasion_btr_crash_btr +invasion_btr_crash_squashedcar + +favela_ending_car + +favela_escape_ending_chopper_open_back_door +favela_escape_ending_chopper_in +favela_escape_ending_chopper_loop +favela_escape_ending_chopper_flying_away + +contingency_btr_slide + +zodiac_price_left_aim_4 +zodiac_price_left_aim_5 +zodiac_price_left_aim_6 +zodiac_price_right_aim_4 +zodiac_price_right_aim_5 +zodiac_price_right_aim_6 + +sa15_radar_spinup +sa15_radar_spinloop +sa15_radar_spindown +sa15_turret_scanloop + +training_humvee_door + +estate_chopper_sequence_pavelow + +airport_ending_open_doors +airport_ending_close_doors + +russian_swat_van_driver_getout_door + +nx_vh_crawler_movement + +Nx_Miniuav_Idle +Nx_Miniuav_HitReact +Nx_Miniuav_fire + +nx_vh_ugv_movement +nx_vh_ugv_movement_backwards +nx_vh_ugv_main_turret_fire + +nx_vh_future_tank_movement +nx_vh_future_tank_movement_backwards +nx_vh_future_tank_loading + +nx_vh_osprey_movement + +nx_vh_blackhawk_us_movement + +nx_vh_moving_platform_movement + +nx_vh_lunar_rover_movement +nx_vh_lunar_rover_movement_backwards + +nx_vh_president_suburban_movement +nx_vh_president_suburban_movement_backwards + +nx_vh_chinese_ugv_movement +nx_vh_chinese_ugv_movement_backwards + +nx_vh_chinese_tanker_movement +nx_vh_chinese_tanker_movement_backwards + +nx_vh_chinese_vtol_getout +nx_vh_chinese_vtol_getout_low +nx_vh_chinese_vtol_stopflare + +nx_vh_chinese_lgv_movement +nx_vh_chinese_lgv_movement_backwards +nx_vh_chinese_lgv_door_open + +nx_vh_chinese_lgv_gunner_mount_turret +nx_vh_chinese_lgv_gunner_getout_turret + +nx_vh_lapd_passenger_door_getout +nx_vh_lapd_driver_door_getout + +nx_vh_exfil_swat_back_doors_open + +nx_vh_exfil_policecar_driver_door_open + +nx_vh_Sedan_Right_Front_Door_Open_Min +nx_vh_Sedan_Right_Rear_Door_Open_Min +nx_vh_Sedan_Left_Front_Door_Open_Min +nx_vh_Sedan_Left_Rear_Door_Open_Min +nx_vh_Sedan_Right_Front_Door_Open_Med +nx_vh_Sedan_Right_Rear_Door_Open_Med +nx_vh_Sedan_Left_Front_Door_Open_Med +nx_vh_Sedan_Left_Rear_Door_Open_Med +nx_vh_Sedan_Right_Front_Door_Open_Max +nx_vh_Sedan_Right_Rear_Door_Open_Max +nx_vh_Sedan_Left_Front_Door_Open_Max +nx_vh_Sedan_Left_Rear_Door_Open_Max + +nx_vh_SUV_Right_Front_Door_Open_Min +nx_vh_SUV_Right_Rear_Door_Open_Min +nx_vh_SUV_Left_Front_Door_Open_Min +nx_vh_SUV_Left_Rear_Door_Open_Min +nx_vh_SUV_Right_Front_Door_Open_Med +nx_vh_SUV_Right_Rear_Door_Open_Med +nx_vh_SUV_Left_Front_Door_Open_Med +nx_vh_SUV_Left_Rear_Door_Open_Med +nx_vh_SUV_Right_Front_Door_Open_Max +nx_vh_SUV_Right_Rear_Door_Open_Max +nx_vh_SUV_Left_Front_Door_Open_Max +nx_vh_SUV_Left_Rear_Door_Open_Max + +nx_vh_chinese_vtol_movement + +nx_vh_chinese_skimmer_movement +nx_vh_chinese_skimmer_motntst01 +nx_vh_chinese_skimmer_motntst02 + +nx_vh_lb_spotlight_search_w_rotors +nx_vh_lb_spotlight_stable_w_rotors + +nx_vh_escort_ugv_dropoff_ugv +nx_vh_escort_ugv_dropoff_osprey + +nx_lava_train_cart_allied_01 +nx_lava_train_cart_allied_02 +nx_lava_train_cart_allied_03 +nx_lava_train_cart_allied_04 +nx_lava_train_cart_axis_01 +nx_lava_train_cart_axis_02 +nx_lava_train_cart_axis_03 +nx_lava_train_cart_axis_04 +nx_lava_train_cart_axis_05 +nx_lava_train_cart_axis_06 +nx_lava_train_cart_axis_07 +nx_lava_train_cart_axis_08 + +//*PROTOTYPE* nx_vh_night_raven assets *PROTOTYPE* +proto_nx_vh_night_raven_movement +proto_nx_vh_night_raven_missiles_fire + +//EC_VTOL UAV CARGODROP// +nx_vh_chinese_vtol_UAV_Cargodropoff_Cargo +nx_vh_chinese_vtol_UAV_Cargodropoff_VTOL +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV01 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV02 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV03 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV04 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV05 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV06 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV07 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV08 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV09 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV10 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV11 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV12 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV13 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV14 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV15 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV16 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV17 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV18 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV19 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV20 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV21 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV22 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV23 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV24 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV25 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV26 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV27 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV28 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV29 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV30 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV31 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV32 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV33 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV34 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV35 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV36 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV37 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV38 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV39 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV40 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV41 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV42 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV43 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV44 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV45 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV46 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV47 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV48 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV49 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV50 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV51 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV52 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV53 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV54 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV55 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV56 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV57 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV58 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV59 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV60 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV61 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV62 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV63 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV64 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV65 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV66 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV67 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV68 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV69 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV70 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV71 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV72 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV73 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV74 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV75 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV76 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV77 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV78 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV79 +nx_vh_chinese_vtol_UAV_Cargodropoff_UAV80 +//EC_VTOL UAV CARGODROP// + +ugv_turn_anims +{ + nx_vh_ugv_movement_L + nx_vh_ugv_movement_R + nx_vh_ugv_movement_backwards_L + nx_vh_ugv_movement_backwards_R +} + +// nx_ugv_test anim for scripted event +ugv_in_motion +nx_ugv_bounce +nx_brickwall_ugv_brktrgh_ugv +nx_fp_rtc_aresreveal_ugv + +nx_lapes_ac130 +nx_lapes_m1a1 + +// nx_repel + +nx_tp_uav_reveal_uav1 +nx_tp_uav_reveal_uav2 +nx_repel_ugv_jumpoff_LZ +nx_fp_rtc_osprey_intro_ugv +nx_fp_rtc_osprey_intro_osprey +nx_vh_rtc_osprey_flyby_osprey1 +nx_vh_rtc_osprey_flyby_osprey2 +nx_vh_rtc_osprey_flyby_osprey3 + +//Lunar +nx_vh_lunar_rovercrash_player +nx_vh_lunar_ec_lgv_arrive +nx_vh_lunar_falcon_death_rover + +nx_vh_lunar_rover_intro +{ + nx_vh_lunar_rover_intro_drive_rover + nx_vh_lunar_rover_intro_jump_rover +} + +//subpen_apc_deploy +nx_tp_sub_apc_animatic + +// nx_Skyscraper +nx_vh_skyscraper_landing_pad_vtol_01 +nx_vh_skyscraper_uav_crash_01 +nx_vh_skyscraper_uav_crash_01_idle +nx_vh_skyscraper_uav_crash_01_p2 +nx_vh_skyscraper_uav_crash_01_p2_idle +nx_vh_skyscraper_uav_crash_01_p3 +nx_vh_skyscraper_atrium_crash_01 + +//hithard +nx_news_chopper_crash +nx_vh_hhh_parachute_idle +nx_vh_hhh_parachute_deploy_osprey +nx_vh_hhh_parachute_deploy_parachute + +nx_vh_hhh_parachute_landed +nx_vh_hhh_parachute_landed_guy2 + +nx_vh_hithard_ec_ugv_pullup_sedan_1 +nx_vh_hithard_ec_ugv_pullup_sedan_2 + +nx_vh_hithard_vtol_uav_deploy + +nx_vh_hithard_motorcade_ambush3_suv_01 +nx_vh_hithard_motorcade_ambush3_suv_02 +nx_vh_hithard_Intro_Osprey01 +nx_vh_hithard_Intro_Osprey02 +nx_vh_hithard_Intro_Osprey03 +nx_vh_hithard_Intro_Osprey04 +nx_vh_hithard_Intro_part1_Osprey01 +nx_vh_hithard_Intro_part1_Osprey02 +nx_vh_chinese_vtol_ugv_dropoff_suv_01 +nx_vh_chinese_vtol_ugv_dropoff_ugv_01 +nx_vh_chinese_vtol_ugv_dropoff_chinese_vtol_01 +nx_vh_hithard_ospreycrashvp_osprey_01 + +//hithard_b + +nx_vh_hhh_tanklapes_tank_unlatch_01 +nx_vh_hhh_tanklapes_tank_01 + +//PROTOTYPE Roboturret + +nx_vh_roboturret_run +nx_vh_roboturret_walk +nx_vh_roboturret_idle + +//Prototype Chase + +prototype_chase_vh_jeep_jump_jeep + +//Rocket +nx_vh_rocket_intro_helicopter_01 +nx_vh_rocket_intro_helicopter_02 +nx_vh_rocket_intro_helicopter_03 +nx_vh_rocket_intro_helicopter_04 +nx_vh_rocket_intro_helicopter_05 +nx_vh_rocket_intro_helicopter_06 +nx_vh_rocket_intro_helicopter_07 +nx_vh_rocket_intro_helicopter_08 +nx_vh_rocket_intro_helicopter_player_01 +nx_vh_rocket_intro_Bomber_01 +nx_vh_rocket_intro_Bomber_02 +nx_vh_rocket_intro_Bomber_03 +nx_vh_rocket_intro_Bomber_04 +nx_vh_rocket_helicoptercrash_helicopter_01 +nx_vh_rocket_helicoptercrash_helicopter_02 +nx_vh_rocket_witness_nuke_helicpoter_01 +nx_vh_rocket_jump_onto_gantry_littlebird_01 +nx_vh_rocket_climb_onto_littlebird_littlebird_01 +nx_vh_rocket_woods_chopperflyover_blackhawk_01 +nx_vh_rocket_opfor_helicopter_intro_opfor_heli_01 +nx_vh_rocket_opfor_helicopter_intro_opfor_heli_02 +nx_vh_rocket_helicopter_bridge_opfor_heli +nx_vh_rocket_chopper_btl_delta_hind_01 +nx_vh_rocket_chopper_btl_delta_blackhind_02 +nx_vh_rocket_chopper_btl_delta_blackhawk_01 +nx_vh_rocket_chopper_btl_delta_blackhawk_02 +nx_vh_rocket_chopper_btl_delta_blackhawk_03 +nx_vh_rocket_chopper_btl_delta_blackhawk_04 +nx_vh_rocket_chopper_btl_delta_blackhawk_05 +nx_vh_rocket_nuke_crash_chopper2 +nx_vh_rocket_nuke_crash_chopper3 +nx_vh_rocket_base_delta_01_player_heli +nx_vh_rocket_base_delta_01_ally_heli +nx_vh_rocket_base_delta_01_opfor_heli +nx_vh_rocket_base_delta_01_opfor_heli_02 +nx_vh_rocket_chopper_dogfight_delta_blackhawk_01 +nx_vh_rocket_chopper_dogfight_delta_opfor_01 +nx_vh_rocket_chopper_dogfight_delta_opfor_02 +nx_vh_rocket_chopper_btl_delta_ltlbrd_01 +nx_vh_rocket_chopper_btl_delta_ltlbrd_02 +nx_vh_rocket_aa_shoot_helicopter_down_heli + +//Exfil +nx_vh_exfil_police_cars1_car_01 +nx_vh_exfil_police_cars1_car_02 + +// lava +nx_vh_lava_train_derailment_rover_01 +nx_vh_lava_train_derailment_rover_02 +nx_vh_lava_roverarrive_rover +nx_vh_lava_control_breach_skimmer +nx_vh_lava_bridge_to_train_skimmer_01 +nx_vh_lava_bridge_to_train_skimmer_02 +nx_vh_lava_skimmer_battle_01_skimmer +nx_vh_lava_skimmer_battle_02_skimmer +nx_vh_lava_trainseperate_fall_train +nx_vh_lava_trainseperate_player_jump_train \ No newline at end of file diff --git a/character/mp_character_airborne_assault_a.gsc b/character/mp_character_airborne_assault_a.gsc new file mode 100644 index 0000000..4aaedbb --- /dev/null +++ b/character/mp_character_airborne_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_assault_a"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_assault_b.gsc b/character/mp_character_airborne_assault_b.gsc new file mode 100644 index 0000000..0adec72 --- /dev/null +++ b/character/mp_character_airborne_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_assault_b"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_assault_c.gsc b/character/mp_character_airborne_assault_c.gsc new file mode 100644 index 0000000..bd2e832 --- /dev/null +++ b/character/mp_character_airborne_assault_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_assault_c"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_assault_c"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_lmg.gsc b/character/mp_character_airborne_lmg.gsc new file mode 100644 index 0000000..ad3212b --- /dev/null +++ b/character/mp_character_airborne_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_lmg"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_lmg_b.gsc b/character/mp_character_airborne_lmg_b.gsc new file mode 100644 index 0000000..5d65636 --- /dev/null +++ b/character/mp_character_airborne_lmg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_lmg_b"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_lmg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_lmg_c.gsc b/character/mp_character_airborne_lmg_c.gsc new file mode 100644 index 0000000..6e040dd --- /dev/null +++ b/character/mp_character_airborne_lmg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_lmg_c"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_lmg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_shotgun.gsc b/character/mp_character_airborne_shotgun.gsc new file mode 100644 index 0000000..a41d803 --- /dev/null +++ b/character/mp_character_airborne_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_shotgun"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_shotgun_b.gsc b/character/mp_character_airborne_shotgun_b.gsc new file mode 100644 index 0000000..0e27139 --- /dev/null +++ b/character/mp_character_airborne_shotgun_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_shotgun_b"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_shotgun_b"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_shotgun_c.gsc b/character/mp_character_airborne_shotgun_c.gsc new file mode 100644 index 0000000..d9761b5 --- /dev/null +++ b/character/mp_character_airborne_shotgun_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_shotgun_c"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_shotgun_c"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_smg.gsc b/character/mp_character_airborne_smg.gsc new file mode 100644 index 0000000..439c752 --- /dev/null +++ b/character/mp_character_airborne_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_smg"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_smg_b.gsc b/character/mp_character_airborne_smg_b.gsc new file mode 100644 index 0000000..09726b1 --- /dev/null +++ b/character/mp_character_airborne_smg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_smg_b"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_smg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_airborne_smg_c.gsc b/character/mp_character_airborne_smg_c.gsc new file mode 100644 index 0000000..c648427 --- /dev/null +++ b/character/mp_character_airborne_smg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_airborne_smg_c"); codescripts\character::attachHead( "alias_airborne_heads", xmodelalias\alias_airborne_heads::main() ); self setViewmodel("viewhands_russian_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_airborne_smg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_airborne_heads::main()); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_ally_ghillie_arctic.gsc b/character/mp_character_ally_ghillie_arctic.gsc new file mode 100644 index 0000000..e55bbb2 --- /dev/null +++ b/character/mp_character_ally_ghillie_arctic.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_ally_sniper_ghillie_arctic"); + self attach("head_allies_sniper_ghillie_arctic", "", true); + self.headModel = "head_allies_sniper_ghillie_arctic"; + self setViewmodel("viewhands_ghillie_arctic"); + self.voice = "taskforce"; +} +precache() +{ + precacheModel("mp_body_ally_sniper_ghillie_arctic"); + precacheModel("head_allies_sniper_ghillie_arctic"); + precacheModel("viewhands_ghillie_arctic"); +} \ No newline at end of file diff --git a/character/mp_character_ally_ghillie_desert.gsc b/character/mp_character_ally_ghillie_desert.gsc new file mode 100644 index 0000000..95bf62f --- /dev/null +++ b/character/mp_character_ally_ghillie_desert.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_ally_sniper_ghillie_desert"); + self attach("head_allies_sniper_ghillie_desert", "", true); + self.headModel = "head_allies_sniper_ghillie_desert"; + self setViewmodel("viewhands_ghillie_desert"); + self.voice = "taskforce"; +} +precache() +{ + precacheModel("mp_body_ally_sniper_ghillie_desert"); + precacheModel("head_allies_sniper_ghillie_desert"); + precacheModel("viewhands_ghillie_desert"); +} \ No newline at end of file diff --git a/character/mp_character_ally_ghillie_forest.gsc b/character/mp_character_ally_ghillie_forest.gsc new file mode 100644 index 0000000..ac0cbf9 --- /dev/null +++ b/character/mp_character_ally_ghillie_forest.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_ally_sniper_ghillie_forest"); + self attach("head_allies_sniper_ghillie_forest", "", true); + self.headModel = "head_allies_sniper_ghillie_forest"; + self setViewmodel("viewhands_ghillie_forest"); + self.voice = "taskforce"; +} +precache() +{ + precacheModel("mp_body_ally_sniper_ghillie_forest"); + precacheModel("head_allies_sniper_ghillie_forest"); + precacheModel("viewhands_ghillie_forest"); +} \ No newline at end of file diff --git a/character/mp_character_ally_ghillie_urban.gsc b/character/mp_character_ally_ghillie_urban.gsc new file mode 100644 index 0000000..2ac54bf --- /dev/null +++ b/character/mp_character_ally_ghillie_urban.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_ally_sniper_ghillie_urban"); + self attach("head_allies_sniper_ghillie_urban", "", true); + self.headModel = "head_allies_sniper_ghillie_urban"; + self setViewmodel("viewhands_ghillie_urban"); + self.voice = "seal"; +} +precache() +{ + precacheModel("mp_body_ally_sniper_ghillie_urban"); + precacheModel("head_allies_sniper_ghillie_urban"); + precacheModel("viewhands_ghillie_urban"); +} \ No newline at end of file diff --git a/character/mp_character_composite_assault_a.gsc b/character/mp_character_composite_assault_a.gsc new file mode 100644 index 0000000..271925e --- /dev/null +++ b/character/mp_character_composite_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arab_assault_a"); codescripts\character::attachHead( "alias_opforce_arab_heads", xmodelalias\alias_opforce_arab_heads::main() ); self setViewmodel("viewhands_militia"); self.voice = "arab";}precache(){ precacheModel("mp_body_opforce_arab_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arab_heads::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_composite_lmg.gsc b/character/mp_character_composite_lmg.gsc new file mode 100644 index 0000000..fd04b44 --- /dev/null +++ b/character/mp_character_composite_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arab_lmg_a"); codescripts\character::attachHead( "alias_opforce_arab_heads", xmodelalias\alias_opforce_arab_heads::main() ); self setViewmodel("viewhands_militia"); self.voice = "arab";}precache(){ precacheModel("mp_body_opforce_arab_lmg_a"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arab_heads::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_composite_shotgun.gsc b/character/mp_character_composite_shotgun.gsc new file mode 100644 index 0000000..e3ed6a7 --- /dev/null +++ b/character/mp_character_composite_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arab_shotgun_a"); codescripts\character::attachHead( "alias_opforce_arab_heads", xmodelalias\alias_opforce_arab_heads::main() ); self setViewmodel("viewhands_militia"); self.voice = "arab";}precache(){ precacheModel("mp_body_opforce_arab_shotgun_a"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arab_heads::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_composite_smg.gsc b/character/mp_character_composite_smg.gsc new file mode 100644 index 0000000..ac418cb --- /dev/null +++ b/character/mp_character_composite_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arab_smg_a"); codescripts\character::attachHead( "alias_opforce_arab_heads", xmodelalias\alias_opforce_arab_heads::main() ); self setViewmodel("viewhands_militia"); self.voice = "arab";}precache(){ precacheModel("mp_body_opforce_arab_smg_a"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arab_heads::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_assault_aa_blk.gsc b/character/mp_character_militia_assault_aa_blk.gsc new file mode 100644 index 0000000..869e982 --- /dev/null +++ b/character/mp_character_militia_assault_aa_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_assault_aa_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_assault_aa_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_assault_aa_wht.gsc b/character/mp_character_militia_assault_aa_wht.gsc new file mode 100644 index 0000000..ebbd1cc --- /dev/null +++ b/character/mp_character_militia_assault_aa_wht.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_assault_aa_wht"); codescripts\character::attachHead( "alias_opforce_militia_heads_wht", xmodelalias\alias_opforce_militia_heads_wht::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_assault_aa_wht"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_wht::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_assault_ab_blk.gsc b/character/mp_character_militia_assault_ab_blk.gsc new file mode 100644 index 0000000..de2228c --- /dev/null +++ b/character/mp_character_militia_assault_ab_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_assault_ab_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_assault_ab_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_assault_ac_blk.gsc b/character/mp_character_militia_assault_ac_blk.gsc new file mode 100644 index 0000000..9d0c9ad --- /dev/null +++ b/character/mp_character_militia_assault_ac_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_assault_ac_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_assault_ac_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_lmg_aa_blk.gsc b/character/mp_character_militia_lmg_aa_blk.gsc new file mode 100644 index 0000000..0985548 --- /dev/null +++ b/character/mp_character_militia_lmg_aa_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_lmg_aa_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_lmg_aa_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_lmg_ab_blk.gsc b/character/mp_character_militia_lmg_ab_blk.gsc new file mode 100644 index 0000000..4e46bfd --- /dev/null +++ b/character/mp_character_militia_lmg_ab_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_lmg_ab_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_lmg_ab_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_lmg_ac_blk.gsc b/character/mp_character_militia_lmg_ac_blk.gsc new file mode 100644 index 0000000..55bd4bf --- /dev/null +++ b/character/mp_character_militia_lmg_ac_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_lmg_ac_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_lmg_ac_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_shotgun_aa_blk.gsc b/character/mp_character_militia_shotgun_aa_blk.gsc new file mode 100644 index 0000000..6ba6b08 --- /dev/null +++ b/character/mp_character_militia_shotgun_aa_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_aa_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_aa_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_shotgun_aa_wht.gsc b/character/mp_character_militia_shotgun_aa_wht.gsc new file mode 100644 index 0000000..49b3390 --- /dev/null +++ b/character/mp_character_militia_shotgun_aa_wht.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_aa_wht"); codescripts\character::attachHead( "alias_opforce_militia_heads_wht", xmodelalias\alias_opforce_militia_heads_wht::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_aa_wht"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_wht::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_smg_aa_blk.gsc b/character/mp_character_militia_smg_aa_blk.gsc new file mode 100644 index 0000000..6ba6b08 --- /dev/null +++ b/character/mp_character_militia_smg_aa_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_aa_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_aa_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_smg_aa_wht.gsc b/character/mp_character_militia_smg_aa_wht.gsc new file mode 100644 index 0000000..49b3390 --- /dev/null +++ b/character/mp_character_militia_smg_aa_wht.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_aa_wht"); codescripts\character::attachHead( "alias_opforce_militia_heads_wht", xmodelalias\alias_opforce_militia_heads_wht::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_aa_wht"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_wht::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_smg_ab_blk.gsc b/character/mp_character_militia_smg_ab_blk.gsc new file mode 100644 index 0000000..88d86c4 --- /dev/null +++ b/character/mp_character_militia_smg_ab_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_ab_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_ab_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_militia_smg_ac_blk.gsc b/character/mp_character_militia_smg_ac_blk.gsc new file mode 100644 index 0000000..32e22cc --- /dev/null +++ b/character/mp_character_militia_smg_ac_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_militia_smg_ac_blk"); codescripts\character::attachHead( "alias_opforce_militia_heads_blk", xmodelalias\alias_opforce_militia_heads_blk::main() ); self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_militia_smg_ac_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_militia_heads_blk::main()); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_nx_ally_juggernaut.gsc b/character/mp_character_nx_ally_juggernaut.gsc new file mode 100644 index 0000000..1dfafb5 --- /dev/null +++ b/character/mp_character_nx_ally_juggernaut.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("body_complete_mp_pmc_ai_temp"); + self attach("head_complete_mp_pmc_ai_temp", "", true); + self.headModel = "head_complete_mp_pmc_ai_temp"; + self setViewmodel("viewhands_usmc"); + self.voice = "american"; +} +precache() +{ + precacheModel("body_complete_mp_pmc_ai_temp"); + precacheModel("head_complete_mp_pmc_ai_temp"); + precacheModel("viewhands_usmc"); +} \ No newline at end of file diff --git a/character/mp_character_nx_axis_juggernaut.gsc b/character/mp_character_nx_axis_juggernaut.gsc new file mode 100644 index 0000000..fd9c1f3 --- /dev/null +++ b/character/mp_character_nx_axis_juggernaut.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("body_complete_mp_pmc_ai_alt_temp"); self attach("head_complete_mp_pmc_ai_alt_temp", "", true); self.headModel = "head_complete_mp_pmc_ai_alt_temp"; self setViewmodel("viewhands_op_force"); self.voice = "american";}precache(){ precacheModel("body_complete_mp_pmc_ai_alt_temp"); precacheModel("head_complete_mp_pmc_ai_alt_temp"); precacheModel("viewhands_op_force");} \ No newline at end of file diff --git a/character/mp_character_op_airborne_riot.gsc b/character/mp_character_op_airborne_riot.gsc new file mode 100644 index 0000000..0d4e540 --- /dev/null +++ b/character/mp_character_op_airborne_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_op_airborne"); self attach("head_riot_op_airborne", "", true); self.headModel = "head_riot_op_airborne"; self setViewmodel("viewhands_russian_airborne"); self.voice = "seal";}precache(){ precacheModel("mp_body_riot_op_airborne"); precacheModel("head_riot_op_airborne"); precacheModel("viewhands_russian_airborne");} \ No newline at end of file diff --git a/character/mp_character_op_airborne_sniper.gsc b/character/mp_character_op_airborne_sniper.gsc new file mode 100644 index 0000000..9da6f3c --- /dev/null +++ b/character/mp_character_op_airborne_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_op_airborne_sniper"); self attach("head_op_airborne_sniper", "", true); self.headModel = "head_op_airborne_sniper"; self setViewmodel("viewhands_sniper_op_airborne"); self.voice = "russian";}precache(){ precacheModel("mp_body_op_airborne_sniper"); precacheModel("head_op_airborne_sniper"); precacheModel("viewhands_sniper_op_airborne");} \ No newline at end of file diff --git a/character/mp_character_op_arab_riot.gsc b/character/mp_character_op_arab_riot.gsc new file mode 100644 index 0000000..596bba2 --- /dev/null +++ b/character/mp_character_op_arab_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_op_arab"); self attach("head_riot_op_arab", "", true); self.headModel = "head_riot_op_arab"; self setViewmodel("viewhands_militia"); self.voice = "arab";}precache(){ precacheModel("mp_body_riot_op_arab"); precacheModel("head_riot_op_arab"); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_op_arab_sniper.gsc b/character/mp_character_op_arab_sniper.gsc new file mode 100644 index 0000000..58f922f --- /dev/null +++ b/character/mp_character_op_arab_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_op_arab_sniper"); self attach("head_op_arab_sniper", "", true); self.headModel = "head_op_arab_sniper"; self setViewmodel("viewhands_sniper_op_arab"); self.voice = "arab";}precache(){ precacheModel("mp_body_op_arab_sniper"); precacheModel("head_op_arab_sniper"); precacheModel("viewhands_sniper_op_arab");} \ No newline at end of file diff --git a/character/mp_character_op_arctic_riot.gsc b/character/mp_character_op_arctic_riot.gsc new file mode 100644 index 0000000..3a3f778 --- /dev/null +++ b/character/mp_character_op_arctic_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_op_arctic"); self attach("head_riot_op_arctic", "", true); self.headModel = "head_riot_op_arctic"; self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_riot_op_arctic"); precacheModel("head_riot_op_arctic"); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_op_arctic_sniper.gsc b/character/mp_character_op_arctic_sniper.gsc new file mode 100644 index 0000000..a01aebc --- /dev/null +++ b/character/mp_character_op_arctic_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_op_arctic_sniper"); self attach("head_op_arctic_sniper", "", true); self.headModel = "head_op_arctic_sniper"; self setViewmodel("viewhands_sniper_op_arctic"); self.voice = "russian";}precache(){ precacheModel("mp_body_op_arctic_sniper"); precacheModel("head_op_arctic_sniper"); precacheModel("viewhands_sniper_op_arctic");} \ No newline at end of file diff --git a/character/mp_character_op_ghillie_arctic.gsc b/character/mp_character_op_ghillie_arctic.gsc new file mode 100644 index 0000000..dcfffb4 --- /dev/null +++ b/character/mp_character_op_ghillie_arctic.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_op_sniper_ghillie_arctic"); + self attach("head_op_sniper_ghillie_arctic", "", true); + self.headModel = "head_op_sniper_ghillie_arctic"; + self setViewmodel("viewhands_ghillie_arctic"); + self.voice = "russian"; +} +precache() +{ + precacheModel("mp_body_op_sniper_ghillie_arctic"); + precacheModel("head_op_sniper_ghillie_arctic"); + precacheModel("viewhands_ghillie_arctic"); +} \ No newline at end of file diff --git a/character/mp_character_op_ghillie_desert.gsc b/character/mp_character_op_ghillie_desert.gsc new file mode 100644 index 0000000..3f394d1 --- /dev/null +++ b/character/mp_character_op_ghillie_desert.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_op_sniper_ghillie_desert"); + self attach("head_op_sniper_ghillie_desert", "", true); + self.headModel = "head_op_sniper_ghillie_desert"; + self setViewmodel("viewhands_ghillie_desert"); + self.voice = "arab"; +} +precache() +{ + precacheModel("mp_body_op_sniper_ghillie_desert"); + precacheModel("head_op_sniper_ghillie_desert"); + precacheModel("viewhands_ghillie_desert"); +} \ No newline at end of file diff --git a/character/mp_character_op_ghillie_forest.gsc b/character/mp_character_op_ghillie_forest.gsc new file mode 100644 index 0000000..ee37647 --- /dev/null +++ b/character/mp_character_op_ghillie_forest.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_op_sniper_ghillie_forest"); + self attach("head_op_sniper_ghillie_forest", "", true); + self.headModel = "head_op_sniper_ghillie_forest"; + self setViewmodel("viewhands_ghillie_forest"); + self.voice = "russian"; +} +precache() +{ + precacheModel("mp_body_op_sniper_ghillie_forest"); + precacheModel("head_op_sniper_ghillie_forest"); + precacheModel("viewhands_ghillie_forest"); +} \ No newline at end of file diff --git a/character/mp_character_op_ghillie_urban.gsc b/character/mp_character_op_ghillie_urban.gsc new file mode 100644 index 0000000..e6188c3 --- /dev/null +++ b/character/mp_character_op_ghillie_urban.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_op_sniper_ghillie_urban"); + self attach("head_op_sniper_ghillie_urban", "", true); + self.headModel = "head_op_sniper_ghillie_urban"; + self setViewmodel("viewhands_ghillie_urban"); + self.voice = "russian"; +} +precache() +{ + precacheModel("mp_body_op_sniper_ghillie_urban"); + precacheModel("head_op_sniper_ghillie_urban"); + precacheModel("viewhands_ghillie_urban"); +} \ No newline at end of file diff --git a/character/mp_character_op_militia_riot.gsc b/character/mp_character_op_militia_riot.gsc new file mode 100644 index 0000000..ddf3ec6 --- /dev/null +++ b/character/mp_character_op_militia_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_op_militia"); self attach("head_riot_op_militia", "", true); self.headModel = "head_riot_op_militia"; self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_riot_op_militia"); precacheModel("head_riot_op_militia"); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_op_militia_sniper.gsc b/character/mp_character_op_militia_sniper.gsc new file mode 100644 index 0000000..187e1a6 --- /dev/null +++ b/character/mp_character_op_militia_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_op_miltia_sniper"); self attach("head_op_militia_sniper", "", true); self.headModel = "head_op_militia_sniper"; self setViewmodel("viewhands_militia"); self.voice = "portuguese";}precache(){ precacheModel("mp_body_op_miltia_sniper"); precacheModel("head_op_militia_sniper"); precacheModel("viewhands_militia");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_assault_a.gsc b/character/mp_character_opforce_arctic_assault_a.gsc new file mode 100644 index 0000000..1ef621a --- /dev/null +++ b/character/mp_character_opforce_arctic_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_assault_a"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_assault_b.gsc b/character/mp_character_opforce_arctic_assault_b.gsc new file mode 100644 index 0000000..380d58a --- /dev/null +++ b/character/mp_character_opforce_arctic_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_assault_b"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_assault_c.gsc b/character/mp_character_opforce_arctic_assault_c.gsc new file mode 100644 index 0000000..a2e5cfa --- /dev/null +++ b/character/mp_character_opforce_arctic_assault_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_assault_c"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_assault_c"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_lmg.gsc b/character/mp_character_opforce_arctic_lmg.gsc new file mode 100644 index 0000000..279689d --- /dev/null +++ b/character/mp_character_opforce_arctic_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_lmg"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_lmg_b.gsc b/character/mp_character_opforce_arctic_lmg_b.gsc new file mode 100644 index 0000000..f7bb735 --- /dev/null +++ b/character/mp_character_opforce_arctic_lmg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_lmg_b"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_lmg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_lmg_c.gsc b/character/mp_character_opforce_arctic_lmg_c.gsc new file mode 100644 index 0000000..776dc44 --- /dev/null +++ b/character/mp_character_opforce_arctic_lmg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_lmg_c"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_lmg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_shotgun.gsc b/character/mp_character_opforce_arctic_shotgun.gsc new file mode 100644 index 0000000..e8af58c --- /dev/null +++ b/character/mp_character_opforce_arctic_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_shotgun"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_shotgun_b.gsc b/character/mp_character_opforce_arctic_shotgun_b.gsc new file mode 100644 index 0000000..e6ef0fe --- /dev/null +++ b/character/mp_character_opforce_arctic_shotgun_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_shotgun_b"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_shotgun_b"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_shotgun_c.gsc b/character/mp_character_opforce_arctic_shotgun_c.gsc new file mode 100644 index 0000000..226f743 --- /dev/null +++ b/character/mp_character_opforce_arctic_shotgun_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_shotgun_c"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_shotgun_c"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_smg.gsc b/character/mp_character_opforce_arctic_smg.gsc new file mode 100644 index 0000000..078b274 --- /dev/null +++ b/character/mp_character_opforce_arctic_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_smg"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_smg_b.gsc b/character/mp_character_opforce_arctic_smg_b.gsc new file mode 100644 index 0000000..c9215a5 --- /dev/null +++ b/character/mp_character_opforce_arctic_smg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_smg_b"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_smg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_opforce_arctic_smg_c.gsc b/character/mp_character_opforce_arctic_smg_c.gsc new file mode 100644 index 0000000..1a66f4e --- /dev/null +++ b/character/mp_character_opforce_arctic_smg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_opforce_arctic_smg_c"); codescripts\character::attachHead( "alias_opforce_arctic_heads", xmodelalias\alias_opforce_arctic_heads::main() ); self setViewmodel("viewhands_arctic_opforce"); self.voice = "russian";}precache(){ precacheModel("mp_body_opforce_arctic_smg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_opforce_arctic_heads::main()); precacheModel("viewhands_arctic_opforce");} \ No newline at end of file diff --git a/character/mp_character_seal_socom_assault_a.gsc b/character/mp_character_seal_socom_assault_a.gsc new file mode 100644 index 0000000..5c84269 --- /dev/null +++ b/character/mp_character_seal_socom_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_a"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp", xmodelalias\alias_seal_soccom_heads_mp::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_seal_socom_assault_b.gsc b/character/mp_character_seal_socom_assault_b.gsc new file mode 100644 index 0000000..465a2ee --- /dev/null +++ b/character/mp_character_seal_socom_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_b"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp", xmodelalias\alias_seal_soccom_heads_mp::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_seal_socom_assault_b_blk.gsc b/character/mp_character_seal_socom_assault_b_blk.gsc new file mode 100644 index 0000000..caf81eb --- /dev/null +++ b/character/mp_character_seal_socom_assault_b_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_b_blk"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp_blk", xmodelalias\alias_seal_soccom_heads_mp_blk::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_b_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp_blk::main()); precacheModel("viewhands_us_army");} diff --git a/character/mp_character_seal_socom_assault_c.gsc b/character/mp_character_seal_socom_assault_c.gsc new file mode 100644 index 0000000..4018fd9 --- /dev/null +++ b/character/mp_character_seal_socom_assault_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_c"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp", xmodelalias\alias_seal_soccom_heads_mp::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_c"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_seal_socom_assault_c_blk.gsc b/character/mp_character_seal_socom_assault_c_blk.gsc new file mode 100644 index 0000000..80a9d1f --- /dev/null +++ b/character/mp_character_seal_socom_assault_c_blk.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_c_blk"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp_blk", xmodelalias\alias_seal_soccom_heads_mp_blk::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_c_blk"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp_blk::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_seal_socom_assault_d.gsc b/character/mp_character_seal_socom_assault_d.gsc new file mode 100644 index 0000000..3b5ba36 --- /dev/null +++ b/character/mp_character_seal_socom_assault_d.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_soccom_assault_d"); codescripts\character::attachHead( "alias_seal_soccom_heads_mp", xmodelalias\alias_seal_soccom_heads_mp::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_seal_soccom_assault_d"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_soccom_heads_mp::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_seal_udt_assault_a.gsc b/character/mp_character_seal_udt_assault_a.gsc new file mode 100644 index 0000000..e745820 --- /dev/null +++ b/character/mp_character_seal_udt_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_udt_assault_a"); codescripts\character::attachHead( "alias_seal_udt_heads", xmodelalias\alias_seal_udt_heads::main() ); self setViewmodel("viewhands_udt"); self.voice = "seal";}precache(){ precacheModel("mp_body_seal_udt_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_udt_heads::main()); precacheModel("viewhands_udt");} diff --git a/character/mp_character_seal_udt_assault_b.gsc b/character/mp_character_seal_udt_assault_b.gsc new file mode 100644 index 0000000..ed8182f --- /dev/null +++ b/character/mp_character_seal_udt_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_udt_assault_b"); codescripts\character::attachHead( "alias_seal_udt_heads", xmodelalias\alias_seal_udt_heads::main() ); self setViewmodel("viewhands_udt"); self.voice = "seal";}precache(){ precacheModel("mp_body_seal_udt_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_udt_heads::main()); precacheModel("viewhands_udt");} diff --git a/character/mp_character_seal_udt_lmg.gsc b/character/mp_character_seal_udt_lmg.gsc new file mode 100644 index 0000000..37a8b63 --- /dev/null +++ b/character/mp_character_seal_udt_lmg.gsc @@ -0,0 +1,14 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_seal_udt_lmg"); + codescripts\character::attachHead( "alias_seal_udt_heads", xmodelalias\alias_seal_udt_heads::main() ); + self setViewmodel("viewhands_udt"); + self.voice = "seal"; +} +precache() +{ + precacheModel("mp_body_seal_udt_lmg"); + codescripts\character::precacheModelArray(xmodelalias\alias_seal_udt_heads::main()); + precacheModel("viewhands_udt"); +} \ No newline at end of file diff --git a/character/mp_character_seal_udt_smg.gsc b/character/mp_character_seal_udt_smg.gsc new file mode 100644 index 0000000..6d3822b --- /dev/null +++ b/character/mp_character_seal_udt_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_seal_udt_smg"); codescripts\character::attachHead( "alias_seal_udt_heads", xmodelalias\alias_seal_udt_heads::main() ); self setViewmodel("viewhands_udt"); self.voice = "seal";}precache(){ precacheModel("mp_body_seal_udt_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_seal_udt_heads::main()); precacheModel("viewhands_udt");} diff --git a/character/mp_character_seal_udt_sniper.gsc b/character/mp_character_seal_udt_sniper.gsc new file mode 100644 index 0000000..c0d767d --- /dev/null +++ b/character/mp_character_seal_udt_sniper.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_body_seal_udt_sniper"); + self attach("head_allies_seal_udt_sniper", "", true); + self.headModel = "head_allies_seal_udt_sniper"; + self setViewmodel("viewhands_sniper_udt"); + self.voice = "seal"; +} +precache() +{ + precacheModel("mp_body_seal_udt_sniper"); + precacheModel("head_allies_seal_udt_sniper"); + precacheModel("viewhands_sniper_udt"); +} \ No newline at end of file diff --git a/character/mp_character_tf141_arctic_riot.gsc b/character/mp_character_tf141_arctic_riot.gsc new file mode 100644 index 0000000..abd73fb --- /dev/null +++ b/character/mp_character_tf141_arctic_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_tf141_arctic"); self attach("head_riot_tf141_arctic", "", true); self.headModel = "head_riot_tf141_arctic"; self setViewmodel("viewhands_arctic"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_riot_tf141_arctic"); precacheModel("head_riot_tf141_arctic"); precacheModel("viewhands_arctic");} \ No newline at end of file diff --git a/character/mp_character_tf141_arctic_sniper.gsc b/character/mp_character_tf141_arctic_sniper.gsc new file mode 100644 index 0000000..0c76a02 --- /dev/null +++ b/character/mp_character_tf141_arctic_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_arctic_sniper"); self attach("head_allies_tf141_arctic_sniper", "", true); self.headModel = "head_allies_tf141_arctic_sniper"; self setViewmodel("viewhands_sniper_tf141_arctic"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_arctic_sniper"); precacheModel("head_allies_tf141_arctic_sniper"); precacheModel("viewhands_sniper_tf141_arctic");} diff --git a/character/mp_character_tf141_desert_riot.gsc b/character/mp_character_tf141_desert_riot.gsc new file mode 100644 index 0000000..8f33f9c --- /dev/null +++ b/character/mp_character_tf141_desert_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_tf141_desert"); self attach("head_riot_tf141_desert", "", true); self.headModel = "head_riot_tf141_desert"; self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_riot_tf141_desert"); precacheModel("head_riot_tf141_desert"); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf141_desert_sniper.gsc b/character/mp_character_tf141_desert_sniper.gsc new file mode 100644 index 0000000..49546f1 --- /dev/null +++ b/character/mp_character_tf141_desert_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_desert_sniper"); self attach("head_allies_tf141_desert_sniper", "", true); self.headModel = "head_allies_tf141_desert_sniper"; self setViewmodel("viewhands_sniper_tf141_desert"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_desert_sniper"); precacheModel("head_allies_tf141_desert_sniper"); precacheModel("viewhands_sniper_tf141_desert");} \ No newline at end of file diff --git a/character/mp_character_tf141_forest_riot.gsc b/character/mp_character_tf141_forest_riot.gsc new file mode 100644 index 0000000..5232611 --- /dev/null +++ b/character/mp_character_tf141_forest_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_tf141_forest"); self attach("head_riot_tf141_forest", "", true); self.headModel = "head_riot_tf141_forest"; self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_riot_tf141_forest"); precacheModel("head_riot_tf141_forest"); precacheModel("viewhands_tf141");} diff --git a/character/mp_character_tf141_forest_sniper.gsc b/character/mp_character_tf141_forest_sniper.gsc new file mode 100644 index 0000000..c6427f7 --- /dev/null +++ b/character/mp_character_tf141_forest_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_forest_sniper"); self attach("head_allies_tf141_forest_sniper", "", true); self.headModel = "head_allies_tf141_forest_sniper"; self setViewmodel("viewhands_sniper_tf141_forest"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_forest_sniper"); precacheModel("head_allies_tf141_forest_sniper"); precacheModel("viewhands_sniper_tf141_forest");} \ No newline at end of file diff --git a/character/mp_character_tf_141_arctic_assault_a.gsc b/character/mp_character_tf_141_arctic_assault_a.gsc new file mode 100644 index 0000000..f06cdf7 --- /dev/null +++ b/character/mp_character_tf_141_arctic_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_assault_a"); codescripts\character::attachHead( "alias_tf141_heads_arctic", xmodelalias\alias_tf141_heads_arctic::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_arctic::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_arctic_assault_b.gsc b/character/mp_character_tf_141_arctic_assault_b.gsc new file mode 100644 index 0000000..ba8ae0a --- /dev/null +++ b/character/mp_character_tf_141_arctic_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_assault_b"); codescripts\character::attachHead( "alias_tf141_heads_arctic", xmodelalias\alias_tf141_heads_arctic::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_arctic::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_arctic_lmg.gsc b/character/mp_character_tf_141_arctic_lmg.gsc new file mode 100644 index 0000000..0fabab3 --- /dev/null +++ b/character/mp_character_tf_141_arctic_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_lmg"); codescripts\character::attachHead( "alias_tf141_heads_arctic", xmodelalias\alias_tf141_heads_arctic::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_arctic::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_arctic_shotgun.gsc b/character/mp_character_tf_141_arctic_shotgun.gsc new file mode 100644 index 0000000..ac5fd14 --- /dev/null +++ b/character/mp_character_tf_141_arctic_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_shotgun"); codescripts\character::attachHead( "alias_tf141_heads_arctic", xmodelalias\alias_tf141_heads_arctic::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_arctic::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_arctic_smg.gsc b/character/mp_character_tf_141_arctic_smg.gsc new file mode 100644 index 0000000..75d7b71 --- /dev/null +++ b/character/mp_character_tf_141_arctic_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_tf141_smg"); codescripts\character::attachHead( "alias_tf141_heads_arctic", xmodelalias\alias_tf141_heads_arctic::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_tf141_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_arctic::main()); precacheModel("viewhands_tf141");} diff --git a/character/mp_character_tf_141_desert_assault_a.gsc b/character/mp_character_tf_141_desert_assault_a.gsc new file mode 100644 index 0000000..ef11bb6 --- /dev/null +++ b/character/mp_character_tf_141_desert_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_desert_tf141_assault_a"); codescripts\character::attachHead( "alias_tf141_heads_desert", xmodelalias\alias_tf141_heads_desert::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_desert_tf141_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_desert::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_desert_assault_b.gsc b/character/mp_character_tf_141_desert_assault_b.gsc new file mode 100644 index 0000000..454a320 --- /dev/null +++ b/character/mp_character_tf_141_desert_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_desert_tf141_assault_b"); codescripts\character::attachHead( "alias_tf141_heads_desert", xmodelalias\alias_tf141_heads_desert::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_desert_tf141_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_desert::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_desert_lmg.gsc b/character/mp_character_tf_141_desert_lmg.gsc new file mode 100644 index 0000000..3362d91 --- /dev/null +++ b/character/mp_character_tf_141_desert_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_desert_tf141_lmg"); codescripts\character::attachHead( "alias_tf141_heads_desert", xmodelalias\alias_tf141_heads_desert::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_desert_tf141_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_desert::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_desert_shotgun.gsc b/character/mp_character_tf_141_desert_shotgun.gsc new file mode 100644 index 0000000..56f4acc --- /dev/null +++ b/character/mp_character_tf_141_desert_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_desert_tf141_shotgun"); codescripts\character::attachHead( "alias_tf141_heads_desert", xmodelalias\alias_tf141_heads_desert::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_desert_tf141_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_desert::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_desert_smg.gsc b/character/mp_character_tf_141_desert_smg.gsc new file mode 100644 index 0000000..61a3b8e --- /dev/null +++ b/character/mp_character_tf_141_desert_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_desert_tf141_smg"); codescripts\character::attachHead( "alias_tf141_heads_desert", xmodelalias\alias_tf141_heads_desert::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_desert_tf141_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_desert::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_forest_assault_a.gsc b/character/mp_character_tf_141_forest_assault_a.gsc new file mode 100644 index 0000000..5801c4c --- /dev/null +++ b/character/mp_character_tf_141_forest_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_forest_tf141_assault_a"); codescripts\character::attachHead( "alias_tf141_heads_forest", xmodelalias\alias_tf141_heads_forest::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_forest_tf141_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_forest::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_forest_assault_b.gsc b/character/mp_character_tf_141_forest_assault_b.gsc new file mode 100644 index 0000000..7d1ddcf --- /dev/null +++ b/character/mp_character_tf_141_forest_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_forest_tf141_assault_b"); codescripts\character::attachHead( "alias_tf141_heads_forest", xmodelalias\alias_tf141_heads_forest::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_forest_tf141_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_forest::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_forest_lmg.gsc b/character/mp_character_tf_141_forest_lmg.gsc new file mode 100644 index 0000000..7cd7ea8 --- /dev/null +++ b/character/mp_character_tf_141_forest_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_forest_tf141_lmg"); codescripts\character::attachHead( "alias_tf141_heads_forest", xmodelalias\alias_tf141_heads_forest::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_forest_tf141_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_forest::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_forest_shotgun.gsc b/character/mp_character_tf_141_forest_shotgun.gsc new file mode 100644 index 0000000..7b2b280 --- /dev/null +++ b/character/mp_character_tf_141_forest_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_forest_tf141_shotgun"); codescripts\character::attachHead( "alias_tf141_heads_forest", xmodelalias\alias_tf141_heads_forest::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_forest_tf141_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_forest::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_tf_141_forest_smg.gsc b/character/mp_character_tf_141_forest_smg.gsc new file mode 100644 index 0000000..6c072dd --- /dev/null +++ b/character/mp_character_tf_141_forest_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_forest_tf141_smg"); codescripts\character::attachHead( "alias_tf141_heads_forest", xmodelalias\alias_tf141_heads_forest::main() ); self setViewmodel("viewhands_tf141"); self.voice = "taskforce";}precache(){ precacheModel("mp_body_forest_tf141_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_tf141_heads_forest::main()); precacheModel("viewhands_tf141");} \ No newline at end of file diff --git a/character/mp_character_udt_riot.gsc b/character/mp_character_udt_riot.gsc new file mode 100644 index 0000000..18d7563 --- /dev/null +++ b/character/mp_character_udt_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_riot_udt"); self attach("head_riot_udt", "", true); self.headModel = "head_riot_udt"; self setViewmodel("viewhands_udt"); self.voice = "seal";}precache(){ precacheModel("mp_body_riot_udt"); precacheModel("head_riot_udt"); precacheModel("viewhands_udt");} diff --git a/character/mp_character_us_army_assault_a.gsc b/character/mp_character_us_army_assault_a.gsc new file mode 100644 index 0000000..adfdffd --- /dev/null +++ b/character/mp_character_us_army_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_assault_a"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_assault_b.gsc b/character/mp_character_us_army_assault_b.gsc new file mode 100644 index 0000000..f1599a7 --- /dev/null +++ b/character/mp_character_us_army_assault_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_assault_b"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_assault_b"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_assault_c.gsc b/character/mp_character_us_army_assault_c.gsc new file mode 100644 index 0000000..1ac2af4 --- /dev/null +++ b/character/mp_character_us_army_assault_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_assault_c"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_assault_c"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_lmg.gsc b/character/mp_character_us_army_lmg.gsc new file mode 100644 index 0000000..abc9ef3 --- /dev/null +++ b/character/mp_character_us_army_lmg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_lmg"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_lmg"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_lmg_b.gsc b/character/mp_character_us_army_lmg_b.gsc new file mode 100644 index 0000000..d36af24 --- /dev/null +++ b/character/mp_character_us_army_lmg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_lmg_b"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_lmg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} diff --git a/character/mp_character_us_army_lmg_c.gsc b/character/mp_character_us_army_lmg_c.gsc new file mode 100644 index 0000000..9de9696 --- /dev/null +++ b/character/mp_character_us_army_lmg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_lmg_c"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_lmg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_riot.gsc b/character/mp_character_us_army_riot.gsc new file mode 100644 index 0000000..b3ad878 --- /dev/null +++ b/character/mp_character_us_army_riot.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_riot"); codescripts\character::attachHead( "alias_us_army_riot", xmodelalias\alias_us_army_riot::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_riot"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_riot::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_shotgun.gsc b/character/mp_character_us_army_shotgun.gsc new file mode 100644 index 0000000..5343420 --- /dev/null +++ b/character/mp_character_us_army_shotgun.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_shotgun"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_shotgun"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_shotgun_b.gsc b/character/mp_character_us_army_shotgun_b.gsc new file mode 100644 index 0000000..dbba7f2 --- /dev/null +++ b/character/mp_character_us_army_shotgun_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_shotgun_b"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_shotgun_b"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_shotgun_c.gsc b/character/mp_character_us_army_shotgun_c.gsc new file mode 100644 index 0000000..1a5ed19 --- /dev/null +++ b/character/mp_character_us_army_shotgun_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_shotgun_c"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_shotgun_c"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_smg.gsc b/character/mp_character_us_army_smg.gsc new file mode 100644 index 0000000..dc8d71b --- /dev/null +++ b/character/mp_character_us_army_smg.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_smg"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_smg"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_smg_b.gsc b/character/mp_character_us_army_smg_b.gsc new file mode 100644 index 0000000..95d7eaf --- /dev/null +++ b/character/mp_character_us_army_smg_b.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_smg_b"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_smg_b"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_smg_c.gsc b/character/mp_character_us_army_smg_c.gsc new file mode 100644 index 0000000..1e81402 --- /dev/null +++ b/character/mp_character_us_army_smg_c.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_us_army_smg_c"); codescripts\character::attachHead( "alias_us_army_heads", xmodelalias\alias_us_army_heads::main() ); self setViewmodel("viewhands_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_us_army_smg_c"); codescripts\character::precacheModelArray(xmodelalias\alias_us_army_heads::main()); precacheModel("viewhands_us_army");} \ No newline at end of file diff --git a/character/mp_character_us_army_sniper.gsc b/character/mp_character_us_army_sniper.gsc new file mode 100644 index 0000000..a1cac37 --- /dev/null +++ b/character/mp_character_us_army_sniper.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_body_army_sniper"); self attach("head_allies_us_army_sniper", "", true); self.headModel = "head_allies_us_army_sniper"; self setViewmodel("viewhands_sniper_us_army"); self.voice = "american";}precache(){ precacheModel("mp_body_army_sniper"); precacheModel("head_allies_us_army_sniper"); precacheModel("viewhands_sniper_us_army");} diff --git a/character/mp_nx_character_china_assault_a.gsc b/character/mp_nx_character_china_assault_a.gsc new file mode 100644 index 0000000..e21cad8 --- /dev/null +++ b/character/mp_nx_character_china_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_china_army_body_assault_a"); codescripts\character::attachHead( "alias_nx_china_army_heads", xmodelalias\alias_nx_china_army_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "arab";}precache(){ precacheModel("mp_china_army_body_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_nx_china_army_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_china_pres_assault_a.gsc b/character/mp_nx_character_china_pres_assault_a.gsc new file mode 100644 index 0000000..a016af8 --- /dev/null +++ b/character/mp_nx_character_china_pres_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_china_space_assault_body"); codescripts\character::attachHead( "alias_nx_china_pres_heads", xmodelalias\alias_nx_china_pres_heads::main() ); self setViewmodel("viewhands_chinese_lunar"); self.voice = "american";}precache(){ precacheModel("mp_nx_china_space_assault_body"); codescripts\character::precacheModelArray(xmodelalias\alias_nx_china_pres_heads::main()); precacheModel("viewhands_chinese_lunar");} diff --git a/character/mp_nx_character_china_space_assault_a.gsc b/character/mp_nx_character_china_space_assault_a.gsc new file mode 100644 index 0000000..5f994aa --- /dev/null +++ b/character/mp_nx_character_china_space_assault_a.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_nx_china_space_assault_body"); + self attach("mp_nx_china_space_assault_head", "", true); + self.headModel = "mp_nx_china_space_assault_head"; + self setViewmodel("viewhands_chinese_lunar"); + self.voice = "american"; +} +precache() +{ + precacheModel("mp_nx_china_space_assault_body"); + precacheModel("mp_nx_china_space_assault_head"); + precacheModel("viewhands_chinese_lunar"); +} \ No newline at end of file diff --git a/character/mp_nx_character_china_spec_assault_a.gsc b/character/mp_nx_character_china_spec_assault_a.gsc new file mode 100644 index 0000000..84c2dd8 --- /dev/null +++ b/character/mp_nx_character_china_spec_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_china_specops_body_assault_a"); codescripts\character::attachHead( "alias_nx_china_specops_heads", xmodelalias\alias_nx_china_specops_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_china_specops_body_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_nx_china_specops_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_ec_hardline_a.gsc b/character/mp_nx_character_ec_hardline_a.gsc new file mode 100644 index 0000000..86084bd --- /dev/null +++ b/character/mp_nx_character_ec_hardline_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_ec_hardline_body"); codescripts\character::attachHead( "alias_mp_nx_ec_hardline_heads", xmodelalias\alias_mp_nx_ec_hardline_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_ec_hardline_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_ec_hardline_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_ec_hulc_a.gsc b/character/mp_nx_character_ec_hulc_a.gsc new file mode 100644 index 0000000..44b1304 --- /dev/null +++ b/character/mp_nx_character_ec_hulc_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_ec_hulc_body"); codescripts\character::attachHead( "alias_mp_nx_ec_hulc_heads", xmodelalias\alias_mp_nx_ec_hulc_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_ec_hulc_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_ec_hulc_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_ec_marathon_a.gsc b/character/mp_nx_character_ec_marathon_a.gsc new file mode 100644 index 0000000..f694845 --- /dev/null +++ b/character/mp_nx_character_ec_marathon_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_ec_marathon_body"); codescripts\character::attachHead( "alias_mp_nx_ec_marathon_heads", xmodelalias\alias_mp_nx_ec_marathon_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_ec_marathon_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_ec_marathon_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_ec_ninja_a.gsc b/character/mp_nx_character_ec_ninja_a.gsc new file mode 100644 index 0000000..2981409 --- /dev/null +++ b/character/mp_nx_character_ec_ninja_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_ec_ninja_body"); codescripts\character::attachHead( "alias_mp_nx_ec_ninja_heads", xmodelalias\alias_mp_nx_ec_ninja_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_ec_ninja_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_ec_ninja_heads::main()); precacheModel("viewhands_us_specops");} \ No newline at end of file diff --git a/character/mp_nx_character_ec_trophy_a.gsc b/character/mp_nx_character_ec_trophy_a.gsc new file mode 100644 index 0000000..43fd3e7 --- /dev/null +++ b/character/mp_nx_character_ec_trophy_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_ec_trophy_body"); codescripts\character::attachHead( "alias_mp_nx_ec_trophy_heads", xmodelalias\alias_mp_nx_ec_trophy_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_ec_trophy_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_ec_trophy_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_us_army_assault_a.gsc b/character/mp_nx_character_us_army_assault_a.gsc new file mode 100644 index 0000000..3ed083a --- /dev/null +++ b/character/mp_nx_character_us_army_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ codescripts\character::setModelFromArray(xmodelalias\alias_mp_nx_us_army_bodies::main()); codescripts\character::attachHead( "alias_nx_us_army_heads", xmodelalias\alias_nx_us_army_heads::main() ); self setViewmodel("viewhands_nx_us_army"); self.voice = "american";}precache(){ codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_army_bodies::main()); codescripts\character::precacheModelArray(xmodelalias\alias_nx_us_army_heads::main()); precacheModel("viewhands_nx_us_army");} diff --git a/character/mp_nx_character_us_hardline_a.gsc b/character/mp_nx_character_us_hardline_a.gsc new file mode 100644 index 0000000..0c9bac4 --- /dev/null +++ b/character/mp_nx_character_us_hardline_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_hardline_body"); codescripts\character::attachHead( "alias_mp_nx_us_hardline_heads", xmodelalias\alias_mp_nx_us_hardline_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_hardline_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_hardline_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_us_hulc_a.gsc b/character/mp_nx_character_us_hulc_a.gsc new file mode 100644 index 0000000..4c15bce --- /dev/null +++ b/character/mp_nx_character_us_hulc_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_hulc_body"); codescripts\character::attachHead( "alias_mp_nx_us_hulc_heads", xmodelalias\alias_mp_nx_us_hulc_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_hulc_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_hulc_heads::main()); precacheModel("viewhands_us_specops");} \ No newline at end of file diff --git a/character/mp_nx_character_us_marathon_a.gsc b/character/mp_nx_character_us_marathon_a.gsc new file mode 100644 index 0000000..b9bddd7 --- /dev/null +++ b/character/mp_nx_character_us_marathon_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_marathon_body"); codescripts\character::attachHead( "alias_mp_nx_us_marathon_heads", xmodelalias\alias_mp_nx_us_marathon_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_marathon_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_marathon_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_us_ninja_a.gsc b/character/mp_nx_character_us_ninja_a.gsc new file mode 100644 index 0000000..592db98 --- /dev/null +++ b/character/mp_nx_character_us_ninja_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_ninja_body"); codescripts\character::attachHead( "alias_mp_nx_us_ninja_heads", xmodelalias\alias_mp_nx_us_ninja_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_ninja_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_ninja_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_us_pres_assault_a.gsc b/character/mp_nx_character_us_pres_assault_a.gsc new file mode 100644 index 0000000..3a33964 --- /dev/null +++ b/character/mp_nx_character_us_pres_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_space_assault_body"); codescripts\character::attachHead( "alias_nx_us_pres_heads", xmodelalias\alias_nx_us_pres_heads::main() ); self setViewmodel("viewhands_us_lunar"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_space_assault_body"); codescripts\character::precacheModelArray(xmodelalias\alias_nx_us_pres_heads::main()); precacheModel("viewhands_us_lunar");} \ No newline at end of file diff --git a/character/mp_nx_character_us_secretservice_a.gsc b/character/mp_nx_character_us_secretservice_a.gsc new file mode 100644 index 0000000..d629626 --- /dev/null +++ b/character/mp_nx_character_us_secretservice_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ codescripts\character::setModelFromArray(xmodelalias\alias_mp_nx_us_secretservice_bodies::main()); codescripts\character::attachHead( "alias_mp_nx_us_secretservice_heads", xmodelalias\alias_mp_nx_us_secretservice_heads::main() ); self setViewmodel("viewhands_airport"); self.voice = "american";}precache(){ codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_secretservice_bodies::main()); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_secretservice_heads::main()); precacheModel("viewhands_airport");} diff --git a/character/mp_nx_character_us_space_assault_a.gsc b/character/mp_nx_character_us_space_assault_a.gsc new file mode 100644 index 0000000..6c0c89e --- /dev/null +++ b/character/mp_nx_character_us_space_assault_a.gsc @@ -0,0 +1,15 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main() +{ + self setModel("mp_nx_us_space_assault_body"); + self attach("mp_nx_us_space_assault_head", "", true); + self.headModel = "mp_nx_us_space_assault_head"; + self setViewmodel("viewhands_us_lunar"); + self.voice = "american"; +} +precache() +{ + precacheModel("mp_nx_us_space_assault_body"); + precacheModel("mp_nx_us_space_assault_head"); + precacheModel("viewhands_us_lunar"); +} \ No newline at end of file diff --git a/character/mp_nx_character_us_specops_assault_a.gsc b/character/mp_nx_character_us_specops_assault_a.gsc new file mode 100644 index 0000000..a430095 --- /dev/null +++ b/character/mp_nx_character_us_specops_assault_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_specops_body_assault_a"); codescripts\character::attachHead( "alias_nx_us_specops_heads", xmodelalias\alias_nx_us_specops_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_specops_body_assault_a"); codescripts\character::precacheModelArray(xmodelalias\alias_nx_us_specops_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/character/mp_nx_character_us_trophy_a.gsc b/character/mp_nx_character_us_trophy_a.gsc new file mode 100644 index 0000000..12cd9e9 --- /dev/null +++ b/character/mp_nx_character_us_trophy_a.gsc @@ -0,0 +1,2 @@ +// THIS FILE IS AUTOGENERATED, DO NOT MODIFY +main(){ self setModel("mp_nx_us_trophy_body"); codescripts\character::attachHead( "alias_mp_nx_us_trophy_heads", xmodelalias\alias_mp_nx_us_trophy_heads::main() ); self setViewmodel("viewhands_us_specops"); self.voice = "american";}precache(){ precacheModel("mp_nx_us_trophy_body"); codescripts\character::precacheModelArray(xmodelalias\alias_mp_nx_us_trophy_heads::main()); precacheModel("viewhands_us_specops");} diff --git a/codescripts/character.gsc b/codescripts/character.gsc new file mode 100644 index 0000000..987a435 --- /dev/null +++ b/codescripts/character.gsc @@ -0,0 +1,4 @@ +gscsetModelFromArray( a ) +{ + self setModel( a[ randomint( a.size ) ] ); +} \ No newline at end of file diff --git a/codescripts/delete.gsc b/codescripts/delete.gsc new file mode 100644 index 0000000..0bcbb74 --- /dev/null +++ b/codescripts/delete.gsc @@ -0,0 +1,7 @@ +main() +{ + assert(isdefined(self)); + wait 0; + if (isdefined(self)) + self delete(); +} \ No newline at end of file diff --git a/codescripts/struct.gsc b/codescripts/struct.gsc new file mode 100644 index 0000000..1d53c04 --- /dev/null +++ b/codescripts/struct.gsc @@ -0,0 +1,23 @@ +InitStructs() +{ + level._struct = []; +} + +CreateStruct() +{ + struct = spawnstruct(); + level._struct[level._struct.size] = struct; + return struct; +} + +FindStruct( position ) +{ + for( i = 0; i < level._struct.size; i++ ) + { + if( DistanceSquared( level._struct[i].origin, position ) < 1 ) + { + return level._struct[i]; + } + } + return undefined; +} \ No newline at end of file diff --git a/common_scripts/_artcommon.gsc b/common_scripts/_artcommon.gsc new file mode 100644 index 0000000..f60ed63 --- /dev/null +++ b/common_scripts/_artcommon.gsc @@ -0,0 +1,171 @@ +#include common_scripts\utility; + +artStartVisionFileExport() +{ + fileprint_launcher_start_file(); +} + +artEndVisionFileExport() +{ + return fileprint_launcher_end_file( "\\share\\raw\\vision\\"+level._script+ ".vision", true ); +} + +artStartFogFileExport() +{ + fileprint_launcher_start_file(); + +} + +artEndFogFileExport() +{ + return fileprint_launcher_end_file( "\\share\\raw\\maps\\createart\\"+level._script+ "_art.gsc", true ); +} + +artCommonfxprintln( string ) +{ + fileprint_launcher( string ); +} + + +setfogsliders() +{ + /# + fogcolor = getdvarvector( "g_fogColorReadOnly" ); + maxOpacity = GetDvar( "g_fogMaxOpacityReadOnly" ); + halfplane = GetDvar( "g_fogHalfDistReadOnly" ); + nearplane = GetDvar( "g_fogStartDistReadOnly" ); + + sunFogEnabled = GetDvar( "g_sunFogEnabledReadOnly" ); + sunFogColor = getdvarvector( "g_sunFogColorReadOnly" ); + sunFogDir = getdvarvector( "g_sunFogDirReadOnly" ); + sunFogBeginFadeAngle = GetDvar( "g_sunFogBeginFadeAngleReadOnly" ); + sunFogEndFadeAngle = GetDvar( "g_sunFogEndFadeAngleReadOnly" ); + sunFogScale = GetDvar( "g_sunFogScaleReadOnly" ); + + mulFogBlend = GetDvar( "g_mulFogBlendReadOnly" ); + mulFogNearColor = GetDvar( "g_mulFogNearColorReadOnly" ); + mulFogFarColor = GetDvar( "g_mulFogFarColorReadOnly" ); + + if ( !isdefined( mulFogBlend ) + || !isdefined( mulFogNearColor ) + || !isdefined( mulFogFarColor ) + ) + { + mulFogBlend = 0.0; + mulFogNearColor = ( 1, 1, 1 ); + mulFogFarColor = ( 1, 1, 1 ); + } + + if ( !isdefined( fogcolor ) + || !isdefined( maxOpacity ) + || !isdefined( halfplane ) + || !isdefined( nearplane ) + || !isdefined( sunFogEnabled ) + || !isdefined( sunFogColor ) + || !isdefined( sunFogDir ) + || !isdefined( sunFogBeginFadeAngle ) + || !isdefined( sunFogEndFadeAngle ) + || !isdefined( sunFogScale ) + ) + { + fogcolor = ( 1, 1, 1 ); + halfplane = 10000001; + nearplane = 10000000; + maxOpacity = 1; + + sunFogEnabled = false; + sunFogColor = ( 1, 1, 1 ); + sunFogDir = ( 1.0, 0.0, 0.0 ); + sunFogBeginFadeAngle = GetDvar( "g_sunFogBeginFadeAngle" ); + sunFogEndFadeAngle = GetDvar( "g_sunFogEndFadeAngle" ); + sunFogScale = GetDvar( "g_sunFogScaleReadOnly" ); + + } + + SetDevDvar( "scr_fog_exp_halfplane", halfplane ); + SetDevDvar( "scr_fog_nearplane", nearplane ); + SetDevDvar( "scr_fog_color", fogcolor ); + SetDevDvar( "scr_fog_max_opacity", maxOpacity ); + + SetDevDvar( "scr_sunFogEnabled", sunFogEnabled ); + SetDevDvar( "scr_sunFogColor", sunFogColor ); + SetDevDvar( "scr_sunFogDir", sunFogDir ); + SetDevDvar( "scr_sunFogBeginFadeAngle", sunFogBeginFadeAngle ); + SetDevDvar( "scr_sunFogEndFadeAngle", sunFogEndFadeAngle ); + SetDevDvar( "scr_sunFogScale", sunFogScale ); + + SetDevDvar( "scr_mulFogBlend", mulFogBlend ); + SetDevDvar( "scr_mulFogNearColor", mulFogNearColor ); + SetDevDvar( "scr_mulFogFarColor", mulFogFarColor ); + #/ +} + + +translateFogSlidersToScript() +{ + level._fogexphalfplane = GetDvarFloat( "scr_fog_exp_halfplane" ); + level._fognearplane = GetDvarFloat( "scr_fog_nearplane" ); + level._fogcolor = getdvarvector( "scr_fog_color" ); + level._fogmaxopacity = GetDvarFloat( "scr_fog_max_opacity" ); + + level._sunFogEnabled = GetDvarInt( "scr_sunFogEnabled" ); + level._sunFogColor = getdvarvector( "scr_sunFogColor" ); + level._sunFogDir = getdvarvector( "scr_sunFogDir" ); + level._sunFogBeginFadeAngle = GetDvarFloat( "scr_sunFogBeginFadeAngle" ); + level._sunFogEndFadeAngle = GetDvarFloat( "scr_sunFogEndFadeAngle" ); + level._sunFogScale = GetDvarFloat( "scr_sunFogScale" ); + + level._mulFogBlend = GetDvarFloat( "scr_mulFogBlend" ); + level._mulFogNearColor = getdvarvector( "scr_mulFogNearColor" ); + level._mulFogFarColor = getdvarvector( "scr_mulFogFarColor" ); +} + + +updateFogFromScript() +{ + /# + if ( GetDvarInt( "scr_cmd_plr_sun" ) ) + { + SetDevDvar( "scr_sunFogDir", AnglesToForward( level._player GetPlayerAngles() ) ); + SetDevDvar( "scr_cmd_plr_sun", 0 ); + } + + #/ + + if ( ! GetDvarInt( "scr_fog_disable" ) ) + { + if ( level._sunFogEnabled ) + SetExpFog( level._fognearplane, level._fogexphalfplane, level._fogcolor[ 0 ], level._fogcolor[ 1 ], level._fogcolor[ 2 ], level._fogmaxopacity, 0, + level._mulFogBlend, 0, level._mulFogNearColor[ 0 ], level._mulFogNearColor[ 1 ], level._mulFogNearColor[ 2 ], level._mulFogFarColor[ 0 ], level._mulFogFarColor[ 1 ], level._mulFogFarColor[ 2 ], + level._sunFogColor[ 0 ], level._sunFogColor[ 1 ], level._sunFogColor[ 2 ], level._sunFogDir, level._sunFogBeginFadeAngle, level._sunFogEndFadeAngle, level._sunFogScale ); + else + SetExpFog( level._fognearplane, level._fogexphalfplane, level._fogcolor[ 0 ], level._fogcolor[ 1 ], level._fogcolor[ 2 ], level._fogmaxopacity, 0, + level._mulFogBlend, 0, level._mulFogNearColor[ 0 ], level._mulFogNearColor[ 1 ], level._mulFogNearColor[ 2 ], level._mulFogFarColor[ 0 ], level._mulFogFarColor[ 1 ], level._mulFogFarColor[ 2 ] ); + } + else + { + SetExpFog( 1000000000, 1000000001, 0, 0, 0, 0, 0 );// couldn't find discreet fog disabling other than to never set it in the first place + } +} + + +artfxprintlnFog() +{ + fileprint_launcher( "" ); + fileprint_launcher( "\t//* Fog section * " ); + fileprint_launcher( "" ); + + fileprint_launcher( "\tsetDevDvar( \"scr_fog_disable\"" + ", " + "\"" + GetDvarInt( "scr_fog_disable" ) + "\"" + " );" ); + + fileprint_launcher( "" ); + if ( ! GetDvarInt( "scr_fog_disable" ) ) + { + if ( level._sunFogEnabled ) + fileprint_launcher( "\tsetExpFog( " + level._fognearplane + ", " + level._fogexphalfplane + ", " + level._fogcolor[0] + ", " + level._fogcolor[1] + ", " + level._fogcolor[2] + ", " + level._fogmaxopacity + ", 0, " + + level._mulFogBlend + ", 0, " + level._mulFogNearColor[0] + ", " + level._mulFogNearColor[1] + ", " + level._mulFogNearColor[2] + ", " + level._mulFogFarColor[0] + ", " + level._mulFogFarColor[1] + ", " + level._mulFogFarColor[2] + ", " + + level._sunFogColor[0] + ", " + level._sunFogColor[1] + ", " + level._sunFogColor[2] + ", (" + level._sunFogDir[0] + ", " + level._sunFogDir[1] + ", " + level._sunFogDir[2] + "), " + level._sunFogBeginFadeAngle + ", " + level._sunFogEndFadeAngle + ", " + level._sunFogScale + " );" ); + else + fileprint_launcher( "\tsetExpFog( " + level._fognearplane + ", " + level._fogexphalfplane + ", " + level._fogcolor[0] + ", " + level._fogcolor[1] + ", " + level._fogcolor[2] + ", " + level._fogmaxopacity + ", 0, " + + level._mulFogBlend + ", 0, " + level._mulFogNearColor[0] + ", " + level._mulFogNearColor[1] + ", " + level._mulFogNearColor[2] + ", " + level._mulFogFarColor[0] + ", " + level._mulFogFarColor[1] + ", " + level._mulFogFarColor[2] + ");" ); + } +} \ No newline at end of file diff --git a/common_scripts/_createfx.gsc b/common_scripts/_createfx.gsc new file mode 100644 index 0000000..b5c19c8 --- /dev/null +++ b/common_scripts/_createfx.gsc @@ -0,0 +1,1981 @@ +#include common_scripts\utility; +#include common_scripts\_fx; +#include common_scripts\_createfxMenu; + +createEffect( type, fxid ) +{ + ent = spawnStruct(); + if ( !isdefined( level._createFXent ) ) + level._createFXent = []; + + level._createFXent[ level._createFXent.size ] = ent; + ent.v = []; + ent.v[ "type" ] = type; + ent.v[ "fxid" ] = fxid; + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "origin" ] = ( 0, 0, 0 ); + ent.drawn = true; + return ent; +} + +add_effect( name, effect ) +{ + if ( !isdefined( level._effect ) ) + level._effect = []; + + level._effect[ name ] = loadfx( effect ); +} + +createLoopSound() +{ + ent = spawnStruct(); + if ( !isdefined( level._createFXent ) ) + level._createFXent = []; + + level._createFXent[ level._createFXent.size ] = ent; + ent.v = []; + ent.v[ "type" ] = "soundfx"; + ent.v[ "fxid" ] = "No FX"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "origin" ] = ( 0, 0, 0 ); + ent.drawn = true; + return ent; +} + +createNewExploder() +{ + ent = spawnStruct(); + if ( !isdefined( level._createFXent ) ) + level._createFXent = []; + + level._createFXent[ level._createFXent.size ] = ent; + + ent.v = []; + ent.v[ "type" ] = "exploder"; + ent.v[ "fxid" ] = "No FX"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "origin" ] = ( 0, 0, 0 ); + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = 1; + ent.v[ "exploder_type" ] = "normal"; + ent.drawn = true; + + return ent; +} + +createOneShotEntity() +{ + ent = spawnStruct(); + if ( !isdefined( level._createFXent ) ) + level._createFXent = []; + + level._createFXent[ level._createFXent.size ] = ent; + + ent.v = []; + ent.v[ "type" ] = "oneshotfx"; + ent.v[ "fxid" ] = "No FX"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "origin" ] = ( 0, 0, 0 ); + ent.v[ "flag" ] = "nil"; + ent.drawn = true; + + return ent; +} + +set_forward_and_up_vectors() +{ + self.v[ "up" ] = anglestoup( self.v[ "angles" ] ); + self.v[ "forward" ] = anglestoforward( self.v[ "angles" ] ); +} + +createfx_common() +{ + precacheShader( "black" ); + + if( level._mp_createfx ) + { + hack_start( "painter_mp" ); + } + else + { + hack_start( "painter" ); + } + + flag_init( "createfx_saving" ); + + // Effects placing tool + if ( !isdefined( level._createFX ) ) + { + level._createFX = []; + } + + level._createfx_loopcounter = 0; + + triggers = getentarray( "trigger_multiple", "classname" ); + for ( i = 0;i < triggers.size;i++ ) + { + triggers[ i ] delete(); + } + + triggers = getentarray( "trigger_radius", "classname" ); + for ( i = 0;i < triggers.size;i++ ) + { + triggers[ i ] delete(); + } +} + +createFxLogic() +{ + waittillframeend;// let _load run first + + menu_init(); + + if ( !isdefined( level._effect ) ) + level._effect = []; + + if ( GetDvar( "createfx_map" ) == "" ) + SetDevDvar( "createfx_map", level._script ); + else if ( GetDvar( "createfx_map" ) == level._script ) + [[ level._func_position_player ]](); + + // restore player position & orientation + level._player restore_for_createfx(); + + level._createFxHudElements = []; + level._createFx_hudElements = 30; + // all this offset stuff lets us duplicate the text which puts an outline around + // it and makes it more legible + strOffsetX = []; + strOffsetY = []; + strOffsetX[ 0 ] = 0; + strOffsetY[ 0 ] = 0; + strOffsetX[ 1 ] = 1; + strOffsetY[ 1 ] = 1; + strOffsetX[ 2 ] = -2; + strOffsetY[ 2 ] = 1; + strOffsetX[ 3 ] = 1; + strOffsetY[ 3 ] = -1; + strOffsetX[ 4 ] = -2; + strOffsetY[ 4 ] = -1; + + SetDevDvar( "fx", "nil" ); + + // setup "crosshair" + crossHair = newHudElem(); + crossHair.location = 0; + crossHair.alignX = "center"; + crossHair.alignY = "middle"; + crossHair.foreground = 1; + crossHair.fontScale = 2; + crossHair.sort = 20; + crossHair.alpha = 1; + crossHair.x = 320; + crossHair.y = 233; + crossHair setText( "." ); + + // setup the free text marker to allow some permanent strings + level._clearTextMarker = newHudElem(); + level._clearTextMarker.alpha = 0; + level._clearTextMarker setText( "marker" ); + + for ( i = 0; i < level._createFx_hudElements; i++ ) + { + newStrArray = []; + + for ( p = 0; p < 1; p++ ) + { + newStr = newHudElem(); + newStr.alignX = "left"; + newStr.location = 0; + newStr.foreground = 1; + newStr.fontScale = 1.40; + newStr.alpha = 1; + newStr.archived = 0; + newStr.x = 0 + strOffsetX[ p ]; + newStr.y = 60 + strOffsetY[ p ] + i * 15; + newStr.sort = newStr.y; + //newStr.sort = 20 - p; + + if ( p > 0 ) + { + newStr.color = ( 0, 0, 0 ); + } + + newStrArray[ newStrArray.size ] = newStr; + } + + level._createFxHudElements[ i ] = newStrArray; + } + + newStrArray = []; + + for ( p = 0; p < 5; p++ ) + { + // setup instructional text + newStr = newHudElem(); + newStr.alignX = "center"; + newStr.location = 0; + newStr.foreground = 1; + newStr.fontScale = 1.40; + newStr.alpha = 1; + newStr.x = 320 + strOffsetX[ p ]; + newStr.y = 80 + strOffsetY[ p ]; + newStr.sort = newStr.y; + newStr.archived = 0; + // newStr.sort = 20 - p; + + if ( p > 0 ) + { + newStr.color = ( 0, 0, 0 ); + } + + newStrArray[ newStrArray.size ] = newStr; + } + + level._createFX_centerPrint = newStrArray; + + // gets cumulatively added to to create digital accelleration + level._selectedMove_up = 0; + level._selectedMove_forward = 0; + level._selectedMove_right = 0; + level._selectedRotate_pitch = 0; + level._selectedRotate_roll = 0; + level._selectedRotate_yaw = 0; + level._selected_fx = []; + level._selected_fx_ents = []; + + level._createfx_lockedList = []; + level._createfx_lockedList[ "escape" ] = true; + level._createfx_lockedList[ "BUTTON_LSHLDR" ] = true; + level._createfx_lockedList[ "BUTTON_RSHLDR" ] = true; + level._createfx_lockedList[ "mouse1" ] = true; + level._createfx_lockedList[ "ctrl" ] = true; + + level._createfx_draw_enabled = true; + level._last_displayed_ent = undefined; + + level._buttonIsHeld = []; + axisMode = false; + lastPlayerOrigin = (0,0,0); + + if( !level._mp_createfx ) + { + lastPlayerOrigin = level._player.origin; + } + + colors = []; + colors[ "loopfx" ][ "selected" ] = ( 1.0, 1.0, 0.2 ); + colors[ "loopfx" ][ "highlighted" ] = ( 0.4, 0.95, 1.0 ); + colors[ "loopfx" ][ "default" ] = ( 0.3, 0.8, 1.0 ); + + colors[ "oneshotfx" ][ "selected" ] = ( 1.0, 1.0, 0.2 ); + colors[ "oneshotfx" ][ "highlighted" ] = ( 0.4, 0.95, 1.0 ); + colors[ "oneshotfx" ][ "default" ] = ( 0.3, 0.8, 1.0 ); + + colors[ "exploder" ][ "selected" ] = ( 1.0, 1.0, 0.2 ); + colors[ "exploder" ][ "highlighted" ] = ( 1.0, 0.2, 0.2 ); + colors[ "exploder" ][ "default" ] = ( 1.0, 0.1, 0.1 ); + + colors[ "rainfx" ][ "selected" ] = ( 1.0, 1.0, 0.2 ); + colors[ "rainfx" ][ "highlighted" ] = ( .95, 0.4, 0.95 ); + colors[ "rainfx" ][ "default" ] = ( .78, 0.0, 0.73 ); + + colors[ "soundfx" ][ "selected" ] = ( 1.0, 1.0, 0.2 ); + colors[ "soundfx" ][ "highlighted" ] = ( .5, 1.0, 0.75 ); + colors[ "soundfx" ][ "default" ] = ( .2, 0.9, 0.2 ); + + lastHighlightedEnt = undefined; + level._fx_rotating = false; + setMenu( "none" ); + level._createfx_selecting = false; + + // black background for text + black = newHudElem(); + black.x = -120; + black.y = 200; + // black[i].alignX = "center"; + // black[i].alignY = "middle"; + black.foreground = 0; + black setShader( "black", 250, 160 ); + black.alpha = 0;// 0.6; + + level._createfx_inputlocked = false; + + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + ent post_entity_creation_function(); + } + + thread draw_distance(); + lastSelectEntity = undefined; + thread createfx_autosave(); + + for ( ;; ) + { + wait( 0.02 ); + + changedSelectedEnts = false; + + // calculate the "cursor" + right = anglestoright( level._player getplayerangles() ); + forward = anglestoforward( level._player getplayerangles() ); + up = anglestoup( level._player getplayerangles() ); + dot = 0.85; + + placeEnt_vector = vector_multiply( forward, 750 ); + level._createfxCursor = bullettrace( level._player geteye(), level._player geteye() + placeEnt_vector, false, undefined ); + highlightedEnt = undefined; + + // ************************************************************ + // + // General input + // + // ************************************************************ + + level._buttonClick = []; + level._button_is_kb = []; + process_button_held_and_clicked(); + ctrlHeld = button_is_held( "ctrl", "BUTTON_LSHLDR" ); + leftClick = button_is_clicked( "mouse1", "BUTTON_A" ); + leftHeld = button_is_held( "mouse1", "BUTTON_A" ); + + create_fx_menu(); + + if ( button_is_clicked( "shift", "BUTTON_X" ) ) + axisMode = !axisMode; + + //changing to allow devgui item + if ( button_is_clicked( "F5" ) ) + SetDevDvar( "scr_createfx_dump", 1 ); + + if( GetDvarInt( "scr_createfx_dump" ) ) + { + SetDevDvar( "scr_createfx_dump", 0 ); + generate_fx_log(); + } + + if ( button_is_clicked( "F2" ) ) + toggle_createfx_drawing(); + + if ( button_is_clicked( "ins" ) ) + insert_effect(); + + if ( button_is_clicked( "del" ) ) + delete_pressed(); + + if ( button_is_clicked( "end", "l" ) ) + { + drop_selection_to_ground(); + changedSelectedEnts = true; + } + + if ( button_is_clicked( "escape" ) ) + clear_settable_fx(); + + if ( button_is_clicked( "space" ) ) + set_off_exploders(); + + if ( button_is_clicked( "g" ) ) + { + select_all_exploders_of_currently_selected( "exploder" ); + select_all_exploders_of_currently_selected( "flag" ); + } + + if ( button_is_clicked( "tab", "BUTTON_RSHLDR" ) ) + { + move_selection_to_cursor(); + changedSelectedEnts = true; + } + + if ( button_is_held( "h", "F1" ) ) + { + show_help(); + //wait( 0.05 ); + continue; + } + + if ( button_is_clicked( "BUTTON_LSTICK" ) ) + copy_ents(); + if ( button_is_clicked( "BUTTON_RSTICK" ) ) + paste_ents(); + + if ( ctrlHeld ) + { + if ( button_is_clicked( "c" ) ) + copy_ents(); + + if ( button_is_clicked( "v" ) ) + paste_ents(); + } + + if ( isdefined( level._selected_fx_option_index ) ) + menu_fx_option_set(); + + // ************************************************************ + // + // Highlighted Entity Handling + // + // ************************************************************ + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + + difference = vectornormalize( ent.v[ "origin" ] - ( level._player.origin + ( 0, 0, 55 ) ) ); + newdot = vectordot( forward, difference ); + if ( newdot < dot ) + continue; + + dot = newdot; + highlightedEnt = ent; + } + level._fx_highLightedEnt = highLightedEnt; + + if ( isdefined( highLightedEnt ) ) + { + if ( isdefined( lastHighlightedEnt ) ) + { + if ( lastHighlightedEnt != highlightedEnt ) + { + // a highlighted ent is no longer highlighted so scale down the text size +// lastHighlightedEnt.text = "."; +// lastHighlightedEnt.textsize = 2; + if ( !ent_is_selected( lastHighlightedEnt ) ) + lastHighlightedEnt thread entity_highlight_disable(); + + // an ent became highlighted for the first time so scale up the text size on the new ent +// highlightedEnt.text = HighlightedEnt.v["fxid"]; +// highlightedEnt.textsize = 1; + if ( !ent_is_selected( highlightedEnt ) ) + highlightedEnt thread entity_highlight_enable(); + } + } + else + { + // an ent became highlighted for the first time so scale up the text size on the new ent +// HighlightedEnt.text = HighlightedEnt.v["fxid"]; +// HighlightedEnt.textsize = 1; + if ( !ent_is_selected( highlightedEnt ) ) + highlightedEnt thread entity_highlight_enable(); + } + } + + manipulate_createfx_ents( highlightedEnt, leftClick, leftHeld, ctrlHeld, colors, right ); + + // ************************************************************ + // + // Rotation and Movement + // + // ************************************************************ + + if ( axisMode && level._selected_fx_ents.size > 0 ) + { + // draw axis and do rotation if shift is held + thread [[ level._func_process_fx_rotater ]](); + if ( button_is_clicked( "enter", "p" ) ) + reset_axis_of_selected_ents(); + + if ( button_is_clicked( "v" ) ) + copy_angles_of_selected_ents(); + + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + level._selected_fx_ents[ i ] draw_axis(); + + if ( level._selectedRotate_pitch != 0 || level._selectedRotate_yaw != 0 || level._selectedRotate_roll != 0 ) + changedSelectedEnts = true; + //wait( 0.05 ); +/* + for ( i=0; i < level.selected_fx_ents.size; i++) + { + ent = level.selected_fx_ents[i]; + ent.angles = ent.angles + (level.selectedRotate_pitch, level.selectedRotate_yaw, 0); + ent set_forward_and_up_vectors(); + } + + if (level.selectedRotate_pitch != 0 || level.selectedRotate_yaw != 0) + changedSelectedEnts = true; +*/ + } + else + { + selectedMove_vector = get_selected_move_vector(); + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + if ( isdefined( ent.model ) )// ents with brushmodels are from radiant and dont get moved + continue; + + ent.v[ "origin" ] = ent.v[ "origin" ] + selectedMove_vector; + } + + if ( distance( ( 0, 0, 0 ), selectedMove_vector ) > 0 ) + changedSelectedEnts = true; + + //wait( 0.05 ); + } + + if ( changedSelectedEnts ) + update_selected_entities(); + + if( !level._mp_createfx ) + lastPlayerOrigin = [[ level._func_position_player_get ]]( lastPlayerOrigin ); + + lastHighlightedEnt = highlightedEnt; + + // if the last selected entity changes then reset the options offset + if ( last_selected_entity_has_changed( lastSelectEntity ) ) + { + level._effect_list_offset = 0; + clear_settable_fx(); + setmenu( "none" ); + } + + if ( level._selected_fx_ents.size ) + lastSelectEntity = level._selected_fx_ents[ level._selected_fx_ents.size - 1 ]; + else + lastSelectEntity = undefined; + } +} + +copy_angles_of_selected_ents() +{ + // so it stops rotating them over time + level notify( "new_ent_selection" ); + + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + ent.v[ "angles" ] = level._selected_fx_ents[ level._selected_fx_ents.size - 1 ].v[ "angles" ]; + ent set_forward_and_up_vectors(); + } + + update_selected_entities(); +} + +reset_axis_of_selected_ents() +{ + // so it stops rotating them over time + level notify( "new_ent_selection" ); + + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent set_forward_and_up_vectors(); + } + + update_selected_entities(); +} + +last_selected_entity_has_changed( lastSelectEntity ) +{ + if ( isdefined( lastSelectEntity ) ) + { + if ( !entities_are_selected() ) + return true; + } + else + return entities_are_selected(); + + return( lastSelectEntity != level._selected_fx_ents[ level._selected_fx_ents.size - 1 ] ); +} + +createfx_showOrigin( id, org, delay, org2, type, exploder, id2, fireFx, fireFxDelay, fireFxSound, fxSound, fxQuake, fxDamage, soundalias, repeat, delay_min, delay_max, damage_radius, fireFxTimeout ) +{ +} + +drop_selection_to_ground() +{ + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + trace = bullettrace( ent.v[ "origin" ], ent.v[ "origin" ] + ( 0, 0, -2048 ), false, undefined ); + ent.v[ "origin" ] = trace[ "position" ]; + } +} + +set_off_exploders() +{ + level notify( "createfx_exploder_reset" ); + exploders = []; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + if ( isdefined( ent.v[ "exploder" ] ) ) + exploders[ ent.v[ "exploder" ] ] = true; + } + + keys = getarraykeys( exploders ); + for ( i = 0; i < keys.size; i++ ) + exploder( keys[ i ] ); +} + +draw_distance() +{ + count = 0; + if ( GetDvarInt( "createfx_drawdist" ) == 0 ) + SetDevDvar( "createfx_drawdist", "1500" ); + + for ( ;; ) + { + maxDist = GetDvarInt( "createfx_drawdist" ); + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + ent.drawn = distance( level._player.origin, ent.v[ "origin" ] ) <= maxDist; + + count++ ; + if ( count > 100 ) + { + count = 0; + wait( 0.05 ); + } + } + if ( level._createFXent.size == 0 ) + wait( 0.05 ); + } +} + +createfx_autosave() +{ + for ( ;; ) + { + wait( 300 ); + flag_waitopen( "createfx_saving" ); + generate_fx_log( true ); + } +} + +rotate_over_time( org, rotater ) +{ + level endon( "new_ent_selection" ); + timer = 0.1; + for ( p = 0;p < timer * 20;p++ ) + { + if ( level._selectedRotate_pitch != 0 ) + org AddPitch( level._selectedRotate_pitch ); + else + if ( level._selectedRotate_yaw != 0 ) + org AddYaw( level._selectedRotate_yaw ); + else + org AddRoll( level._selectedRotate_roll ); + + wait( 0.05 ); + org draw_axis(); + + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + if ( isdefined( ent.model ) )// ents with brushmodels are from radiant and dont get moved + continue; + + ent.v[ "origin" ] = rotater[ i ].origin; + ent.v[ "angles" ] = rotater[ i ].angles; + } + } +} + +delete_pressed() +{ + if ( level._createfx_inputlocked ) + { + remove_selected_option(); + return; + } + + delete_selection(); +} + +remove_selected_option() +{ + if ( !isdefined( level._selected_fx_option_index ) ) + { + return; + } + + name = level._createFX_options[ level._selected_fx_option_index ][ "name" ]; + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + if ( !ent_is_selected( ent ) ) + continue; + + ent remove_option( name ); + } + + update_selected_entities(); + clear_settable_fx(); +} + +remove_option( name ) +{ + self.v[ name ] = undefined; +} + +delete_selection() +{ + newArray = []; + + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + if ( ent_is_selected( ent ) ) + { + if ( isdefined( ent.looper ) ) + ent.looper delete(); + + ent notify( "stop_loop" ); + } + else + newArray[ newArray.size ] = ent; + } + + level._createFXent = newArray; + + level._selected_fx = []; + level._selected_fx_ents = []; + clear_fx_hudElements(); +} + +move_selection_to_cursor() +{ + origin = level._createfxCursor[ "position" ]; + if ( level._selected_fx_ents.size <= 0 ) + return; + + center = get_center_of_array( level._selected_fx_ents ); + difference = center - origin; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + if ( isdefined( ent.model ) )// ents with brushmodels are from radiant and dont get moved + continue; + + ent.v[ "origin" ] -= difference; + } +} + +insert_effect() +{ + setMenu( "creation" ); + level._effect_list_offset = 0; + clear_fx_hudElements(); + + set_fx_hudElement( "Pick effect type to create:" ); + set_fx_hudElement( "1. Ambient/OneShot fx" ); + set_fx_hudElement( "2. Scripted/Exploder fx" ); + set_fx_hudElement( "3. Looping sound" ); + set_fx_hudElement( "(c) Cancel" ); + set_fx_hudElement( "(x) Exit" ); + + /* + set_fx_hudElement( "2. Looping fx" ); // no more + set_fx_hudElement("Pick an effect:"); + set_fx_hudElement("In the console, type"); + set_fx_hudElement("/fx name"); + set_fx_hudElement("Where name is the name of the sound alias"); + */ +} + +show_help() +{ + clear_fx_hudElements(); + set_fx_hudElement( "Help:" ); + set_fx_hudElement( "Insert Insert entity" ); + set_fx_hudElement( "L Drop selected entities to the ground" ); + set_fx_hudElement( "A Add option to the selected entities" ); + set_fx_hudElement( "P Reset the rotation of the selected entities" ); + set_fx_hudElement( "V Copy the angles from the most recently selected fx onto all selected fx." ); + set_fx_hudElement( "Delete Kill the selected entities" ); + set_fx_hudElement( "ESCAPE Cancel out of option-modify-mode, must have console open" ); + set_fx_hudElement( "Ctrl-C Copy" ); + set_fx_hudElement( "Ctrl-V Paste" ); + set_fx_hudElement( "F2 Toggle createfx dot and text drawing" ); + set_fx_hudElement( "F5 SAVES your work" ); + set_fx_hudElement( "Dpad Move selected entitise on X/Y or rotate pitch/yaw" ); + set_fx_hudElement( "A button Toggle the selection of the current entity" ); + set_fx_hudElement( "X button Toggle entity rotation mode" ); + set_fx_hudElement( "Y button Move selected entites up or rotate roll" ); + set_fx_hudElement( "B button Move selected entites down or rotate roll" ); + set_fx_hudElement( "R Shoulder Move selected entities to the cursor" ); + set_fx_hudElement( "L Shoulder Hold to select multiple entites" ); + set_fx_hudElement( "L JoyClick Copy" ); + set_fx_hudElement( "R JoyClick Paste" ); + set_fx_hudElement( "N UFO" ); + set_fx_hudElement( "T Toggle Timescale FAST" ); + set_fx_hudElement( "Y Toggle Timescale SLOW" ); + set_fx_hudElement( "[ Toggle FX Visibility" ); + set_fx_hudElement( "] Toggle ShowTris" ); + set_fx_hudElement( "F11 Toggle FX Profile" ); +} + + +select_last_entity() +{ + select_entity( level._createFXent.size - 1, level._createFXent[ level._createFXent.size - 1 ] ); +} + +select_all_exploders_of_currently_selected( key ) +{ + selected_exploders = []; + foreach ( ent in level._selected_fx_ents ) + { + if ( !isdefined( ent.v[ key ] ) ) + continue; + + value = ent.v[ key ]; + selected_exploders[ value ] = true; + } + + foreach ( value, _ in selected_exploders ) + { + foreach ( index, ent in level._createFXent ) + { + if ( index_is_selected( index ) ) + continue; + if ( !isdefined( ent.v[ key ] ) ) + continue; + if ( ent.v[ key ] != value ) + continue; + + select_entity( index, ent ); + } + } + + update_selected_entities(); +} + +copy_ents() +{ + if ( level._selected_fx_ents.size <= 0 ) + return; + + array = []; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + newent = spawnstruct(); + + newent.v = ent.v; + newent post_entity_creation_function(); + array[ array.size ] = newent; + } + + level._stored_ents = array; +} + +post_entity_creation_function() +{ + self.textAlpha = 0; + self.drawn = true; +} + +paste_ents() +{ + if ( !isdefined( level._stored_ents ) ) + return; + + clear_entity_selection(); + + for ( i = 0;i < level._stored_ents.size;i++ ) + add_and_select_entity( level._stored_ents[ i ] ); + + move_selection_to_cursor(); + update_selected_entities(); + level._stored_ents = []; + copy_ents();// roundabout way to put new entities in the copy queue +} + +add_and_select_entity( ent ) +{ + level._createFXent[ level._createFXent.size ] = ent; + select_last_entity(); +} + +get_center_of_array( array ) +{ + center = ( 0, 0, 0 ); + for ( i = 0; i < array.size; i++ ) + center = ( center[ 0 ] + array[ i ].v[ "origin" ][ 0 ], center[ 1 ] + array[ i ].v[ "origin" ][ 1 ], center[ 2 ] + array[ i ].v[ "origin" ][ 2 ] ); + + return( center[ 0 ] / array.size, center[ 1 ] / array.size, center[ 2 ] / array.size ); +} + +ent_draw_axis() +{ + self endon( "death" ); + for ( ;; ) + { + draw_axis(); + wait( 0.05 ); + } +} + +rotation_is_occuring() +{ + if ( level._selectedRotate_roll != 0 ) + return true; + if ( level._selectedRotate_pitch != 0 ) + return true; + return level._selectedRotate_yaw != 0; +} + +print_fx_options( ent, tab, file, autosave ) +{ + for ( i = 0; i < level._createFX_options.size; i++ ) + { + option = level._createFX_options[ i ]; + if ( !isdefined( ent.v[ option[ "name" ] ] ) ) + continue; + if ( !mask( option[ "mask" ], ent.v[ "type" ] ) ) + continue; + + if ( option[ "type" ] == "string" ) + { +// if ( !autosave ) +// println( " ent.v[ \"" + option[ "name" ] + "\" ] = \"" + ent.v[ option[ "name" ] ] + "\";" ); + cfxprintln( file, tab + "ent.v[ \"" + option[ "name" ] + "\" ] = \"" + ent.v[ option[ "name" ] ] + "\";" ); + continue; + } + + // int or float +// if ( !autosave ) +// println( " ent.v[ \"" + option[ "name" ] + "\" ] = " + ent.v[ option[ "name" ] ] + ";" ); + cfxprintln( file, tab + "ent.v[ \"" + option[ "name" ] + "\" ] = " + ent.v[ option[ "name" ] ] + ";" ); + } +} + +entity_highlight_disable() +{ + self notify( "highlight change" ); + self endon( "highlight change" ); + + for ( ;; ) + { + self.textalpha = self.textalpha * 0.85; + self.textalpha = self.textalpha - 0.05; + if ( self.textalpha < 0 ) + break; + wait( 0.05 ); + } + + self.textalpha = 0; +} + +entity_highlight_enable() +{ + self notify( "highlight change" ); + self endon( "highlight change" ); + + for ( ;; ) + { +// self.textalpha = sin(gettime()) * 0.5 + 0.5; + self.textalpha = self.textalpha + 0.05; + self.textalpha = self.textalpha * 1.25; + if ( self.textalpha > 1 ) + break; + wait( 0.05 ); + } + + self.textalpha = 1; + +} + + +toggle_createfx_drawing() +{ + level._createfx_draw_enabled = !level._createfx_draw_enabled; +} + +manipulate_createfx_ents( highlightedEnt, leftClick, leftHeld, ctrlHeld, colors, right ) +{ + if ( !level._createfx_draw_enabled ) + return; + + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + if ( !ent.drawn ) + continue; + + scale = GetDvarFloat( "createfx_scaleid" ); + + if ( isdefined( highlightedEnt ) && ent == highlightedEnt ) + { + if ( !entities_are_selected() ) + display_fx_info( ent ); + + if ( leftClick ) + { + entWasSelected = index_is_selected( i ); + level._createfx_selecting = !entWasSelected;// used for drag select / deselect + if ( !ctrlHeld ) + { + selectedSize = level._selected_fx_ents.size; + clear_entity_selection(); + if ( entWasSelected && selectedSize == 1 ) + select_entity( i, ent ); + } + toggle_entity_selection( i, ent ); + } + else + if ( leftHeld ) + { + if ( ctrlHeld ) + { + if ( level._createfx_selecting ) + select_entity( i, ent ); + + if ( !level._createfx_selecting ) + deselect_entity( i, ent ); + } + } + + + colorIndex = "highlighted"; + if ( index_is_selected( i ) ) + colorIndex = "selected"; + + + print3d( ent.v[ "origin" ], ".", colors[ ent.v[ "type" ] ][ colorIndex ], 1, scale ); + if ( ent.textalpha > 0 ) + { + printRight = vector_multiply( right, ent.v[ "fxid" ].size * - 2.93 * scale ); + print3d( ent.v[ "origin" ] + printRight + ( 0, 0, 15 ), ent.v[ "fxid" ], colors[ ent.v[ "type" ] ][ colorIndex ], ent.textalpha, scale ); + } + } + else + { + colorIndex = "default"; + if ( index_is_selected( i ) ) + colorIndex = "selected"; + + print3d( ent.v[ "origin" ], ".", colors[ ent.v[ "type" ] ][ colorIndex ], 1, scale ); + if ( ent.textalpha > 0 ) + { + printRight = vector_multiply( right, ent.v[ "fxid" ].size * - 2.93 ); + print3d( ent.v[ "origin" ] + printRight + ( 0, 0, 15 ), ent.v[ "fxid" ], colors[ ent.v[ "type" ] ][ colorIndex ], ent.textalpha, scale ); + } + } + } +} + +clear_settable_fx() +{ + level._createfx_inputlocked = false; + SetDevDvar( "fx", "nil" ); + // in case we were modifying an option + level._selected_fx_option_index = undefined; + reset_fx_hud_colors(); +} + +reset_fx_hud_colors() +{ + for ( i = 0;i < level._createFx_hudElements; i++ ) + level._createFxHudElements[ i ][ 0 ].color = ( 1, 1, 1 ); +} + + +button_is_held( name, name2 ) +{ + if ( isdefined( name2 ) ) + { + if ( isdefined( level._buttonIsHeld[ name2 ] ) ) + return true; + } + return isdefined( level._buttonIsHeld[ name ] ); +} + +button_is_clicked( name, name2 ) +{ + if ( isdefined( name2 ) ) + { + if ( isdefined( level._buttonClick[ name2 ] ) ) + return true; + } + return isdefined( level._buttonClick[ name ] ); +} + +toggle_entity_selection( index, ent ) +{ + if ( isdefined( level._selected_fx[ index ] ) ) + deselect_entity( index, ent ); + else + select_entity( index, ent ); +} + +select_entity( index, ent ) +{ + if ( isdefined( level._selected_fx[ index ] ) ) + return; + clear_settable_fx(); + level notify( "new_ent_selection" ); + + ent thread entity_highlight_enable(); + + level._selected_fx[ index ] = true; + level._selected_fx_ents[ level._selected_fx_ents.size ] = ent; +} + +ent_is_highlighted( ent ) +{ + if ( !isdefined( level._fx_highLightedEnt ) ) + return false; + return ent == level._fx_highLightedEnt; +} + + +deselect_entity( index, ent ) +{ + if ( !isdefined( level._selected_fx[ index ] ) ) + return; + + clear_settable_fx(); + level notify( "new_ent_selection" ); + + level._selected_fx[ index ] = undefined; + + if ( !ent_is_highlighted( ent ) ) + ent thread entity_highlight_disable(); + + // remove the entity from the array of selected entities + newArray = []; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + if ( level._selected_fx_ents[ i ] != ent ) + newArray[ newArray.size ] = level._selected_fx_ents[ i ]; + } + level._selected_fx_ents = newArray; +} + +index_is_selected( index ) +{ + return isdefined( level._selected_fx[ index ] ); +} + +ent_is_selected( ent ) +{ + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + if ( level._selected_fx_ents[ i ] == ent ) + return true; + } + return false; +} + +clear_entity_selection() +{ + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + if ( !ent_is_highlighted( level._selected_fx_ents[ i ] ) ) + level._selected_fx_ents[ i ] thread entity_highlight_disable(); + } + level._selected_fx = []; + level._selected_fx_ents = []; +} + +draw_axis() +{ + range = 25 * GetDvarFloat( "createfx_scaleid" ); + +// range = 25; + forward = anglestoforward( self.v[ "angles" ] ); + forward = vector_multiply( forward, range ); + right = anglestoright( self.v[ "angles" ] ); + right = vector_multiply( right, range ); + up = anglestoup( self.v[ "angles" ] ); + up = vector_multiply( up, range ); + line( self.v[ "origin" ], self.v[ "origin" ] + forward, ( 1, 0, 0 ), 1 ); + line( self.v[ "origin" ], self.v[ "origin" ] + up, ( 0, 1, 0 ), 1 ); + line( self.v[ "origin" ], self.v[ "origin" ] + right, ( 0, 0, 1 ), 1 ); +} + + +clear_fx_hudElements() +{ + level._clearTextMarker clearAllTextAfterHudElem(); + + for ( i = 0; i < level._createFx_hudElements; i++ ) + { + for ( p = 0; p < 1; p++ ) + { + level._createFxHudElements[ i ][ p ] setText( "" ); + } + } + + level._fxHudElements = 0; +} + + +set_fx_hudElement( text ) +{ + for ( p = 0; p < 1; p++ ) + { + level._createFxHudElements[ level._fxHudElements ][ p ] setText( text ); + } + + level._fxHudElements++ ; + assert( level._fxHudElements < level._createFx_hudElements ); +} + +createfx_centerprint( text ) +{ + thread createfx_centerprint_thread( text ); +} + +createfx_centerprint_thread( text ) +{ + level notify( "new_createfx_centerprint" ); + level endon( "new_createfx_centerprint" ); + for ( p = 0;p < 5;p++ ) + level._createFX_centerPrint[ p ] setText( text ); + wait( 4.5 ); + for ( p = 0;p < 5;p++ ) + level._createFX_centerPrint[ p ] setText( "" ); +} + +buttonDown( button, button2 ) +{ + return buttonPressed_internal( button ) || buttonPressed_internal( button2 ); +} + + + +buttonPressed_internal( button ) +{ + if ( !isdefined( button ) ) + return false; + + // keyboard buttons can be locked so you can type in the fx info on the keyboard without + // accidentally activating features + if ( kb_locked( button ) ) + return false; + + return level._player buttonPressed( button ); +} + + +get_selected_move_vector() +{ + yaw = level._player getplayerangles()[ 1 ]; + angles = ( 0, yaw, 0 ); + right = anglestoright( angles ); + forward = anglestoforward( angles ); + up = anglestoup( angles ); + + keypressed = false; + rate = 1; + + if ( buttonDown( "kp_uparrow", "DPAD_UP" ) ) + { + if ( level._selectedMove_forward < 0 ) + level._selectedMove_forward = 0; + + level._selectedMove_forward = level._selectedMove_forward + rate; + } + else + if ( buttonDown( "kp_downarrow", "DPAD_DOWN" ) ) + { + if ( level._selectedMove_forward > 0 ) + level._selectedMove_forward = 0; + level._selectedMove_forward = level._selectedMove_forward - rate; + } + else + level._selectedMove_forward = 0; + + if ( buttonDown( "kp_rightarrow", "DPAD_RIGHT" ) ) + { + if ( level._selectedMove_right < 0 ) + level._selectedMove_right = 0; + + level._selectedMove_right = level._selectedMove_right + rate; + } + else + if ( buttonDown( "kp_leftarrow", "DPAD_LEFT" ) ) + { + if ( level._selectedMove_right > 0 ) + level._selectedMove_right = 0; + level._selectedMove_right = level._selectedMove_right - rate; + } + else + level._selectedMove_right = 0; + + if ( buttonDown( "BUTTON_Y" ) ) + { + if ( level._selectedMove_up < 0 ) + level._selectedMove_up = 0; + + level._selectedMove_up = level._selectedMove_up + rate; + } + else + if ( buttonDown( "BUTTON_B" ) ) + { + if ( level._selectedMove_up > 0 ) + level._selectedMove_up = 0; + level._selectedMove_up = level._selectedMove_up - rate; + } + else + level._selectedMove_up = 0; + +// vector = (level.selectedMove_right, level.selectedMove_forward, level.selectedMove_up); + vector = ( 0, 0, 0 ); + vector += vector_multiply( forward, level._selectedMove_forward ); + vector += vector_multiply( right, level._selectedMove_right ); + vector += vector_multiply( up, level._selectedMove_up ); + + return vector; +} + +process_button_held_and_clicked() +{ + add_button( "mouse1" ); + add_kb_button( "shift" ); + add_kb_button( "ctrl" ); + add_button( "BUTTON_RSHLDR" ); + add_button( "BUTTON_LSHLDR" ); + add_button( "BUTTON_RSTICK" ); + add_button( "BUTTON_LSTICK" ); + add_button( "BUTTON_A" ); + add_button( "BUTTON_B" ); + add_button( "BUTTON_X" ); + add_button( "BUTTON_Y" ); + add_button( "DPAD_UP" ); + add_button( "DPAD_LEFT" ); + add_button( "DPAD_RIGHT" ); + add_button( "DPAD_DOWN" ); + add_kb_button( "escape" ); + + add_kb_button( "a" ); + add_kb_button( "g" ); + add_button( "F1" ); + add_button( "F5" ); + add_button( "F2" ); + add_kb_button( "c" ); + add_kb_button( "h" ); + add_kb_button( "i" ); + add_kb_button( "k" ); + add_kb_button( "l" ); + add_kb_button( "m" ); + add_kb_button( "p" ); + add_kb_button( "t" ); + add_kb_button( "x" ); + add_button( "del" );// DEL is allowed to be pressed while in select mode + add_kb_button( "end" ); + add_kb_button( "tab" ); + add_kb_button( "ins" ); + add_kb_button( "add" ); + add_kb_button( "space" ); + add_kb_button( "enter" ); + add_kb_button( "v" ); + add_kb_button( "1" ); + add_kb_button( "2" ); + add_kb_button( "3" ); + add_kb_button( "4" ); + add_kb_button( "5" ); + add_kb_button( "6" ); + add_kb_button( "7" ); + add_kb_button( "8" ); + add_kb_button( "9" ); + add_kb_button( "0" ); +} + + +locked( name ) +{ + if ( isdefined( level._createfx_lockedList[ name ] ) ) + return false; + + return kb_locked( name ); +} + +kb_locked( name ) +{ + return level._createfx_inputlocked && isdefined( level._button_is_kb[ name ] ); +} + + +add_button( name ) +{ + if ( locked( name ) ) + return; + + if ( !isdefined( level._buttonIsHeld[ name ] ) ) + { + if ( level._player buttonPressed( name ) ) + { + level._buttonIsHeld[ name ] = true; + level._buttonClick[ name ] = true; +// println("Button: " + name); + } + } + else + { + if ( !level._player buttonPressed( name ) ) + { + level._buttonIsHeld[ name ] = undefined; + } + } +} + +add_kb_button( name ) +{ + level._button_is_kb[ name ] = true; + add_button( name ); +} + + + +set_anglemod_move_vector() +{ + rate = 2; + + if ( buttonDown( "kp_uparrow", "DPAD_UP" ) ) + { + if ( level._selectedRotate_pitch < 0 ) + level._selectedRotate_pitch = 0; + + level._selectedRotate_pitch = level._selectedRotate_pitch + rate; + } + else + if ( buttonDown( "kp_downarrow", "DPAD_DOWN" ) ) + { + if ( level._selectedRotate_pitch > 0 ) + level._selectedRotate_pitch = 0; + level._selectedRotate_pitch = level._selectedRotate_pitch - rate; + } + else + level._selectedRotate_pitch = 0; + + if ( buttonDown( "kp_leftarrow", "DPAD_LEFT" ) ) + { + if ( level._selectedRotate_yaw < 0 ) + level._selectedRotate_yaw = 0; + + level._selectedRotate_yaw = level._selectedRotate_yaw + rate; + } + else + if ( buttonDown( "kp_rightarrow", "DPAD_RIGHT" ) ) + { + if ( level._selectedRotate_yaw > 0 ) + level._selectedRotate_yaw = 0; + level._selectedRotate_yaw = level._selectedRotate_yaw - rate; + } + else + level._selectedRotate_yaw = 0; + + if ( buttonDown( "BUTTON_Y" ) ) + { + if ( level._selectedRotate_roll < 0 ) + level._selectedRotate_roll = 0; + + level._selectedRotate_roll = level._selectedRotate_roll + rate; + } + else + if ( buttonDown( "BUTTON_B" ) ) + { + if ( level._selectedRotate_roll > 0 ) + level._selectedRotate_roll = 0; + level._selectedRotate_roll = level._selectedRotate_roll - rate; + } + else + level._selectedRotate_roll = 0; + +} + +cfxprintlnStart() +{ + fileprint_launcher_start_file(); +} + +cfxprintln( file, string ) +{ + fileprint_launcher( string ); + if ( file == -1 ) + return; + fprintln( file, string ); +} + +cfxprintlnEnd( file, autosave, radiant_exploder_add_string ) +{ + bP4add = true; + + if( radiant_exploder_add_string != "" || autosave ) + bP4add = false; + + scriptname = level._script+radiant_exploder_add_string+"_fx.gsc"; + if( autosave ) + scriptname = "backup.gsc"; + + fileprint_launcher_end_file( "/share/raw/maps/createfx/" + scriptname, bP4add ); +} + +update_selected_entities() +{ + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + ent [[ level._func_updatefx ]](); + } +} + +hack_start( painter_spmp ) +{ + if ( !isdefined( painter_spmp ) ) + painter_spmp = "painter_mp"; + precachemenu( painter_spmp ); + if( painter_spmp == "painter_mp" ) + return; + + wait .05; + level._player openpopupmenu( painter_spmp );// painter.menu execs some console commands( ufo mode ).. sneaky hacks. + level._player closepopupmenu( painter_spmp ); +} + +get_player() +{ + return getentarray( "player", "classname" )[ 0 ]; +} + +// bobble sort, performance does not really matter since it's only used by createFX tool. +create_fx_sort_array( fx_array ) +{ + loop_count = 0; + wait_count = 2000; + + for ( i = 0; i < fx_array.size - 1; i++ ) + { + for ( j = i; j < fx_array.size; j++ ) + { + // compare 2 fx entities + result = compareFXent( fx_array[ i ], fx_array[ j ] ); + if ( result > 0 ) + { + // swap + a = fx_array[ i ]; + fx_array[ i ] = fx_array[ j ]; + fx_array[ j ] = a; + } + + loop_count = loop_count + 1; + if ( loop_count > wait_count ) + { + wait( 0.001 ); + loop_count = 0; + } + } + } +} + +// bobble sort, performance does not really matter since it's only used by createFX tool. +sort_fx_entities() +{ + create_fx_sort_array( level._createFXent ); +} + +createfx_orgranize_array() +{ + types = []; + types[ 0 ] = "soundfx"; + types[ 1 ] = "loopfx"; + types[ 2 ] = "oneshotfx"; + types[ 3 ] = "exploder"; + + array = []; + foreach ( index, _ in types ) + { + array[ index ] = []; + } + + foreach ( ent in level._createFXent ) + { + found_type = false; + foreach ( index, type in types ) + { + if ( ent.v[ "type" ] != type ) + continue; + + found_type = true; + array[ index ][ array[ index ].size ] = ent; + break; + } + + assertex( found_type, "Didnt understand createfx type " + ent.v[ "type" ] ); + } + + new_array = []; + + for ( i = 0; i < types.size; i++ ) + { + create_fx_sort_array( array[i] ); + + foreach ( ent in array[ i ] ) + { + new_array[ new_array.size ] = ent; + } + } + + level._createFXent = new_array; +} + +stop_fx_looper( killElements ) +{ + if ( isdefined( self.looper ) ) + { + if ( isdefined( killElements ) ) + { + self.looper delete(killElements); + } + else + { + self.looper delete(); + } + } + self stop_loopsound(); +} + +stop_loopsound() +{ + self notify( "stop_loop" ); +} + +func_get_level_fx() +{ + AssertEx( IsDefined( level._effect ), "No effect aliases defined!" ); + + if ( !IsDefined( level._effect_keys ) ) + { + keys = getarraykeys( level._effect ); + } + else + { + keys = getarraykeys( level._effect ); + if ( keys.size == level._effect_keys.size ) + { + return level._effect_keys; + } + } + + println( "alphabetizing fx" ); + + keys = sortString( keys ); // faster version + //keys = alphabetize( keys ); // this is slow + + level._effect_keys = keys; + return keys; +} + +restart_fx_looper() +{ + stop_fx_looper( 1 ); + + self set_forward_and_up_vectors(); + if ( self.v[ "type" ] == "loopfx" ) + { + // new entities from copy/paste wont have a looper + self create_looper(); + } + + if ( self.v[ "type" ] == "oneshotfx" ) + { + // new entities from copy/paste wont have a looper + self create_triggerfx(); + } + + if ( self.v[ "type" ] == "soundfx" ) + { + // new entities from copy/paste wont have a looper + self create_loopsound(); + } +} + +process_fx_rotater() +{ + if ( level._fx_rotating ) + return; + + + set_anglemod_move_vector(); + + if ( !rotation_is_occuring() ) + return; + + level._fx_rotating = true; + + if ( level._selected_fx_ents.size > 1 ) + { + center = get_center_of_array( level._selected_fx_ents ); + org = spawn( "script_origin", center ); + org.v[ "angles" ] = level._selected_fx_ents[ 0 ].v[ "angles" ]; + org.v[ "origin" ] = center; + + rotater = []; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + rotater[ i ] = spawn( "script_origin", level._selected_fx_ents[ i ].v[ "origin" ] ); + rotater[ i ].angles = level._selected_fx_ents[ i ].v[ "angles" ]; + rotater[ i ] linkto( org ); + } + +// println ("pitch " + level.selectedRotate_pitch + " yaw " + level.selectedRotate_yaw); + + rotate_over_time( org, rotater ); + + org delete(); + + for ( i = 0; i < rotater.size; i++ ) + rotater[ i ] delete(); + } + else if ( level._selected_fx_ents.size == 1 ) + { + ent = level._selected_fx_ents[ 0 ]; + rotater = spawn( "script_origin", ( 0, 0, 0 ) ); + rotater.angles = ent.v[ "angles" ]; + if ( level._selectedRotate_pitch != 0 ) + rotater AddPitch( level._selectedRotate_pitch ); + else + if ( level._selectedRotate_yaw != 0 ) + rotater AddYaw( level._selectedRotate_yaw ); + else + rotater AddRoll( level._selectedRotate_roll ); + ent.v[ "angles" ] = rotater.angles; + rotater delete(); + wait( 0.05 ); + } + + level._fx_rotating = false; +} + +computeFXentKey( ent ) +{ + primaryKey = 0; + + if ( ent.v[ "type" ] == "loopfx" ) + { + primaryKey = 1; + } + else if ( ent.v[ "type" ] == "oneshotfx" ) + { + primaryKey = 2; + } + else if ( ent.v[ "type" ] == "exploder" ) + { + primaryKey = 3; + } + else if ( ent.v[ "type" ] == "soundfx" ) + { + primaryKey = 4; + } + + return primaryKey; +} + +compareFXent( ent0, ent1 ) +{ + // compare fx type + key0 = computeFXentKey( ent0 ); + key1 = computeFXentKey( ent1 ); + + if ( key0 < key1 ) + { + return -1; + } + else if ( key0 > key1 ) + { + return 1; + } + + str0 = ""; + str1 = ""; + + // sound type + if ( key0==4 ) + { + str0 = ent0.v[ "soundalias" ]; + str1 = ent1.v[ "soundalias" ]; + } + else + { + str0 = ent0.v[ "fxid" ]; + str1 = ent1.v[ "fxid" ]; + } + + // compare fx id + result = compareString( str0, str1 ); + + if ( result != 0 ) + { + return result; + } + + // compare fx origin + diff = ent0.v[ "origin" ] - ent1.v[ "origin" ]; + for ( i=0; i<3; i++ ) + { + if ( diff[i] < 0 ) + { + return -1; + } + else if ( diff[i] > 0 ) + { + return 1; + } + } + + // same + return 0; +} + +generate_fx_log( autosave ) +{ + // first lets fix all the really small numbers so they dont cause errors because the game will print out + // 4.2343-7e or whatever but cant accept it back in from script + + flag_waitopen( "createfx_saving" ); + flag_set( "createfx_saving" ); + autosave = isdefined( autosave ); + tab = "\t"; + + radiant_exploder_add_string = ""; + if( GetDvarInt("scr_map_exploder_dump") ) + radiant_exploder_add_string = "_radiant_exploders"; + + filename = "createfx/" + level._script + radiant_exploder_add_string + "_fx.gsc"; + if ( autosave ) + filename = "createfx/backup.gsc"; + +// file = openfile( filename, "write" ); +// assertex( file != -1, "File not writeable (maybe you should check it out): " + filename ); + file = -1; + + // backup _createFXent array + fxEntityBackup = level._createFXent; + + cfxprintlnStart(); + cfxprintln( file, "//_createfx generated. Do not touch!!" ); + cfxprintln( file, "#include common_scripts\\utility;" ); + cfxprintln( file, "#include common_scripts\\_createfx;\n" ); + cfxprintln( file, "main()" ); + cfxprintln( file, "{" ); + + createfx_orgranize_array(); + + limit = 0.1; + for ( p = 0; p < level._createFXent.size; p++ ) + { + ent = level._createFXent[ p ]; + origin = []; + angles = []; + for ( i = 0;i < 3;i++ ) + { + origin[ i ] = ent.v[ "origin" ][ i ]; + angles[ i ] = ent.v[ "angles" ][ i ]; + + if ( origin[ i ] < limit && origin[ i ] > limit * - 1 ) + origin[ i ] = 0; + if ( angles[ i ] < limit && angles[ i ] > limit * - 1 ) + angles[ i ] = 0; + } + + ent.v[ "origin" ] = ( origin[ 0 ], origin[ 1 ], origin[ 2 ] ); + ent.v[ "angles" ] = ( angles[ 0 ], angles[ 1 ], angles[ 2 ] ); + } + + cfxprintln( file, tab + "// CreateFX entities size: " + level._createFxEnt.size ); + + processed = 0; + + for ( i = 0; i < level._createFXent.size; i++ ) + { + if ( file != -1 && level._createfx_loopcounter > 32 ) + { + level._createfx_loopcounter = 0; + wait .05; // loop protection fails on writing the file + } + level._createfx_loopcounter++; + + e = level._createFXent[ i ]; + assertEX( isdefined( e.v[ "type" ] ), "effect at origin " + e.v[ "origin" ] + " has no type" ); + + // don't post .map effects in the script. +// if (e.v["worldfx"]) +// continue; + + // when scr_map_exploder_dump is set just output the exploders from radiant. could output two scripts but keeping it simple. + if( GetDvarInt("scr_map_exploder_dump") ) + { + if ( !isdefined( e.model ) ) + { + continue; + } + } + else if ( isdefined( e.model ) ) + { + continue; // entities with models are from radiant and don't get reported + } + + if ( e.v[ "type" ] == "loopfx" ) + { + cfxprintln( file, tab + "ent = createLoopEffect( \"" + e.v[ "fxid" ] + "\" );" ); + processed++; + } + else if ( e.v[ "type" ] == "oneshotfx" ) + { + cfxprintln( file, tab + "ent = createOneshotEffect( \"" + e.v[ "fxid" ] + "\" );" ); + processed++; + } + else if ( e.v[ "type" ] == "exploder" ) + { + cfxprintln( file, tab + "ent = createExploder( \"" + e.v[ "fxid" ] + "\" );" ); + processed++; + } + else if ( e.v[ "type" ] == "soundfx" ) + { + cfxprintln( file, tab + "ent = createLoopSound();" ); + processed++; + } + + cfxprintln( file, tab + "ent.v[ \"origin\" ] = ( " + e.v[ "origin" ][ 0 ] + ", " + e.v[ "origin" ][ 1 ] + ", " + e.v[ "origin" ][ 2 ] + " );" ); + cfxprintln( file, tab + "ent.v[ \"angles\" ] = ( " + e.v[ "angles" ][ 0 ] + ", " + e.v[ "angles" ][ 1 ] + ", " + e.v[ "angles" ][ 2 ] + " );" ); + + print_fx_options( e, tab, file, autosave ); + cfxprintln( file, "" ); + } + + cfxprintln( file, tab + "// CreateFX entities placed: " + processed ); + cfxprintln( file, "}" ); + cfxprintln( file, " " ); + cfxprintlnEnd( file, autosave, radiant_exploder_add_string ); + +// saved = closefile( file ); +// assertex( saved == 1, "File not saved (see above message?): " + filename ); + flag_clear( "createfx_saving" ); + + // restore + level._createFXent = fxEntityBackup; +} + +deleteAllEffects() +{ + immediate = 1; + + foreach ( entFx in level._createfxent ) + { + if ( isdefined( entFx.looper ) ) + { + if ( isdefined( immediate ) ) + { + entFx.looper delete( immediate ); + } + else + { + entFx.looper delete(); + } + } + entFx notify( "stop_loop" ); + } +} \ No newline at end of file diff --git a/common_scripts/_createfxmenu.gsc b/common_scripts/_createfxmenu.gsc new file mode 100644 index 0000000..f0f2cc2 --- /dev/null +++ b/common_scripts/_createfxmenu.gsc @@ -0,0 +1,638 @@ +#include common_scripts\utility; +#include common_scripts\_createfx; + +menu( name ) +{ + return level._create_fx_menu == name; +} + +setmenu( name ) +{ + level._create_fx_menu = name; +} + +create_fx_menu() +{ + if ( button_is_clicked( "escape", "x" ) ) + { + exit_menu(); + return; + } + + if ( menu( "creation" ) ) + { + if ( button_is_clicked( "1" ) ) + { + setmenu( "create_oneshot" ); + draw_effects_list(); + return; + } + else if ( button_is_clicked( "2" ) ) + { + setmenu( "create_exploder" ); + ent = createNewExploder(); + finish_creating_entity( ent ); + return; + } + else if ( button_is_clicked( "3" ) ) + { + setmenu( "create_loopsound" ); + ent = createLoopSound(); + finish_creating_entity( ent ); + return; + } + } + else if ( menu( "create_oneshot" ) || menu( "create_loopfx" ) || menu( "change_fxid" ) ) + { + if ( button_is_clicked( "m" ) ) + { + increment_list_offset(); + draw_effects_list(); + } + + menu_fx_creation(); + } + else if ( menu( "none" ) ) + { + if ( button_is_clicked( "m" ) ) + increment_list_offset(); + + // change selected entities + menu_change_selected_fx(); + + // if there's a selected ent then display the info on the last one to be selected + if ( entities_are_selected() ) + { + last_selected_ent = get_last_selected_entity(); + + // only update hudelems when we have new info + // if ( !IsDefined( level._last_displayed_ent ) || last_selected_ent != level._last_displayed_ent ) + + // now we always update it + if ( IsDefined( last_selected_ent ) ) + { + display_fx_info( last_selected_ent ); + level._last_displayed_ent = last_selected_ent; + } + + if ( button_is_clicked( "a" ) ) + { + clear_settable_fx(); + setMenu( "add_options" ); + } + else if ( button_is_clicked( "t" ) ) + { + display_fx_type_options(); + setMenu( "type_list" ); + } + } + } + else if ( menu( "add_options" ) ) + { + if ( !entities_are_selected() ) + { + clear_fx_hudElements(); + setMenu( "none" ); + return; + } + + display_fx_add_options( get_last_selected_entity() ); + + if ( button_is_clicked( "m" ) ) + { + increment_list_offset(); + // draw_effects_list(); + } + } + else if ( menu( "type_list" ) ) + { + processed = 0; + last_selected_ent = get_last_selected_entity(); + + if ( button_is_clicked( "1" ) ) + { + // switch to Ambient/OneShot fx + if ( last_selected_ent.v[ "type" ] != "oneshotfx" ) + { + // build new entity + new_ent = CreateOneShotEntity(); + clone_entity_oneshot( last_selected_ent, new_ent ); + + // remove old entity + delete_selection(); + clear_entity_selection(); + select_last_entity(); + update_selected_entities(); + } + + processed = 1; + } + else if ( button_is_clicked( "2" ) ) + { + // switch to Scripted/Exploder fx + if ( last_selected_ent.v[ "type" ] != "exploder" ) + { + // build new entity + new_ent = createNewExploder(); + clone_entity_exploder( last_selected_ent, new_ent ); + + // remove old entity + delete_selection(); + clear_entity_selection(); + select_last_entity(); + update_selected_entities(); + } + + processed = 1; + } + else if ( button_is_clicked( "x" ) ) + { + processed = 1; + } + + last_selected_ent = get_last_selected_entity(); + + if ( processed == 1 ) + { + clear_fx_hudElements(); + display_fx_info( last_selected_ent ); + setMenu( "none" ); + } + } +} + +exit_menu() +{ + clear_fx_hudElements(); + clear_entity_selection(); + update_selected_entities(); + setmenu( "none" ); +} + +get_last_selected_entity() +{ + return level._selected_fx_ents[ level._selected_fx_ents.size - 1 ]; +} + +menu_fx_creation() +{ + count = 0; + picked_fx = undefined; + keys = func_get_level_fx(); + + for ( i = level._effect_list_offset; i < keys.size; i++ ) + { + count = count + 1; + button_to_check = count; + if ( button_to_check == 10 ) + button_to_check = 0; + if ( button_is_clicked( button_to_check + "" ) ) + { + picked_fx = keys[ i ]; + break; + } + + if ( count > level._effect_list_offset_max ) + break; + } + + if ( !isdefined( picked_fx ) ) + return; + + if ( menu( "change_fxid" ) ) + { + apply_option_to_selected_fx( get_option( "fxid" ), picked_fx ); + level._effect_list_offset = 0; + clear_fx_hudElements(); + setMenu( "none" ); + return; + } + + + ent = undefined; + if ( menu( "create_loopfx" ) ) + ent = createLoopEffect( picked_fx ); + if ( menu( "create_oneshot" ) ) + ent = createOneshotEffect( picked_fx ); + + finish_creating_entity( ent ); +} + +clone_entity_oneshot( ent_src, ent_dst ) +{ + ent_dst.v = ent_src.v; + ent_dst.v[ "type" ] = "oneshotfx"; + ent_dst.v[ "delay" ] = -15; + + ent_dst post_entity_creation_function(); +} + +clone_entity_exploder( ent_src, ent_dst ) +{ + ent_dst.v = ent_src.v; + ent_dst.v[ "type" ] = "exploder"; + ent_dst.v[ "delay" ] = 0; + ent_dst.v[ "exploder" ] = 1; + ent_dst.v[ "exploder_type" ] = "normal"; + + ent_dst post_entity_creation_function(); +} + +finish_creating_entity( ent ) +{ + ent.v[ "angles" ] = vectortoangles( ( ent.v[ "origin" ] + ( 0, 0, 100 ) ) - ent.v[ "origin" ] ); + assert( isdefined( ent ) ); + ent post_entity_creation_function();// for createfx dev purposes + clear_entity_selection(); + select_last_entity(); + move_selection_to_cursor(); + update_selected_entities(); + setMenu( "none" ); +} + +menu_init() +{ + level._createFX_options = []; + // each option has a type, a name its stored under, a description, a default, and a mask it uses to determine + // which types of fx can have this option + addOption( "string", "fxid", "The FX", "nil", "fx" ); + addOption( "float", "delay", "Repeat rate/start delay", 0.5, "fx" ); + addOption( "float", "fire_range", "Fire damage range", 0, "fx" ); + addOption( "string", "flag", "Flag", "nil", "exploder" ); + + addOption( "string", "firefx", "2nd FX id", "nil", "exploder" ); + addOption( "float", "firefxdelay", "2nd FX id repeat rate", 0.5, "exploder" ); + addOption( "float", "firefxtimeout", "2nd FX timeout", 5, "exploder" ); + addOption( "string", "firefxsound", "2nd FX soundalias", "nil", "exploder" ); + addOption( "float", "damage", "Radius damage", 150, "exploder" ); + addOption( "float", "damage_radius", "Radius of radius damage", 250, "exploder" ); + addOption( "float", "delay_min", "Minimimum time between repeats", 1, "exploder" ); + addOption( "float", "delay_max", "Maximum time between repeats", 2, "exploder" ); + addOption( "int", "repeat", "Number of times to repeat", 5, "exploder" ); + addOption( "string", "exploder", "Exploder", 1, "exploder" ); + addOption( "string", "earthquake", "Earthquake", "nil", "exploder" ); + + if( !level._mp_createfx ) + addOption( "string", "rumble", "Rumble", "nil", "exploder" ); + addOption( "string", "ender", "Level notify for ending 2nd FX", "nil", "exploder" ); + + addOption( "string", "soundalias", "Soundalias", "nil", "all" ); + addOption( "string", "loopsound", "Loopsound", "nil", "exploder" ); + + if( !level._mp_createfx ) + addOption( "int", "stoppable", "Can be stopped from script", 1, "all" ); + + level._effect_list_offset = 0; + level._effect_list_offset_max = 10; + + + // creates mask groups. For example if the above says its mask is "fx", then all the types under "fx" can use the option + level._createfxMasks = []; + level._createfxMasks[ "all" ] = []; + level._createfxMasks[ "all" ][ "exploder" ] = true; + level._createfxMasks[ "all" ][ "oneshotfx" ] = true; + level._createfxMasks[ "all" ][ "loopfx" ] = true; + level._createfxMasks[ "all" ][ "soundfx" ] = true; + + level._createfxMasks[ "fx" ] = []; + level._createfxMasks[ "fx" ][ "exploder" ] = true; + level._createfxMasks[ "fx" ][ "oneshotfx" ] = true; + level._createfxMasks[ "fx" ][ "loopfx" ] = true; + + level._createfxMasks[ "exploder" ] = []; + level._createfxMasks[ "exploder" ][ "exploder" ] = true; + + level._createfxMasks[ "loopfx" ] = []; + level._createfxMasks[ "loopfx" ][ "loopfx" ] = true; + + level._createfxMasks[ "oneshotfx" ] = []; + level._createfxMasks[ "oneshotfx" ][ "oneshotfx" ] = true; + + level._createfxMasks[ "soundfx" ] = []; + level._createfxMasks[ "soundfx" ][ "soundalias" ] = true; +} + +get_last_selected_ent() +{ + return level._selected_fx_ents[ level._selected_fx_ents.size - 1 ]; +} + +entities_are_selected() +{ + return level._selected_fx_ents.size > 0; +} + +menu_change_selected_fx() +{ + if ( !level._selected_fx_ents.size ) + return; + + count = 0; + drawnCount = 0; + ent = get_last_selected_ent(); + + for ( i = 0; i < level._createFX_options.size; i++ ) + { + option = level._createFX_options[ i ]; + if ( !isdefined( ent.v[ option[ "name" ] ] ) ) + continue; + count++ ; + if ( count < level._effect_list_offset ) + continue; + + drawnCount++ ; + button_to_check = drawnCount; + if ( button_to_check == 10 ) + button_to_check = 0; + + if ( button_is_clicked( button_to_check + "" ) ) + { + prepare_option_for_change( option, drawnCount ); + break; + } + + if ( drawnCount > level._effect_list_offset_max ) + { + more = true; + break; + } + } +} + +prepare_option_for_change( option, drawnCount ) +{ + if ( option[ "name" ] == "fxid" ) + { + setMenu( "change_fxid" ); + draw_effects_list(); + return; + } + + createfx_centerprint( "To change " + option[ "description" ] + " on selected entities, type /fx newvalue" ); + level._createfx_inputlocked = true; + set_option_index( option[ "name" ] ); + setdvar( "fx", "nil" ); + // change color of text to look selected + level._createFxHudElements[ drawnCount + 3 ][ 0 ].color = ( 1, 1, 0 ); +} + +menu_fx_option_set() +{ + if ( getdvar( "fx" ) == "nil" ) + return; + + option = get_selected_option(); + setting = undefined; + if ( option[ "type" ] == "string" ) + setting = getdvar( "fx" ); + if ( option[ "type" ] == "int" ) + setting = getdvarint( "fx" ); + if ( option[ "type" ] == "float" ) + setting = getdvarfloat( "fx" ); + + apply_option_to_selected_fx( option, setting ); +} + +apply_option_to_selected_fx( option, setting ) +{ + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + + if ( mask( option[ "mask" ], ent.v[ "type" ] ) ) + ent.v[ option[ "name" ] ] = setting; + } + + level._last_displayed_ent = undefined; // needed to force a redraw of the last display ent + update_selected_entities(); + clear_settable_fx(); +} + +set_option_index( name ) +{ + for ( i = 0; i < level._createFX_options.size; i++ ) + { + if ( level._createFX_options[ i ][ "name" ] != name ) + continue; + + level._selected_fx_option_index = i; + return; + } +} + +get_selected_option() +{ + return level._createFX_options[ level._selected_fx_option_index ]; +} + +mask( type, name ) +{ + return isdefined( level._createfxMasks[ type ][ name ] ); +} + +addOption( type, name, description, defaultSetting, mask ) +{ + option = []; + option[ "type" ] = type; + option[ "name" ] = name; + option[ "description" ] = description; + option[ "default" ] = defaultSetting; + option[ "mask" ] = mask; + level._createFX_options[ level._createFX_options.size ] = option; +} + +get_option( name ) +{ + for ( i = 0; i < level._createFX_options.size; i++ ) + { + if ( level._createFX_options[ i ][ "name" ] == name ) + return level._createFX_options[ i ]; + } +} + +display_fx_info( ent ) +{ + // are we doing the create fx menu right now? + if ( !menu( "none" ) ) + return; + + clear_fx_hudElements(); + + set_fx_hudElement( "Name: " + ent.v[ "fxid" ] ); + set_fx_hudElement( "Type: " + ent.v[ "type" ] ); + set_fx_hudElement( "Origin: " + ent.v[ "origin" ] ); + set_fx_hudElement( "Angles: " + ent.v[ "angles" ] ); + + if ( entities_are_selected() ) + { + // if entities are selected then we make the entity stats modifiable + count = 0; + drawnCount = 0; + more = false; + for ( i = 0; i < level._createFX_options.size; i++ ) + { + option = level._createFX_options[ i ]; + if ( !isdefined( ent.v[ option[ "name" ] ] ) ) + continue; + count++ ; + if ( count < level._effect_list_offset ) + continue; + + drawnCount++ ; + + //set_fx_hudElement( drawnCount + ". " + option[ "description" ] + ": " + ent.v[ option[ "name" ] ] ); + set_fx_hudElement( "(" + drawnCount + ") " + option[ "description" ] + ": " + ent.v[ option[ "name" ] ] ); + + if ( drawnCount > level._effect_list_offset_max ) + { + more = true; + break; + } + } + + if ( count > level._effect_list_offset_max ) + set_fx_hudElement( "(m) More >" ); + + set_fx_hudElement( "(a) Add >" ); + set_fx_hudElement( "(t) Change Type >" ); + set_fx_hudElement( "(x) Exit >" ); + } + else + { + count = 0; + more = false; + for ( i = 0; i < level._createFX_options.size; i++ ) + { + option = level._createFX_options[ i ]; + if ( !isdefined( ent.v[ option[ "name" ] ] ) ) + continue; + count++ ; + set_fx_hudElement( option[ "description" ] + ": " + ent.v[ option[ "name" ] ] ); + if ( count > level._createFx_hudElements ) + break; + } + } +} + +display_fx_add_options( ent ) +{ + // are we doing the create fx menu right now? + assert( menu( "add_options" ) ); + assert( entities_are_selected() ); + + clear_fx_hudElements(); + set_fx_hudElement( "Name: " + ent.v[ "fxid" ] ); + set_fx_hudElement( "Type: " + ent.v[ "type" ] ); + set_fx_hudElement( "Origin: " + ent.v[ "origin" ] ); + set_fx_hudElement( "Angles: " + ent.v[ "angles" ] ); + + // if entities are selected then we make the entity stats modifiable + count = 0; + drawnCount = 0; + more = false; + + if ( level._effect_list_offset >= level._createFX_options.size ) + level._effect_list_offset = 0; + + for ( i = 0; i < level._createFX_options.size; i++ ) + { + option = level._createFX_options[ i ]; + if ( isdefined( ent.v[ option[ "name" ] ] ) ) + continue; + + // does this type of effect get this kind of option? + if ( !mask( option[ "mask" ], ent.v[ "type" ] ) ) + continue; + + count++ ; + if ( count < level._effect_list_offset ) + continue; + if ( drawnCount >= level._effect_list_offset_max ) + continue; + + drawnCount++ ; + button_to_check = drawnCount; + if ( button_to_check == 10 ) + button_to_check = 0; + if ( button_is_clicked( button_to_check + "" ) ) + { + add_option_to_selected_entities( option ); +// prepare_option_for_change( option, drawnCount ); + menuNone(); + level._last_displayed_ent = undefined; // needed to force a redraw of the last display ent + return; + } + + set_fx_hudElement( button_to_check + ". " + option[ "description" ] ); + } + + if ( count > level._effect_list_offset_max ) + set_fx_hudElement( "(m) More >" ); + + set_fx_hudElement( "(x) Exit >" ); +} + +display_fx_type_options() +{ + clear_fx_hudElements(); + set_fx_hudElement( "(1) Ambient/OneShot fx" ); + set_fx_hudElement( "(2) Scripted/Exploder fx" ); + set_fx_hudElement( "(x) Exit" ); +} + +add_option_to_selected_entities( option ) +{ + setting = undefined; + for ( i = 0; i < level._selected_fx_ents.size; i++ ) + { + ent = level._selected_fx_ents[ i ]; + + if ( mask( option[ "mask" ], ent.v[ "type" ] ) ) + ent.v[ option[ "name" ] ] = option[ "default" ]; + } +} + +menuNone() +{ + level._effect_list_offset = 0; + clear_fx_hudElements(); + setMenu( "none" ); +} + + +draw_effects_list() +{ + + clear_fx_hudElements(); + + set_fx_hudElement( "Pick an effect:" ); + count = 0; + more = false; + + keys = func_get_level_fx(); + + if ( level._effect_list_offset >= keys.size ) + level._effect_list_offset = 0; + + for ( i = level._effect_list_offset; i < keys.size; i++ ) + { + count = count + 1; + set_fx_hudElement( count + ". " + keys[ i ] ); + if ( count >= level._effect_list_offset_max ) + { + more = true; + break; + } + } + + if ( keys.size > level._effect_list_offset_max ) + set_fx_hudElement( "(m) More >" ); +} + +increment_list_offset() +{ + level._effect_list_offset += level._effect_list_offset_max; +// keys = getarraykeys(level._effect); +// if (level.effect_list_offset >= keys.size) +// level.effect_list_offset = 0; +} \ No newline at end of file diff --git a/common_scripts/_destructible.gsc b/common_scripts/_destructible.gsc new file mode 100644 index 0000000..0b4836c --- /dev/null +++ b/common_scripts/_destructible.gsc @@ -0,0 +1,3324 @@ +#include common_scripts\utility; +#using_animtree( "destructibles" ); + +// Car alarm constants +MAX_SIMULTANEOUS_CAR_ALARMS = 2; +CAR_ALARM_ALIAS = "car_alarm"; +CAR_ALARM_OFF_ALIAS = "car_alarm_off"; +NO_CAR_ALARM_MAX_ELAPSED_TIME = 120; +CAR_ALARM_TIMEOUT = 25; +DESTROYED_ATTACHMENT_SUFFIX = "_destroy"; + +SP_DAMAGE_BIAS = 0.5; +SP_EXPLOSIVE_DAMAGE_BIAS = 9.0; + +MP_DAMAGE_BIAS = 1.0; +MP_EXPLOSIVE_DAMAGE_BIAS = 13.0; + +SP_SHOTGUN_BIAS = 8.0; +MP_SHOTGUN_BIAS = 4.0; + +init() +{ + /# + SetDevDvarIfUninitialized( "debug_destructibles", "0" ); + SetDevDvarIfUninitialized( "destructibles_enable_physics", "1" ); + SetDevDvarIfUninitialized( "destructibles_show_radiusdamage", "0" ); + #/ + + level._destructibleSpawnedEntsLimit = 50; + level._destructibleSpawnedEnts = []; + level._currentCarAlarms = 0; + level._commonStartTime = GetTime(); + + /# + level._created_destructibles = []; + #/ + + if ( !isdefined( level._func ) ) + { + // this array will be filled with code commands that SP or MP may use but doesn't exist in the other. + level._func = []; + } + + destructibles_enabled = true; + /# + destructibles_enabled = ( GetDvarInt( "destructibles_enabled", 1 ) == 1 ); + #/ + + if ( destructibles_enabled ) + find_destructibles(); + + deletables = GetEntArray( "delete_on_load", "targetname" ); + foreach ( ent in deletables ) + ent Delete(); + + /# + SetDevDvarIfUninitialized( "scr_destructible_warning", "1" ); + if ( GetDvarInt( "scr_destructible_warning", 1 ) == 1 ) + thread warn_about_old_destructible(); + #/ + + init_destroyed_count(); + init_destructible_frame_queue(); +} + +warn_about_old_destructible() +{ + wait 1; + + // Find all old prefabs and print warning/errors about them so they get updated + destructibles = GetEntArray( "destructible", "targetname" ); + if ( destructibles.size != 0 ) + { + PrintLn( "This map contains old destructible vehicle prefabs which no longer work properly. Please update them to use the new vehicle prefabs in map_source\\prefabs\\destructible\\. See console for a list of vehicles that you need to updated." ); + + PrintLn( "^1###################################################^0" ); + PrintLn( "^1###################################################^0" ); + PrintLn( "^1###################################################^0" ); + + foreach ( vehicle in destructibles ) + PrintLn( "^1Destructible vehicle at ( " + vehicle.origin + " ) uses an old prefab. Update it to use a prefab located in prefabs\destructible\^0" ); + + PrintLn( "^1###################################################^0" ); + PrintLn( "^1###################################################^0" ); + PrintLn( "^1###################################################^0" ); + + AssertMsg( "This map contains old destructible vehicle prefabs which no longer work properly. Please update them to use the new vehicle prefabs in map_source\\prefabs\\destructible\\. See console for a list of vehicles that you need to updated." ); + } +} + +find_destructibles() +{ + //--------------------------------------------------------------------- + // Find all destructibles by their targetnames and run the setup + //--------------------------------------------------------------------- + +// array_thread( GetEntArray( "destructible_vehicle", "targetname" ), ::setup_destructibles ); + + //assuring orders -nate + vehicles = GetEntArray( "destructible_vehicle", "targetname" ); + foreach ( vehicle in vehicles ) + vehicle setup_destructibles(); + + destructible_toy = GetEntArray( "destructible_toy", "targetname" ); + foreach ( toy in destructible_toy ) + toy setup_destructibles(); + + /# + total = 0; + if ( GetDvarInt( "destructibles_locate" ) > 0 ) + { + // Print out the destructibles we created and where they are all located + PrintLn( "##################" ); + PrintLn( "DESTRUCTIBLE LIST:" ); + PrintLn( "##################" ); + PrintLn( "" ); + + keys = GetArrayKeys( level._created_destructibles ); + foreach ( key in keys ) + { + PrintLn( key + ": " + level._created_destructibles[ key ].size ); + total += level._created_destructibles[ key ].size; + } + PrintLn( "" ); + PrintLn( "Total: " + total ); + PrintLn( "" ); + PrintLn( "Locations:" ); + + foreach ( key in keys ) + { + foreach ( destructible in level._created_destructibles[ key ] ) + { + PrintLn( key + ": " + destructible.origin ); + //destructible thread maps\_debug::drawOrgForever(); + } + } + + PrintLn( "" ); + PrintLn( "##################" ); + PrintLn( "##################" ); + PrintLn( "##################" ); + + level._created_destructibles = undefined; + } + #/ + +} + +setup_destructibles( cached ) +{ + if ( !isdefined( cached ) ) + cached = false; + + //--------------------------------------------------------------------- + // Figure out what destructible information this entity should use + //--------------------------------------------------------------------- + destuctableInfo = undefined; + AssertEx( IsDefined( self.destructible_type ), "Destructible object with targetname 'destructible' does not have a 'destructible_type' key / value" ); + + self.modeldummyon = false;// - nate added for vehicle dummy stuff. This is so I can turn a destructible into a dummy and throw it around on jeepride. + self add_damage_owner_recorder(); // Mackey added to track who is damaging the car + + self.destuctableInfo = common_scripts\_destructible_types::makeType( self.destructible_type ); + //println( "### DESTRUCTIBLE ### assigned infotype index: " + self.destuctableInfo ); + if ( self.destuctableInfo < 0 ) + return; + + /# + // Store what destructibles we create and where they are located so we can get a list in the console + if ( !isdefined( level._created_destructibles[ self.destructible_type ] ) ) + level._created_destructibles[ self.destructible_type ] = []; + nextIndex = level._created_destructibles[ self.destructible_type ].size; + level._created_destructibles[ self.destructible_type ][ nextIndex ] = self; + #/ + + if ( !cached ) + precache_destructibles(); + + add_destructible_fx(); + + //--------------------------------------------------------------------- + // Attach all parts to the entity + //--------------------------------------------------------------------- + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + { + self.destructible_parts = []; + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts.size; i++ ) + { + // create the struct where the info for each entity will be held + self.destructible_parts[ i ] = SpawnStruct(); + + // set it's current state to 0 since it has never taken damage yet and will be on it's first state + self.destructible_parts[ i ].v[ "currentState" ] = 0; + + // if it has a health value then store it's value + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "health" ] ) ) + self.destructible_parts[ i ].v[ "health" ] = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "health" ]; + + // find random attachements such as random advertisements on taxi cabs and attach them now + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "random_dynamic_attachment_1" ] ) ) + { + randAttachmentIndex = RandomInt( level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "random_dynamic_attachment_1" ].size ); + attachTag = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "random_dynamic_attachment_tag" ][ randAttachmentIndex ]; + attach_model_1 = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "random_dynamic_attachment_1" ][ randAttachmentIndex ]; + attach_model_2 = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "random_dynamic_attachment_2" ][ randAttachmentIndex ]; + clipToRemove = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "clipToRemove" ][ randAttachmentIndex ]; + self thread do_random_dynamic_attachment( attachTag, attach_model_1, attach_model_2, clipToRemove ); + } + + // continue if it's the base model since its not an attached part + if ( i == 0 ) + continue; + + // attach the part now + modelName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "modelName" ]; + tagName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "tagName" ]; + + stateIndex = 1; + while ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ] ) ) + { + stateTagName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "tagName" ]; + stateModelName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "modelName" ]; + if ( IsDefined( stateTagName ) && stateTagName != tagName ) + { + self hideapart( stateTagName ); + if ( self.modeldummyon ) + self.modeldummy hideapart( stateTagName ); + } + stateIndex++; + } + } + } + + // some destructibles have collision that needs to change due to the large change in the destructible when it blows pu + if ( IsDefined( self.target ) ) + thread destructible_handles_collision_brushes(); + + //--------------------------------------------------------------------- + // Make this entity take damage and wait for events + //--------------------------------------------------------------------- + if ( self.code_classname != "script_vehicle" ) + self SetCanDamage( true ); + if ( isSP() ) + self thread connectTraverses(); + self thread destructible_think(); +} + +destructible_create( type, tagName, health, validAttackers, validDamageZone, validDamageCause ) +{ + //--------------------------------------------------------------------- + // Creates a new information structure for a destructible object + //--------------------------------------------------------------------- + Assert( IsDefined( type ) ); + + if ( !isdefined( level._destructible_type ) ) + level._destructible_type = []; + + destructibleIndex = level._destructible_type.size; + + + destructibleIndex = level._destructible_type.size; + level._destructible_type[ destructibleIndex ] = SpawnStruct(); + level._destructible_type[ destructibleIndex ].v[ "type" ] = type; + + level._destructible_type[ destructibleIndex ].parts = []; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ] = SpawnStruct(); + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "modelName" ] = self.model; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "tagName" ] = tagName; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "health" ] = health; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "validAttackers" ] = validAttackers; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "validDamageZone" ] = validDamageZone; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "validDamageCause" ] = validDamageCause; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "godModeAllowed" ] = true; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "rotateTo" ] = self.angles; + level._destructible_type[ destructibleIndex ].parts[ 0 ][ 0 ].v[ "vehicle_exclude_anim" ] = false; +} + +destructible_part( tagName, modelName, health, validAttackers, validDamageZone, validDamageCause, alsoDamageParent, physicsOnExplosion, grenadeImpactDeath, receiveDamageFromParent ) +{ + //--------------------------------------------------------------------- + // Adds a part to the last created destructible information structure + //--------------------------------------------------------------------- + destructibleIndex = ( level._destructible_type.size - 1 ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts.size ) ); + + partIndex = level._destructible_type[ destructibleIndex ].parts.size; + Assert( partIndex > 0 ); + + stateIndex = 0; + + destructible_info( partIndex, stateIndex, tagName, modelName, health, validAttackers, validDamageZone, validDamageCause, alsoDamageParent, physicsOnExplosion, grenadeImpactDeath, undefined, receiveDamageFromParent ); +} + +destructible_state( tagName, modelName, health, validAttackers, validDamageZone, validDamageCause, grenadeImpactDeath, splashRotation ) +{ + //--------------------------------------------------------------------- + // Adds a new part that is a state of the last created part + // When the previous part reaches zero health this part will show up + // and the previous part will be removed + //--------------------------------------------------------------------- + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size ); + + if ( !isdefined( tagName ) && partIndex == 0 ) + tagName = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ 0 ].v[ "tagName" ]; + + destructible_info( partIndex, stateIndex, tagName, modelName, health, validAttackers, validDamageZone, validDamageCause, undefined, undefined, grenadeImpactDeath, splashRotation ); +} + +destructible_fx( tagName, fxName, useTagAngles, damageType, groupNum, fxCost ) +{ + //assert( IsDefined( tagName ) ); + Assert( IsDefined( fxName ) ); + + if ( !isdefined( useTagAngles ) ) + useTagAngles = true; + + if ( !isdefined( groupNum ) ) + groupNum = 0; + + if ( !isdefined( fxCost ) ) + fxCost = 0; + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + fx_size = 0; + if ( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_filename" ] ) ) + if ( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_filename" ][ groupNum ] ) ) + fx_size = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_filename" ][ groupNum ].size; + + if ( IsDefined( damageType ) ) + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_valid_damagetype" ][ groupNum ][ fx_size ] = damageType; + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_filename" ][ groupNum ][ fx_size ] = fxName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_tag" ][ groupNum ][ fx_size ] = tagName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_useTagAngles" ][ groupNum ][ fx_size ] = useTagAngles; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "fx_cost" ][ groupNum ][ fx_size ] = fxCost; +} + +destructible_loopfx( tagName, fxName, loopRate, fxCost ) +{ + Assert( IsDefined( tagName ) ); + Assert( IsDefined( fxName ) ); + Assert( IsDefined( loopRate ) ); + Assert( loopRate > 0 ); + + if ( !isdefined( fxCost ) ) + fxCost = 0; + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + fx_size = 0; + if ( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_filename" ] ) ) + fx_size = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_filename" ].size; + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_filename" ][ fx_size ] = fxName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_tag" ][ fx_size ] = tagName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_rate" ][ fx_size ] = loopRate; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopfx_cost" ][ fx_size ] = fxCost; +} + +destructible_healthdrain( amount, interval, badplaceRadius, badplaceTeam ) +{ + Assert( IsDefined( amount ) ); + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "healthdrain_amount" ] = amount; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "healthdrain_interval" ] = interval; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "badplace_radius" ] = badplaceRadius; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "badplace_team" ] = badplaceTeam; +} + +destructible_sound( soundAlias, soundCause, groupNum ) +{ + Assert( IsDefined( soundAlias ) ); + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + if ( !isdefined( groupNum ) ) + groupNum = 0; + + if ( !isdefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ] ) ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "soundCause" ] = []; + } + + if ( !isdefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ][ groupNum ] ) ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ][ groupNum ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "soundCause" ][ groupNum ] = []; + } + + index = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ][ groupNum ].size; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "sound" ][ groupNum ][ index ] = soundAlias; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "soundCause" ][ groupNum ][ index ] = soundCause; +} + + +destructible_loopsound( soundAlias, loopsoundCause ) +{ + Assert( IsDefined( soundAlias ) ); + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + if ( !isdefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsound" ] ) ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsound" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsoundCause" ] = []; + } + + index = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsound" ].size; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsound" ][ index ] = soundAlias; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "loopsoundCause" ][ index ] = loopsoundCause; +} + +destructible_anim( animName, animTree, animType, vehicle_exclude, groupNum, mpAnim, maxStartDelay, animRateMin, animRateMax ) +{ + if ( !isdefined( vehicle_exclude ) ) + vehicle_exclude = false; + + Assert( IsDefined( anim ) ); + Assert( IsDefined( animName ) ); + Assert( IsDefined( animtree ) ); + + if ( !isdefined( groupNum ) ) + groupNum = 0; + + array = []; + array[ "anim" ] = animName; + array[ "animTree" ] = animtree; + array[ "animType" ] = animType; + array[ "vehicle_exclude_anim" ] = vehicle_exclude; + array[ "groupNum" ] = groupNum; + array[ "mpAnim" ] = mpAnim; + array[ "maxStartDelay" ] = maxStartDelay; + array[ "animRateMin" ] = animRateMin; + array[ "animRateMax" ] = animRateMax; + add_array_to_destructible( "animation", array ); +} + +destructible_spotlight( tag ) +{ + AssertEx( IsDefined( tag ), "Tag wasn't defined for destructible_spotlight" ); + array = []; + array[ "spotlight_tag" ] = tag; + array[ "spotlight_fx" ] = "spotlight_fx"; + array[ "spotlight_brightness" ] = 0.85; + array[ "randomly_flip" ] = true; + + dvars = []; + dvars[ "r_spotlightendradius" ] = 1200; + dvars[ "r_spotlightstartradius" ] = 50; + array[ "dvars" ] = dvars; + + add_keypairs_to_destructible( array ); +} + +add_key_to_destructible( key, val ) +{ + AssertEx( IsDefined( key ), "Key wasn't defined!" ); + AssertEx( IsDefined( val ), "Val wasn't defined!" ); + + array = []; + array[ key ] = val; + add_keypairs_to_destructible( array ); +} + +/* +============= +///ScriptDocBegin +"Name: add_keypairs_to_destructible( )" +"Summary: Goes through the array and adds each key/val to .v." +"Module: Destructibles" +"MandatoryArg: : Array of keypairs." +"Example: add_keypairs_to_destructible( array );" +"SPMP: singleplayer" +///ScriptDocEnd +============= +*/ +add_keypairs_to_destructible( array ) +{ + // add a single flat array to the destructible, overwriting any existing identical keys. + destructibleIndex = level._destructible_type.size - 1; + partIndex = level._destructible_type[ destructibleIndex ].parts.size - 1; + stateIndex = level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1; + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + foreach ( key, val in array ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ key ] = val; + } +} + +/* +============= +///ScriptDocBegin +"Name: add_array_to_destructible( , )" +"Summary: Goes through the array and adds each key/val to .v." +"Module: Destructibles" +"MandatoryArg: : Array of keypairs." +"MandatoryArg: : Array of keypairs." +"Example: add_array_to_destructible( array );" +"SPMP: singleplayer" +///ScriptDocEnd +============= +*/ +add_array_to_destructible( array_name, array ) +{ + // add an array under a key name, so you can have multiple arrays under a given key name + destructibleIndex = level._destructible_type.size - 1; + partIndex = level._destructible_type[ destructibleIndex ].parts.size - 1; + stateIndex = level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1; + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + v = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v; + + if ( !isdefined( v[ array_name ] ) ) + { + v[ array_name ] = []; + } + + v[ array_name ][ v[ array_name ].size ] = array; + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v = v; +} + +destructible_car_alarm() +{ + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "triggerCarAlarm" ] = true; +} + +destructible_lights_out( range ) +{ + if ( !isdefined( range ) ) + range = 256; + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "break_nearby_lights" ] = range; +} + +random_dynamic_attachment( tagName, attachment_1, attachment_2, clipToRemove ) +{ + // made so I can put random advertisements on the destructible taxi cabs without making lots of destructible types for each version + + Assert( IsDefined( tagName ) ); + Assert( IsDefined( attachment_1 ) ); + + if ( !isdefined( attachment_2 ) ) + attachment_2 = ""; + + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + //stateIndex = ( level.destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + stateIndex = 0; + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + if ( !isdefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_1" ] ) ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_1" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_2" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_tag" ] = []; + } + + index = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_1" ].size; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_1" ][ index ] = attachment_1; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_2" ][ index ] = attachment_2; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "random_dynamic_attachment_tag" ][ index ] = tagName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "clipToRemove" ][ index ] = clipToRemove; +} + +destructible_physics( physTagName, physVelocity ) +{ + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + if ( !isdefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics" ] ) ) + { + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics_tagName" ] = []; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics_velocity" ] = []; + } + + index = level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics" ].size; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics" ][ index ] = true; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics_tagName" ][ index ] = physTagName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physics_velocity" ][ index ] = physVelocity; +} + +destructible_splash_damage_scaler( damage_multiplier ) +{ + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "splash_damage_scaler" ] = damage_multiplier; +} + +destructible_explode( force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continueDamage, originOffset, earthQuakeScale, earthQuakeRadius ) +{ + destructibleIndex = ( level._destructible_type.size - 1 ); + partIndex = ( level._destructible_type[ destructibleIndex ].parts.size - 1 ); + stateIndex = ( level._destructible_type[ destructibleIndex ].parts[ partIndex ].size - 1 ); + + Assert( IsDefined( level._destructible_type ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ] ) ); + Assert( IsDefined( level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] ) ); + + if ( isSP() ) + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_range" ] = rangeSP; + else + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_range" ] = rangeMP; + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode" ] = true; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_force_min" ] = force_min; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_force_max" ] = force_max; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_mindamage" ] = mindamage; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "explode_maxdamage" ] = maxdamage; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "continueDamage" ] = continueDamage; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "originOffset" ] = originOffset; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "earthQuakeScale" ] = earthQuakeScale; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "earthQuakeRadius" ] = earthQuakeRadius; +} + +destructible_info( partIndex, stateIndex, tagName, modelName, health, validAttackers, validDamageZone, validDamageCause, alsoDamageParent, physicsOnExplosion, grenadeImpactDeath, splashRotation, receiveDamageFromParent ) +{ + Assert( IsDefined( partIndex ) ); + Assert( IsDefined( stateIndex ) ); + Assert( IsDefined( level._destructible_type ) ); + Assert( level._destructible_type.size > 0 ); + + if ( IsDefined( modelName ) ) + modelName = ToLower( modelName ); + + destructibleIndex = ( level._destructible_type.size - 1 ); + + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ] = SpawnStruct(); + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "modelName" ] = modelName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "tagName" ] = tagName; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "health" ] = health; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "validAttackers" ] = validAttackers; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "validDamageZone" ] = validDamageZone; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "validDamageCause" ] = validDamageCause; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "alsoDamageParent" ] = alsoDamageParent; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "physicsOnExplosion" ] = physicsOnExplosion; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "grenadeImpactDeath" ] = grenadeImpactDeath; + // sanity check please. I set this here so that I don't have to do isdefined on every part evertime it gets hit + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "godModeAllowed" ] = false; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "splashRotation" ] = splashRotation; + level._destructible_type[ destructibleIndex ].parts[ partIndex ][ stateIndex ].v[ "receiveDamageFromParent" ] = receiveDamageFromParent; +} + +precache_destructibles() +{ + // I needed this to be seperate for vehicle scripts. + //--------------------------------------------------------------------- + // Precache referenced models and load referenced effects + //--------------------------------------------------------------------- + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + return; + + //if ( !isdefined( level.precachedModels ) ) + // level.precachedModels = []; + + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts.size; i++ ) + { + for ( j = 0; j < level._destructible_type[ self.destuctableInfo ].parts[ i ].size; j++ ) + { + if ( level._destructible_type[ self.destuctableInfo ].parts[ i ].size <= j ) + continue; + + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "modelName" ] ) ) + { + //model = level.destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "modelName" ]; + //if ( !isdefined( level.precachedModels[ model ] ) ) + //{ + // level.precachedModels[ model ] = true; + // println( "precachemodel( " + model + " )" ); + //} + PreCacheModel( level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "modelName" ] ); + } + + // in MP we have to precache animations that will be used + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "animation" ] ) ) + { + animGroups = level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "animation" ]; + foreach ( group in animGroups ) + { + if ( IsDefined( group[ "mpAnim" ] ) ) + noself_func( "precacheMpAnim", group[ "mpAnim" ] ); + } + } + + // find random attachements such as random advertisements on taxi cabs and precache them now + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "random_dynamic_attachment_1" ] ) ) + { + foreach ( model in level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "random_dynamic_attachment_1" ] ) + { + if ( IsDefined( model ) && model != "" ) + { + PreCacheModel( model ); + PreCacheModel( model + DESTROYED_ATTACHMENT_SUFFIX ); + + //if ( !isdefined( level.precachedModels[ model ] ) ) + //{ + // level.precachedModels[ model ] = true; + // println( "precachemodel( " + model + " )" ); + //} + + //if ( !isdefined( level.precachedModels[ model + DESTROYED_ATTACHMENT_SUFFIX ] ) ) + //{ + // level.precachedModels[ model + DESTROYED_ATTACHMENT_SUFFIX ] = true; + // println( "precachemodel( " + model + DESTROYED_ATTACHMENT_SUFFIX + " )" ); + //} + } + } + foreach ( model in level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "random_dynamic_attachment_2" ] ) + { + if ( IsDefined( model ) && model != "" ) + { + PreCacheModel( model ); + PreCacheModel( model + DESTROYED_ATTACHMENT_SUFFIX ); + + //if ( !isdefined( level.precachedModels[ model ] ) ) + //{ + // level.precachedModels[ model ] = true; + // println( "precachemodel( " + model + " )" ); + //} + + //if ( !isdefined( level.precachedModels[ model + DESTROYED_ATTACHMENT_SUFFIX ] ) ) + //{ + // level.precachedModels[ model + DESTROYED_ATTACHMENT_SUFFIX ] = true; + // println( "precachemodel( " + model + DESTROYED_ATTACHMENT_SUFFIX + " )" ); + //} + } + } + } + } + } +} + +add_destructible_fx() +{ + // I needed this to be seperate for vehicle scripts. + //--------------------------------------------------------------------- + // Precache referenced models and load referenced effects + //--------------------------------------------------------------------- + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + return; + + //if ( !isdefined( level.precachedFX ) ) + // level.precachedFX = []; + + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts.size; i++ ) + { + for ( j = 0; j < level._destructible_type[ self.destuctableInfo ].parts[ i ].size; j++ ) + { + if ( level._destructible_type[ self.destuctableInfo ].parts[ i ].size <= j ) + continue; + + part = level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ]; + + if ( IsDefined( part.v[ "fx_filename" ] ) ) + { + for ( g = 0; g < part.v[ "fx_filename" ].size; g++ ) + { + // for multiple checks on fx when doing conditional fx playing + fx_filenames = part.v[ "fx_filename" ][ g ]; + if ( IsDefined( fx_filenames ) ) + { + // has we already set this up? + if ( IsDefined( part.v[ "fx" ] ) && IsDefined( part.v[ "fx" ][ g ] ) && part.v[ "fx" ][ g ].size == fx_filenames.size ) + continue; + + foreach ( idx, fx_filename in fx_filenames ) + { + level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "fx" ][ g ][ idx ] = _loadfx( fx_filename ); + + //if ( !isdefined( level.precachedFX[ fx_filename ] ) ) + //{ + // level.precachedFX[ fx_filename ] = true; + // println( "loadfx( " + fx_filename + " )" ); + //} + } + } + } + } + + loopfx_filenames = level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "loopfx_filename" ]; + if ( IsDefined( loopfx_filenames ) ) + { + // has we already set this up? + if ( IsDefined( part.v[ "loopfx" ] ) && part.v[ "loopfx" ].size == loopfx_filenames.size ) + continue; + + foreach ( idx, loopfx_filename in loopfx_filenames ) + { + level._destructible_type[ self.destuctableInfo ].parts[ i ][ j ].v[ "loopfx" ][ idx ] = _loadfx( loopfx_filename ); + + //if ( !isdefined( level.precachedFX[ loopfx_filename ] ) ) + //{ + // level.precachedFX[ loopfx_filename ] = true; + // println( "loadfx( " + loopfx_filename + " )" ); + //} + } + } + } + } + +} + + +canDamageDestructible( testDestructible ) +{ + foreach ( destructible in self.destructibles ) + { + if ( destructible == testDestructible ) + return true; + } + return false; +} + +destructible_think() +{ + //--------------------------------------------------------------------- + // Force it to run update part one time first so we can have parts with + // 0 health that will start on level load instead of waiting for damage + //--------------------------------------------------------------------- + damage = 0; + modelName = self.model; + tagName = undefined; + point = self.origin; + direction_vec = undefined; + attacker = undefined; + damageType = undefined; + self destructible_update_part( damage, modelName, tagName, point, direction_vec, attacker, damageType ); + + //--------------------------------------------------------------------- + // Wait until this entity takes damage + //--------------------------------------------------------------------- + self endon( "stop_taking_damage" ); + for ( ;; ) + { + // set these to undefined to clear them for each loop to save variables + damage = undefined; + attacker = undefined; + direction_vec = undefined; + point = undefined; + type = undefined; + modelName = undefined; + tagName = undefined; + partName = undefined; + dflags = undefined; + + self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, dflags ); + prof_begin( "_destructible" ); + + if ( !isdefined( damage ) ) + continue; + if ( IsDefined( attacker ) && IsDefined( attacker.type ) && attacker.type == "soft_landing" && !attacker canDamageDestructible( self ) ) + continue; + + if ( isSP() ) + damage *= SP_DAMAGE_BIAS; + else + damage *= MP_DAMAGE_BIAS; + + if ( damage <= 0 ) + continue; + + if ( IsDefined( attacker ) && IsPlayer( attacker ) ) + self.damageOwner = attacker; + + type = getDamageType( type ); + Assert( IsDefined( type ) ); + + // shotguns only do one notify so we need to amp up the damage + if ( is_shotgun_damage( attacker, type ) ) + { + if ( isSP() ) + damage *= SP_SHOTGUN_BIAS; + else + damage *= MP_SHOTGUN_BIAS; + } + + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + { + Print3d( point, ".", ( 1, 1, 1 ), 1.0, 0.5, 100 ); + if ( IsDefined( damage ) ) + IPrintLn( "damage amount: " + damage ); + if ( IsDefined( modelName ) ) + IPrintLn( "hit model: " + modelName ); + if ( IsDefined( tagName ) ) + IPrintLn( "hit model tag: " + tagName ); + else + IPrintLn( "hit model tag: " ); + } + #/ + + // override for when base model is damaged. We dont want to pass in empty strings + if ( !isdefined( modelName ) || ( modelName == "" ) ) + { + Assert( IsDefined( self.model ) ); + modelName = self.model; + } + if ( IsDefined( tagName ) && tagName == "" ) + { + if ( IsDefined( partName ) && partName != "" && partName != "tag_body" && partName != "body_animate_jnt" ) + tagName = partName; + else + tagName = undefined; + + baseModelTag = level._destructible_type[ self.destuctableInfo ].parts[ 0 ][ 0 ].v[ "tagName" ]; + if ( IsDefined( baseModelTag ) && IsDefined( partName ) && ( baseModelTag == partName ) ) + tagName = undefined; + } + + prof_end( "_destructible" ); + + // special handling for splash and projectile damage + if ( type == "splash" ) + { + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + IPrintLn( "type = splash" ); + #/ + + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ 0 ][ 0 ].v[ "splash_damage_scaler" ] ) ) + damage *= level._destructible_type[ self.destuctableInfo ].parts[ 0 ][ 0 ].v[ "splash_damage_scaler" ]; + else + { + if ( isSP() ) + damage *= SP_EXPLOSIVE_DAMAGE_BIAS; + else + damage *= MP_EXPLOSIVE_DAMAGE_BIAS; + } + + self destructible_splash_damage( Int( damage ), point, direction_vec, attacker, type ); + continue; + } + + self thread destructible_update_part( Int( damage ), modelName, tagName, point, direction_vec, attacker, type ); + } +} + +is_shotgun_damage( attacker, type ) +{ + if ( type != "bullet" ) + return false; + + if ( !isdefined( attacker ) ) + return false; + + currentWeapon = undefined; + if ( IsPlayer( attacker ) ) + { + currentweapon = attacker getCurrentWeapon(); + } + + if ( !isdefined( currentweapon ) ) + return false; + + class = weaponClass( currentweapon ); + if ( isdefined( class ) && class == "spread" ) + return true; + + return false; +} + +getPartAndStateIndex( modelName, tagName ) +{ + Assert( IsDefined( modelName ) ); + + info = SpawnStruct(); + info.v = []; + + partIndex = -1; + stateIndex = -1; + Assert( IsDefined( self.model ) ); + if ( ( ToLower( modelName ) == ToLower( self.model ) ) && ( !isdefined( tagName ) ) ) + { + modelName = self.model; + tagName = undefined; + partIndex = 0; + stateIndex = 0; + } + + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts.size; i++ ) + { + stateIndex = self.destructible_parts[ i ].v[ "currentState" ]; + + if ( level._destructible_type[ self.destuctableInfo ].parts[ i ].size <= stateIndex ) + continue; + + if ( !isdefined( tagName ) ) + continue; + + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "tagName" ] ) ) + { + partTagName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "tagName" ]; + if ( partTagName == tagName ) + { + partIndex = i; + break; + } + } + } + Assert( stateIndex >= 0 ); + Assert( IsDefined( partIndex ) ); + + info.v[ "stateIndex" ] = stateindex; + info.v[ "partIndex" ] = partindex; + + return info; +} + +destructible_update_part( damage, modelName, tagName, point, direction_vec, attacker, damageType, partInfo ) +{ + //--------------------------------------------------------------------- + // Find what part this is, or is a child of. If the base model was + // the entity that was damaged the part index will be -1 + //--------------------------------------------------------------------- + if ( !isdefined( self.destructible_parts ) ) + return; + if ( self.destructible_parts.size == 0 ) + return; + + prof_begin( "_destructible" ); + + info = getPartAndStateIndex( modelName, tagName ); + stateIndex = info.v[ "stateIndex" ]; + partIndex = info.v[ "partIndex" ]; + + prof_end( "_destructible" ); + + if ( partIndex < 0 ) + return; + + //--------------------------------------------------------------------- + // Deduct the damage amount from the part's health + // If the part runs out of health go to the next state + //--------------------------------------------------------------------- + state_before = stateIndex; + updateHealthValue = false; + delayModelSwap = false; + prof_begin( "_destructible" ); + for ( ;; ) + { + stateIndex = self.destructible_parts[ partIndex ].v[ "currentState" ]; + if( 3 == stateIndex ) + { + wtf = 1; + } + + // there isn't another state to go to when damaged + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ] ) ) + break; + + // see if the model is also supposed to damage the parent + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ 0 ].v[ "alsoDamageParent" ] ) ) + { + if ( getDamageType( damageType ) != "splash" ) + { + ratio = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ 0 ].v[ "alsoDamageParent" ]; + parentDamage = Int( damage * ratio ); + self thread notifyDamageAfterFrame( parentDamage, attacker, direction_vec, point, damageType, "", "" ); + } + } + + // loop through all parts to see which ones also need to get this damage applied to them ( based on their "receiveDamageFromParent" value ) + if ( getDamageType( damageType ) != "splash" ) + { + foreach ( part in level._destructible_type[ self.destuctableInfo ].parts ) + { + if ( !isdefined( part[ 0 ].v[ "receiveDamageFromParent" ] ) ) + continue; + + if ( !isdefined( part[ 0 ].v[ "tagName" ] ) ) + continue; + + ratio = part[ 0 ].v[ "receiveDamageFromParent" ]; + Assert( ratio > 0 ); + + childDamage = Int( damage * ratio ); + childTagName = part[ 0 ].v[ "tagName" ]; + self thread notifyDamageAfterFrame( childDamage, attacker, direction_vec, point, damageType, "", childTagName ); + } + } + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "health" ] ) ) + break; + if ( !isdefined( self.destructible_parts[ partIndex ].v[ "health" ] ) ) + break; + + if ( updateHealthValue ) + self.destructible_parts[ partIndex ].v[ "health" ] = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "health" ]; + updateHealthValue = false; + + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + { + IPrintLn( "stateindex: " + stateIndex ); + IPrintLn( "damage: " + damage ); + IPrintLn( "health( before ): " + self.destructible_parts[ partIndex ].v[ "health" ] ); + } + #/ + + // Handle grenades hitting glass parts. Grenades should make the glass completely break instead of just doing 1 damage and shattering the glass + if ( ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "grenadeImpactDeath" ] ) ) && ( damageType == "impact" ) ) + damage = 100000000; + + // apply the damage to the part if the attacker was a valid attacker + savedHealth = self.destructible_parts[ partIndex ].v[ "health" ]; + validAttacker = self isAttackerValid( partIndex, stateIndex, attacker ); + if ( validAttacker ) + { + validDamageCause = self isValidDamageCause( partIndex, stateIndex, damageType ); + if ( validDamageCause ) + { + if ( IsDefined( attacker ) ) + { + if ( IsPlayer( attacker ) ) + { + self.player_damage += damage; + } + else + { + if ( attacker != self ) + self.non_player_damage += damage; + } + } + + // Chad - ask Brent why we think melee is worth 100000 damage + if ( IsDefined( damageType ) ) + { + if ( damageType == "melee" || damageType == "impact" ) + { + validType = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "validDamageCause" ]; + + if ( IsDefined( validType ) ) + { + if ( validType != "no_melee_yes_impact" ) + { + damage = 100000; + } + } + else + { + damage = 100000; + } + } + } + + self.destructible_parts[ partIndex ].v[ "health" ] -= damage; + } + } + + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + IPrintLn( "health( after ): " + self.destructible_parts[ partIndex ].v[ "health" ] ); + #/ + + // if the part still has health left then we're done + if ( self.destructible_parts[ partIndex ].v[ "health" ] > 0 ) + { + prof_end( "_destructible" ); + return; + } + + // cap on the number of destructibles killed in a single frame + if ( IsDefined( partInfo ) ) + { + partInfo.v[ "fxcost" ] = get_part_FX_cost_for_action_state( partIndex, self.destructible_parts[ partIndex ].v[ "currentState" ] ); + + add_destructible_to_frame_queue( self, partInfo, damage ); + + self.waiting_for_queue = true; + self waittill( "queue_processed", success ); + self.waiting_for_queue = undefined; + + if ( !success )// can we be destroyed this frame? + { + self.destructible_parts[ partIndex ].v[ "health" ] = savedHealth; + return; + } + } + + // if the part ran out of health then carry over to the next part + //damage = Int( abs( self.destructible_parts[ partIndex ].v[ "health" ] ) ); + + // Brent asks - why is this condition here? It'll never trigger given that abs() does the following: + // "fabs returns the absolute value of x. Absolute value is a number's distance from zero on the number line. The absolute value of -4 is 4; the absolute value of 4 is 4." + // It should probably be removed + //if ( damage < 0 ) + //{ + // prof_end( "_destructible" ); + // return; + //} + + // JR - Some destructibles cause a crash due to not having "destructible_parts" + if( !isDefined( self.destructible_parts )) + { + return; + } + + self.destructible_parts[ partIndex ].v[ "currentState" ]++; + stateIndex = self.destructible_parts[ partIndex ].v[ "currentState" ]; + actionStateIndex = ( stateIndex - 1 ); + + // use these rather than re-getting them all the time. This insures that we do + // not overwrite their values too. + action_v = undefined; + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ] ) ) + action_v = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v; + + state_v = undefined; + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ] ) ) + state_v = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v; + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ] ) ) + { + prof_end( "_destructible" ); + return; + } + + //--------------------------------------------------------------------- + // A state change is required so detach the old model or replace it if + // it's the base model that took the damage. + // Then attach the model ( if specified ) used for the new state + // Only do this if there is another state to go to, some parts might have + // fx or anims, or sounds but no next model to go to + //--------------------------------------------------------------------- + + // if the part is meant to explode on this state set a flag. Actual explosion will be done down below + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode" ] ) ) + self.exploding = true; + + // stop all previously looped sounds + if ( IsDefined( self.loopingSoundStopNotifies ) && IsDefined( self.loopingSoundStopNotifies[ toString( partIndex ) ] ) ) + { + for ( i = 0; i < self.loopingSoundStopNotifies[ toString( partIndex ) ].size; i++ ) + { + self notify( self.loopingSoundStopNotifies[ toString( partIndex ) ][ i ] ); + if ( isSP() && self.modeldummyon ) + self.modeldummy notify( self.loopingSoundStopNotifies[ toString( partIndex ) ][ i ] ); + } + self.loopingSoundStopNotifies[ toString( partIndex ) ] = undefined; + } + + // setup our destructible light if we want one and can find one + if ( IsDefined( action_v[ "break_nearby_lights" ] ) ) + { + self destructible_get_my_breakable_light( action_v[ "break_nearby_lights" ] ); + } + + // swap the model + // this doesn't work when threaded off to another function + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ] ) ) + { + if ( partIndex == 0 ) // base model damaged + { + newModel = state_v[ "modelName" ]; + if ( IsDefined( newModel ) && newModel != self.model ) + { + // tagBK< NOTE > System to allow cleanly destroying effects before model swap. + wait( 0.01 ); + if ( IsDefined( self.effect_kill_array )) + { + ii = 0; + foreach( effect in self.effect_kill_array ) + { + StopFxOnTag( effect.effect, self, effect.tag ); + ii++; + + // Can only send 4 events at a time. + if ( ii == 4 ) + { + wait( 0.01 ); + ii = 0; + } + } + + // Wait a frame for the events to get through before the model swap. + if ( ii != 0 ) + { + wait( 0.01 ); + } + } + + self SetModel( newModel ); + if ( isSP() && self.modeldummyon ) + self.modeldummy SetModel( newModel ); + destructible_splash_rotatation( state_v ); + } + } + else // part was damaged, not the base model + { + // handle a part getting damaged here - must be detached and reattached + self hideapart( tagName ); + if ( isSP() && self.modeldummyon ) + self.modeldummy hideapart( tagName ); + + tagName = state_v[ "tagName" ]; + if ( IsDefined( tagName ) ) + { + self showapart( tagName ); + if ( isSP() && self.modeldummyon ) + self.modeldummy showapart( tagName ); + } + } + } + + eModel = get_dummy(); + + // If its exploding clear all previous animations on the destructible. The only animation that will play after this is an explosion animation + if ( IsDefined( self.exploding ) ) + self clear_anims( eModel ); + + // if the part has an anim then play it now + groupNumber = destructible_animation_think( action_v, eModel, damageType, partIndex ); + + // if the part has fx then play it now + groupNumber = destructible_fx_think( action_v, eModel, damageType, partIndex, groupNumber ); + + // if the part has a soundalias then play it now + groupNumber = destructible_sound_think( action_v, eModel, damageType, groupNumber ); + + // if the part has a looping fx then play it now + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx" ] ) ) + { + loopfx_size = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx_filename" ].size; + + if ( loopfx_size > 0 ) + self notify( "FX_State_Change" + partIndex ); + + for ( idx = 0; idx < loopfx_size; idx++ ) + { + Assert( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx_tag" ][ idx ] ) ); + loopfx = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx" ][ idx ]; + loopfx_tag = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx_tag" ][ idx ]; + loopRate = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopfx_rate" ][ idx ]; + self thread loopfx_onTag( loopfx, loopfx_tag, loopRate, partIndex ); + } + } + + // if the part has a looping soundalias then start looping it now + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopsound" ] ) ) + { + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopsound" ].size; i++ ) + { + validSoundCause = self isValidSoundCause( "loopsoundCause", action_v, i, damageType ); + if ( validSoundCause ) + { + loopsoundAlias = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "loopsound" ][ i ]; + loopsoundTagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "tagName" ]; + self thread play_loop_sound_on_destructible( loopsoundAlias, loopsoundTagName ); + + if ( !isdefined( self.loopingSoundStopNotifies ) ) + self.loopingSoundStopNotifies = []; + if ( !isdefined( self.loopingSoundStopNotifies[ toString( partIndex ) ] ) ) + self.loopingSoundStopNotifies[ toString( partIndex ) ] = []; + size = self.loopingSoundStopNotifies[ toString( partIndex ) ].size; + self.loopingSoundStopNotifies[ toString( partIndex ) ][ size ] = "stop sound" + loopsoundAlias; + } + } + } + + // if the part is supposed to trigger a car alarm + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "triggerCarAlarm" ] ) ) + { + self thread do_car_alarm(); + } + + // if the part is supposed to trigger a car alarm + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "break_nearby_lights" ] ) ) + { + self thread break_nearest_light(); + } + + // if the part should drain health then start the drain + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "healthdrain_amount" ] ) ) + { + self notify( "Health_Drain_State_Change" + partIndex ); + healthdrain_amount = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "healthdrain_amount" ]; + healthdrain_interval = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "healthdrain_interval" ]; + healthdrain_modelName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "modelName" ]; + healthdrain_tagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "tagName" ]; + badplaceRadius = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "badplace_radius" ]; + badplaceTeam = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "badplace_team" ]; + if ( healthdrain_amount > 0 ) + { + Assert( ( IsDefined( healthdrain_interval ) ) && ( healthdrain_interval > 0 ) ); + self thread health_drain( healthdrain_amount, healthdrain_interval, partIndex, healthdrain_modelName, healthdrain_tagName, badplaceRadius, badplaceTeam ); + } + } + + // if the part is meant to explode on this state then do it now. Causes all attached models to become physics with the specified force + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode" ] ) ) + { + delayModelSwap = true; + force_min = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode_force_min" ]; + force_max = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode_force_max" ]; + range = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode_range" ]; + mindamage = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode_mindamage" ]; + maxdamage = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "explode_maxdamage" ]; + continueDamage = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "continueDamage" ]; + originOffset = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "originOffset" ]; + earthQuakeScale = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "earthQuakeScale" ]; + earthQuakeRadius = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "earthQuakeRadius" ]; + + if ( IsDefined( attacker ) && attacker != self ) + { + // Achievement Hook + self.attacker = attacker; + + // Only add .damage_type to script_vehicles that happen to be destructibles (ie UAZ) + // This hook provides info so the vehicle can do _player_stat::register_kill() + if ( self.code_classname == "script_vehicle" ) + { + self.damage_type = damageType; + } + } + + self thread explode( partIndex, force_min, force_max, range, mindamage, maxdamage, continueDamage, originOffset, earthQuakeScale, earthQuakeRadius, attacker ); + } + + // if the part should do physics here then initiate the physics and velocity + physTagOrigin = undefined; + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "physics" ] ) ) + { + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "physics" ].size; i++ ) + { + physTagOrigin = undefined; + physTagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "physics_tagName" ][ i ]; + physVelocity = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v[ "physics_velocity" ][ i ]; + + initial_velocity = undefined; + if ( IsDefined( physVelocity ) ) + { + physTagAngles = undefined; + if ( IsDefined( physTagName ) ) + physTagAngles = self GetTagAngles( physTagName ); + else if ( IsDefined( tagName ) ) + physTagAngles = self GetTagAngles( tagName ); + Assert( IsDefined( physTagAngles ) ); + + physTagOrigin = undefined; + if ( IsDefined( physTagName ) ) + physTagOrigin = self GetTagOrigin( physTagName ); + else if ( IsDefined( tagName ) ) + physTagOrigin = self GetTagOrigin( tagName ); + Assert( IsDefined( physTagOrigin ) ); + + phys_x = physVelocity[ 0 ] - 5 + RandomFloat( 10 ); + phys_y = physVelocity[ 1 ] - 5 + RandomFloat( 10 ); + phys_z = physVelocity[ 2 ] - 5 + RandomFloat( 10 ); + + forward = AnglesToForward( physTagAngles ) * phys_x * RandomFloatRange( 80, 110 ); + right = AnglesToRight( physTagAngles ) * phys_y * RandomFloatRange( 80, 110 ); + up = AnglesToUp( physTagAngles ) * phys_z * RandomFloatRange( 80, 110 ); + + initial_velocity = forward + right + up; + + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + { + thread draw_line_for_time( physTagOrigin, physTagOrigin + initial_velocity, 1, 1, 1, 5.0 ); + } + #/ + } + else + { + initial_velocity = point; + impactDir = ( 0, 0, 0 ); + if ( IsDefined( attacker ) ) + { + impactDir = attacker.origin; + initial_velocity = VectorNormalize( point - impactDir ); + initial_velocity = vector_multiply( initial_velocity, 200 ); + } + } + Assert( IsDefined( initial_velocity ) ); + + if ( IsDefined( physTagName ) ) + { + // Do physics on another part, and continue this thread since the current part is still unaffected by the physics + + // get the partIndex that cooresponds to what the tagname is + physPartIndex = undefined; + for ( j = 0; j < level._destructible_type[ self.destuctableInfo ].parts.size; j++ ) + { + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts[ j ][ 0 ].v[ "tagName" ] ) ) + continue; + + if ( level._destructible_type[ self.destuctableInfo ].parts[ j ][ 0 ].v[ "tagName" ] != physTagName ) + continue; + + physPartIndex = j; + break; + } + + if ( IsDefined( physTagOrigin ) ) + self thread physics_launch( physPartIndex, 0, physTagOrigin, initial_velocity ); + else + self thread physics_launch( physPartIndex, 0, point, initial_velocity ); + } + else + { + // Do physics on this part, therefore ending this thread + + if ( IsDefined( physTagOrigin ) ) + self thread physics_launch( partIndex, actionStateIndex, physTagOrigin, initial_velocity ); + else + self thread physics_launch( partIndex, actionStateIndex, point, initial_velocity ); + + prof_end( "_destructible" ); + return; + } + } + } + + updateHealthValue = true; + } + prof_end( "_destructible" ); +} + +PlayFxOnTag_KillOnDestructibleSwap( effect, entity, tag ) +{ + PlayFxOnTag( effect, entity, tag ); + if ( !IsDefined( entity.effect_kill_array )) + { + entity.effect_kill_array = []; + } + new_effect = SpawnStruct(); + new_effect.effect = effect; + new_effect.tag = tag; + entity.effect_kill_array[ entity.effect_kill_array.size ] = new_effect; +} + +destructible_splash_rotatation( v ) +{ + // rotate model due to splash damage direction, optional + model_rotation = v[ "splashRotation" ]; + model_rotate_to = v[ "rotateTo" ]; + + if ( !isdefined( model_rotate_to ) ) + return; + if ( !isdefined( model_rotation ) ) + return; + if ( !model_rotation ) + return; + self.angles = ( self.angles[ 0 ], model_rotate_to[ 1 ], self.angles[ 2 ] ); +} + +// parameter damageType can be single damage or multiple damages separated by spaces +damage_not( damageType ) +{ + toks = StrTok( damageType, " " ); + damages_tok = StrTok( "splash melee bullet splash impact unknown", " " ); + new_string = ""; + + foreach ( idx, tok in toks ) + damages_tok = array_remove( damages_tok, tok ); + + foreach ( damages in damages_tok ) + new_string += damages + " "; + + return new_string; +} + +destructible_splash_damage( damage, point, direction_vec, attacker, damageType ) +{ + if ( damage <= 0 ) + return; + + if ( IsDefined( self.exploded ) ) + return; + + //------------------------------------------------------------------------ + // Fill an array of all possible parts that might have been splash damaged + //------------------------------------------------------------------------ + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + return; + + damagedParts = self getAllActiveParts( direction_vec ); + + if ( damagedParts.size <= 0 ) + return; + + damagedParts = self setDistanceOnParts( damagedParts, point ); + + closestPartDist = getLowestPartDistance( damagedParts ); + Assert( IsDefined( closestPartDist ) ); + + //-------------------------------------------------------------------------- + // Damage each part depending on how close it was to the splash damage point + //-------------------------------------------------------------------------- + + prof_begin( "_destructible" ); + + foreach ( part in damagedParts ) + { + distanceMod = ( part.v[ "distance" ] * 1.4 ); + damageAmount = ( damage - ( distanceMod - closestPartDist ) ); + + if ( damageAmount <= 0 ) + continue; + + if ( IsDefined( self.exploded ) ) + continue; + + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + { + if ( IsDefined( part.v[ "tagName" ] ) ) + Print3d( self GetTagOrigin( part.v[ "tagName" ] ), damageAmount, ( 1, 1, 1 ), 1.0, 0.5, 200 ); + } + #/ + + self thread destructible_update_part( damageAmount, part.v[ "modelName" ], part.v[ "tagName" ], point, direction_vec, attacker, damageType, part ); + } + + prof_end( "_destructible" ); +} + +getAllActiveParts( direction_vec ) +{ + activeParts = []; + + Assert( IsDefined( self.destuctableInfo ) ); + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + return activeParts; + + prof_begin( "_destructible" ); + + for ( i = 0; i < level._destructible_type[ self.destuctableInfo ].parts.size; i++ ) + { + partIndex = i; + currentState = self.destructible_parts[ partIndex ].v[ "currentState" ]; + + // Splash damage rotation, rotation angle only calculated for state that has this option enabled + for ( j = 0; j < level._destructible_type[ self.destuctableInfo ].parts[ partIndex ].size; j++ ) + { + splash_rotation = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ j ].v[ "splashRotation" ]; + if ( IsDefined( splash_rotation ) && splash_rotation ) + { + rotate_to_angle = VectorToAngles( direction_vec ); + rotate_to_angle_y = rotate_to_angle[ 1 ] - 90; + level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ j ].v[ "rotateTo" ] = ( 0, rotate_to_angle_y, 0 ); + } + } + + if ( !isdefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ currentState ] ) ) + continue; + + tagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ currentState ].v[ "tagName" ]; + if ( !isdefined( tagName ) ) + tagName = ""; + + if ( tagName == "" ) + continue; + + modelName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ currentState ].v[ "modelName" ]; + if ( !isdefined( modelName ) ) + modelName = ""; + + activePartIndex = activeParts.size; + activeParts[ activePartIndex ] = SpawnStruct(); + activeParts[ activePartIndex ].v[ "modelName" ] = modelName; + activeParts[ activePartIndex ].v[ "tagName" ] = tagName; + } + + prof_end( "_destructible" ); + + return activeParts; +} + +setDistanceOnParts( partList, point ) +{ + prof_begin( "_destructible" ); + + for ( i = 0; i < partList.size; i++ ) + { + d = Distance( point, self GetTagOrigin( partList[ i ].v[ "tagName" ] ) ); + partList[ i ].v[ "distance" ] = d; + } + + prof_end( "_destructible" ); + + return partList; +} + +getLowestPartDistance( partList ) +{ + closestDist = undefined; + + prof_begin( "_destructible" ); + + foreach ( part in partList ) + { + Assert( IsDefined( part.v[ "distance" ] ) ); + d = part.v[ "distance" ]; + + if ( !isdefined( closestDist ) ) + closestDist = d; + + if ( d < closestDist ) + closestDist = d; + } + + prof_end( "_destructible" ); + + return closestDist; +} + + +isValidSoundCause( soundCauseVar, action_v, soundIndex, damageType, groupNum ) +{ + if ( isdefined( groupNum ) ) + soundCause = action_v[ soundCauseVar ][ groupNum ][ soundIndex ]; + else + soundCause = action_v[ soundCauseVar ][ soundIndex ]; + + if ( !isdefined( soundCause ) ) + return true; + + if ( soundCause == damageType ) + return true; + + return false; +} + +isAttackerValid( partIndex, stateIndex, attacker ) +{ + // return true if the vehicle is being force exploded + if ( IsDefined( self.forceExploding ) ) + return true; + + // return false if the vehicle is trying to explode but it's not allowed to + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "explode" ] ) ) + { + if ( IsDefined( self.dontAllowExplode ) ) + return false; + } + + if ( !isdefined( attacker ) ) + return true; + + if ( attacker == self ) + return true; + + sType = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "validAttackers" ]; + if ( !isdefined( sType ) ) + return true; + + if ( sType == "no_player" ) + { + if ( !isplayer( attacker ) ) + return true; + if ( !isdefined( attacker.damageIsFromPlayer ) ) + return true; + if ( attacker.damageIsFromPlayer == false ) + return true; + } + else + if ( sType == "player_only" ) + { + if ( IsPlayer( attacker ) ) + return true; + if ( IsDefined( attacker.damageIsFromPlayer ) && attacker.damageIsFromPlayer ) + return true; + } + else + if ( sType == "no_ai" && IsDefined( level._isAIfunc ) ) + { + if ( ![[ level._isAIfunc ]]( attacker ) ) + return true; + } + else + if ( sType == "ai_only" && IsDefined( level._isAIfunc ) ) + { + if ( [[ level._isAIfunc ]]( attacker ) ) + return true; + } + else + { + AssertMsg( "Invalid attacker rules on destructible vehicle. Valid types are: ai_only, no_ai, player_only, no_player" ); + } + + return false; +} + +isValidDamageCause( partIndex, stateIndex, damageType ) +{ + if ( !isdefined( damageType ) ) + { + return true; + } + + godModeAllowed = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "godModeAllowed" ]; + if ( godModeAllowed && ( ( IsDefined( self.godmode ) && self.godmode ) || ( IsDefined( self.script_bulletshield ) && self.script_bulletshield ) && damageType == "bullet" ) ) + { + return false; + } + + validType = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "validDamageCause" ]; + if ( !isdefined( validType ) ) + { + return true; + } + + if ( ( validType == "splash" ) && damageType != "splash" ) + { + return false; + } + + if ( ( validType == "no_melee_yes_impact" ) && damageType != "melee" && damageType == "impact" ) + { + return true; + } + else if ( ( validType == "no_melee" ) && damageType == "melee" || damageType == "impact" ) + { + return false; + } + + return true; +} + +getDamageType( type ) +{ + //returns a simple damage type: melee, bullet, splash, or unknown + + if ( !isdefined( type ) ) + return "unknown"; + + type = ToLower( type ); + switch( type ) + { + case "mod_melee": + case "mod_crush": + case "melee": + return "melee"; + case "mod_pistol_bullet": + case "mod_rifle_bullet": + case "bullet": + return "bullet"; + case "mod_grenade": + case "mod_grenade_splash": + case "mod_projectile": + case "mod_projectile_splash": + case "mod_explosive": + case "splash": + return "splash"; + case "mod_impact": + return "impact"; + case "unknown": + return "unknown"; + default: + return "unknown"; + } +} + +damage_mirror( parent, modelName, tagName ) +{ + self notify( "stop_damage_mirror" ); + self endon( "stop_damage_mirror" ); + parent endon( "stop_taking_damage" ); + + self SetCanDamage( true ); + for ( ;; ) + { + self waittill( "damage", damage, attacker, direction_vec, point, type ); + parent notify( "damage", damage, attacker, direction_vec, point, type, modelName, tagName ); + damage = undefined; + attacker = undefined; + direction_vec = undefined; + point = undefined; + type = undefined; + } +} + +add_damage_owner_recorder() +{ + // Mackey added to track who is damaging the car + self.player_damage = 0; + self.non_player_damage = 0; + + self.car_damage_owner_recorder = true; +} + +loopfx_onTag( loopfx, loopfx_tag, loopRate, partIndex ) +{ + self endon( "FX_State_Change" + partIndex ); + self endon( "delete_destructible" ); + level endon( "putout_fires" ); + + while( isdefined( self ) ) + { + eModel = get_dummy(); + PlayFXOnTag( loopfx, eModel, loopfx_tag ); + wait loopRate; + } +} + +health_drain( amount, interval, partIndex, modelName, tagName, badplaceRadius, badplaceTeam ) +{ + self endon( "Health_Drain_State_Change" + partIndex ); + level endon( "putout_fires" ); + self endon( "destroyed" ); + + if( IsDefined( badplaceRadius ) && IsDefined( level._destructible_badplace_radius_multiplier ) ) + { + badplaceRadius *= level._destructible_badplace_radius_multiplier; + } + + if( IsDefined( amount ) &&IsDefined( level._destructible_health_drain_amount_multiplier ) ) + { + amount *= level._destructible_health_drain_amount_multiplier; + } + + wait interval; + + self.healthDrain = true; + + uniqueName = undefined; + + // disable the badplace radius call if level.disable_destructible_bad_places is true + if ( IsDefined( level._disable_destructible_bad_places ) && level._disable_destructible_bad_places ) + badplaceRadius = undefined; + + if ( IsDefined( badplaceRadius ) && IsDefined( badplaceTeam ) && isSP() ) + { + uniqueName = "" + GetTime(); + if ( !isdefined( self.disableBadPlace ) ) + { + if ( IsDefined( self.script_radius ) ) + { + // overwrite the badplace radius from the map + badplaceRadius = self.script_radius; + } + Assert( IsDefined( level._badplace_cylinder_func ) ); + if ( badplaceTeam == "both" ) + call [[ level._badplace_cylinder_func ]]( uniqueName, 0, self.origin, badplaceRadius, 128, "allies", "bad_guys" ); + else + call [[ level._badplace_cylinder_func ]]( uniqueName, 0, self.origin, badplaceRadius, 128, badplaceTeam ); + self thread badplace_remove( uniqueName ); + } + } + + while ( isdefined( self ) && self.destructible_parts[ partIndex ].v[ "health" ] > 0 ) + { + /# + if ( GetDvarInt( "debug_destructibles" , 0 ) == 1 ) + { + IPrintLn( "health before damage: " + self.destructible_parts[ partIndex ].v[ "health" ] ); + IPrintLn( "doing " + amount + " damage" ); + } + #/ + self notify( "damage", amount, self, ( 0, 0, 0 ), ( 0, 0, 0 ), "MOD_UNKNOWN", modelName, tagName ); + wait interval; + } + + self notify( "remove_badplace" ); +} + +badplace_remove( uniqueName ) +{ + self waittill_any( "destroyed", "remove_badplace" ); + + Assert( IsDefined( uniqueName ) ); + Assert( IsDefined( level._badplace_delete_func ) ); + call [[ level._badplace_delete_func ]]( uniqueName ); +} + +physics_launch( partIndex, stateIndex, point, initial_velocity ) +{ + modelName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "modelName" ]; + tagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ stateIndex ].v[ "tagName" ]; + + self hideapart( tagName ); + + /# + if ( GetDvarInt( "destructibles_enable_physics", 1 ) == 0 ) + return; + #/ + + // If we've reached the max number of spawned physics models for destructible vehicles then delete one before creating another + if ( level._destructibleSpawnedEnts.size >= level._destructibleSpawnedEntsLimit ) + physics_object_remove( level._destructibleSpawnedEnts[ 0 ] ); + + // Spawn a model to use for physics using the modelname and position of the part + physicsObject = Spawn( "script_model", self GetTagOrigin( tagName ) ); + physicsObject.angles = self GetTagAngles( tagName ); + physicsObject SetModel( modelName ); + + // Keep track of the new part so it can be removed later if we reach the max + level._destructibleSpawnedEnts[ level._destructibleSpawnedEnts.size ] = physicsObject; + + // Do physics on the model + physicsObject PhysicsLaunchClient( point, initial_velocity ); +} + +physics_object_remove( ent ) +{ + newArray = []; + for ( i = 0; i < level._destructibleSpawnedEnts.size; i++ ) + { + if ( level._destructibleSpawnedEnts[ i ] == ent ) + continue; + newArray[ newArray.size ] = level._destructibleSpawnedEnts[ i ]; + } + level._destructibleSpawnedEnts = newArray; + + if ( isdefined( ent ) ) + ent Delete(); +} + +explode( partIndex, force_min, force_max, range, mindamage, maxdamage, continueDamage, originOffset, earthQuakeScale, earthQuakeRadius, attacker ) +{ + Assert( IsDefined( force_min ) ); + Assert( IsDefined( force_max ) ); + + if( IsDefined( range ) && IsDefined( level._destructible_explosion_radius_multiplier ) ) + { + range *= level._destructible_explosion_radius_multiplier; + } + + if ( !isdefined( originOffset ) ) + originOffset = 80; + + if ( !isdefined( continueDamage ) || ( IsDefined( continueDamage ) && !continueDamage ) ) + { + if ( IsDefined( self.exploded ) ) + return; + self.exploded = true; + } + + self notify( "exploded", attacker ); + level notify( "destructible_exploded" ); + if ( self.code_classname == "script_vehicle" ) + self notify( "death", attacker, self.damage_type ); + + // check if there is a disconnect paths brush to disconnect any traverses + if ( isSP() ) + self thread disconnectTraverses(); + + wait 0.05; + + currentState = self.destructible_parts[ partIndex ].v[ "currentState" ]; + Assert( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ] ) ); + tagName = undefined; + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ currentState ] ) ) + tagName = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ currentState ].v[ "tagName" ]; + + if ( IsDefined( tagName ) ) + explosionOrigin = self GetTagOrigin( tagName ); + else + explosionOrigin = self.origin; + + self notify( "damage", maxdamage, self, ( 0, 0, 0 ), explosionOrigin, "MOD_EXPLOSIVE", "", "" ); + + self notify( "stop_car_alarm" ); + + waittillframeend; + + prof_begin( "_destructible" ); + + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts ) ) + { + for ( i = ( level._destructible_type[ self.destuctableInfo ].parts.size - 1 ); i >= 0; i-- ) + { + if ( i == partIndex ) + continue; + + stateIndex = self.destructible_parts[ i ].v[ "currentState" ]; + if ( stateIndex >= level._destructible_type[ self.destuctableInfo ].parts[ i ].size ) + stateIndex = level._destructible_type[ self.destuctableInfo ].parts[ i ].size - 1; + modelName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "modelName" ]; + tagName = level._destructible_type[ self.destuctableInfo ].parts[ i ][ stateIndex ].v[ "tagName" ]; + + if ( !isdefined( modelName ) ) + continue; + if ( !isdefined( tagName ) ) + continue; + + // dont do physics on parts that are supposed to be removed on explosion + if ( IsDefined( level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "physicsOnExplosion" ] ) ) + { + if ( level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "physicsOnExplosion" ] > 0 ) + { + velocityScaler = level._destructible_type[ self.destuctableInfo ].parts[ i ][ 0 ].v[ "physicsOnExplosion" ]; + + point = self GetTagOrigin( tagName ); + initial_velocity = VectorNormalize( point - explosionOrigin ); + initial_velocity = vector_multiply( initial_velocity, RandomFloatRange( force_min, force_max ) * velocityScaler ); + + self thread physics_launch( i, stateIndex, point, initial_velocity ); + continue; + } + } + //self.destructible_parts[ i ] Hide(); + } + } + + prof_end( "_destructible" ); + + stopTakingDamage = ( !isdefined( continueDamage ) || ( IsDefined( continueDamage ) && !continueDamage ) ); + if ( stopTakingDamage ) + self notify( "stop_taking_damage" ); + + wait 0.05; + + damageLocation = explosionOrigin + ( 0, 0, originOffset ); + + isVehicle = ( GetSubStr( level._destructible_type[ self.destuctableInfo ].v[ "type" ], 0, 7 ) == "vehicle" ); + + if ( isVehicle ) + { + anim.lastCarExplosionTime = GetTime(); + anim.lastCarExplosionDamageLocation = damageLocation; + anim.lastCarExplosionLocation = explosionOrigin; + anim.lastCarExplosionRange = range; + } + + // turn off friendly fire when they blow up so the player doesn't get accidental friendly fire mission failure + level thread set_disable_friendlyfire_value_delayed( 1 ); + + if ( isSP() ) + { + if ( level._gameskill == 0 && !self player_touching_post_clip() ) + self RadiusDamage( damageLocation, range, maxdamage, mindamage, self, "MOD_RIFLE_BULLET" ); + else + self RadiusDamage( damageLocation, range, maxdamage, mindamage, self ); + + if ( IsDefined( self.damageOwner ) && isVehicle ) + { + self.damageOwner notify( "destroyed_car" ); + level notify( "player_destroyed_car", self.damageOwner, damageLocation ); + } + } + else + { + if ( !isdefined( self.damageOwner ) ) + { + self RadiusDamage( damageLocation, range, maxdamage, mindamage, self ); + } + else + { + self RadiusDamage( damageLocation, range, maxdamage, mindamage, self.damageOwner ); + if ( isVehicle ) + { + self.damageOwner notify( "destroyed_car" ); + level notify( "player_destroyed_car", self.damageOwner, damageLocation ); + } + } + } + + if ( IsDefined( earthQuakeScale ) && IsDefined( earthQuakeRadius ) ) + Earthquake( earthQuakeScale, 2.0, damageLocation, earthQuakeRadius ); + + /# + if ( GetDvarInt( "destructibles_show_radiusdamage" ) == 1 ) + thread debug_radiusdamage_circle( damageLocation, range, maxdamage, mindamage ); + #/ + + // explosion damage done, resume friendly fire if it was enabled + level thread set_disable_friendlyfire_value_delayed( 0, 0.05 ); + + magnitudeScaler = 0.01; + magnitude = range * magnitudeScaler; + Assert( magnitude > 0 ); + range *= .99; + PhysicsExplosionSphere( damageLocation, range, 0, magnitude ); + + if ( stopTakingDamage ) + { + self SetCanDamage( false ); + self thread cleanupVars(); + } + + self notify( "destroyed" ); +} + +cleanupVars() +{ + // wait so we can make sure they are no longer needed + wait 0.05; + + if ( !isdefined( self ) ) + return; + + if ( isdefined( self.waiting_for_queue ) ) + self waittill( "queue_processed" ); + + if ( !isdefined( self ) ) + return; + + self.animsapplied = undefined; + self.attacker = undefined; + self.car_damage_owner_recorder = undefined; + self.caralarm = undefined; + self.damageowner = undefined; + self.destructible_parts = undefined; + self.destructible_type = undefined; + self.destuctableinfo = undefined; + self.healthdrain = undefined; + self.non_player_damage = undefined; + self.player_damage = undefined; +} + +set_disable_friendlyfire_value_delayed( value, delay ) +{ + level notify( "set_disable_friendlyfire_value_delayed" ); + level endon( "set_disable_friendlyfire_value_delayed" ); + + Assert( IsDefined( value ) ); + + if ( IsDefined( delay ) ) + wait delay; + + level._friendlyFireDisabledForDestructible = value; +} + +/* +arcadeMode_car_kill() +{ + if ( !isSP() ) + return false; + + if ( !arcadeMode() ) + return false; + + if ( level.script == "ac130" ) + return false; + + if ( IsDefined( level.allCarsDamagedByPlayer ) ) + return true; + + return self maps\_gameskill::player_did_most_damage(); +} +*/ +connectTraverses() +{ + clip = get_traverse_disconnect_brush(); + + if ( !isdefined( clip ) ) + return; + + Assert( IsDefined( level._connectPathsFunction ) ); + clip call [[ level._connectPathsFunction ]](); + clip.origin -= ( 0, 0, 10000 ); +} + +disconnectTraverses() +{ + clip = get_traverse_disconnect_brush(); + + if ( !isdefined( clip ) ) + return; + + clip.origin += ( 0, 0, 10000 ); + Assert( IsDefined( level._disconnectPathsFunction ) ); + clip call [[ level._disconnectPathsFunction ]](); + clip.origin -= ( 0, 0, 10000 ); +} + +get_traverse_disconnect_brush() +{ + if ( !isdefined( self.target ) ) + return undefined; + + targets = GetEntArray( self.target, "targetname" ); + foreach ( target in targets ) + { + if ( IsSpawner( target ) ) + continue; + if ( IsDefined( target.script_destruct_collision ) ) + continue; + if ( target.code_classname == "light" ) + continue; + if ( !target.spawnflags & 1 ) + continue; + return target; + } +} + +hideapart( tagName ) +{ + self HidePart( tagName ); +} + +showapart( tagName ) +{ + self ShowPart( tagName ); +} + +disable_explosion() +{ + self.dontAllowExplode = true; +} + +force_explosion() +{ + self.dontAllowExplode = undefined; + self.forceExploding = true; + self notify( "damage", 1000000000, self, self.origin, self.origin, "MOD_EXPLOSIVE", "", "" ); +} + +get_dummy() +{ + if ( !isSP() ) + return self; + + if ( self.modeldummyon ) + eModel = self.modeldummy; + else + eModel = self; + return eModel; +} + +play_loop_sound_on_destructible( alias, tag ) +{ + eModel = get_dummy(); + + org = Spawn( "sound_emitter", ( 0, 0, 0 ) ); + if ( IsDefined( tag ) ) + org.origin = eModel GetTagOrigin( tag ); + else + org.origin = eModel.origin; + + org PlayLoopSound( alias ); + + eModel thread force_stop_sound( alias ); + + eModel waittill( "stop sound" + alias ); + if ( !isdefined( org ) ) + return; + + org StopLoopSound( alias ); + org Delete(); +} + +force_stop_sound( alias ) +{ + self endon( "stop sound" + alias ); + + level waittill( "putout_fires" ); + self notify( "stop sound" + alias ); +} + +notifyDamageAfterFrame( damage, attacker, direction_vec, point, damageType, modelName, tagName ) +{ + if ( IsDefined( level._notifyDamageAfterFrame ) ) + return; + + level._notifyDamageAfterFrame = true; + waittillframeend; + if ( IsDefined( self.exploded ) ) + { + level._notifyDamageAfterFrame = undefined; + return; + } + + if ( isSP() ) + damage /= SP_DAMAGE_BIAS; + else + damage /= MP_DAMAGE_BIAS; + + self notify( "damage", damage, attacker, direction_vec, point, damageType, modelName, tagName ); + level._notifyDamageAfterFrame = undefined; +} + +play_sound( alias, tag ) +{ + if ( IsDefined( tag ) ) + { + org = Spawn( "sound_emitter", self GetTagOrigin( tag ) ); + org Hide(); + org LinkTo( self, tag, ( 0, 0, 0 ), ( 0, 0, 0 ) ); + } + else + { + org = Spawn( "sound_emitter", ( 0, 0, 0 ) ); + org Hide(); + org.origin = self.origin; + org.angles = self.angles; + org LinkTo( self ); + } + + org PlaySound( alias ); + wait( 5.0 ); + if ( IsDefined( org ) ) + org Delete(); +} + +toString( num ) +{ + return( "" + num ); +} + +do_car_alarm() +{ + if ( IsDefined( self.carAlarm ) ) + return; + self.carAlarm = true; + + if ( !should_do_car_alarm() ) + return; + + self.car_alarm_org = Spawn( "script_model", self.origin ); + self.car_alarm_org Hide(); + self.car_alarm_org PlayLoopSound( CAR_ALARM_ALIAS ); + + level._currentCarAlarms++; + Assert( level._currentCarAlarms <= MAX_SIMULTANEOUS_CAR_ALARMS ); + + self thread car_alarm_timeout(); + + self waittill( "stop_car_alarm" ); + + level._lastCarAlarmTime = GetTime(); + level._currentCarAlarms--; + + self.car_alarm_org StopLoopSound( CAR_ALARM_ALIAS ); + self.car_alarm_org Delete(); +} + +car_alarm_timeout() +{ + self endon( "stop_car_alarm" ); + + // Car alarm only lasts this long until it automatically shuts up + wait CAR_ALARM_TIMEOUT; + + if ( !isdefined( self ) ) + return; + + self thread play_sound( CAR_ALARM_OFF_ALIAS ); + self notify( "stop_car_alarm" ); +} + +should_do_car_alarm() +{ + // If there is already car alarms going off then don't trigger another one + if ( level._currentCarAlarms >= MAX_SIMULTANEOUS_CAR_ALARMS ) + return false; + + // If the player hasn't heard a car alarm yet during this level + timeElapsed = undefined; + if ( !isdefined( level._lastCarAlarmTime ) ) + { + if ( cointoss() ) + return true; + timeElapsed = GetTime() - level._commonStartTime; + } + else + { + timeElapsed = GetTime() - level._lastCarAlarmTime; + } + Assert( IsDefined( timeElapsed ) ); + + // If the player hasn't heard a car alarm in a while then do one + if ( level._currentCarAlarms == 0 && timeElapsed >= NO_CAR_ALARM_MAX_ELAPSED_TIME ) + return true; + + if ( RandomInt( 100 ) <= 33 ) + return true; + + return false; +} + +do_random_dynamic_attachment( tagName, attach_model_1, attach_model_2, clipToRemove ) +{ + Assert( IsDefined( tagName ) ); + Assert( IsDefined( attach_model_1 ) ); + + spawnedModels = []; + + if ( isSP() ) + { + self Attach( attach_model_1, tagName, false ); + if ( IsDefined( attach_model_2 ) && attach_model_2 != "" ) + self Attach( attach_model_2, tagName, false ); + } + else + { + //attach doesn't work in MP so fake it + spawnedModels[ 0 ] = Spawn( "script_model", self GetTagOrigin( tagName ) ); + spawnedModels[ 0 ].angles = self GetTagAngles( tagName ); + spawnedModels[ 0 ] SetModel( attach_model_1 ); + spawnedModels[ 0 ] LinkTo( self, tagName ); + + if ( IsDefined( attach_model_2 ) && attach_model_2 != "" ) + { + spawnedModels[ 1 ] = Spawn( "script_model", self GetTagOrigin( tagName ) ); + spawnedModels[ 1 ].angles = self GetTagAngles( tagName ); + spawnedModels[ 1 ] SetModel( attach_model_2 ); + spawnedModels[ 1 ] LinkTo( self, tagName ); + } + } + + // remove collision that might not be used for this attachment + if ( isdefined( clipToRemove ) ) + { + tagOrg = self getTagOrigin( tagName ); + clip = get_closest_with_targetname( tagOrg, clipToRemove ); + if ( isdefined( clip ) ) + clip delete(); + } + + self waittill( "exploded" ); + + if ( isSP() ) + { + self Detach( attach_model_1, tagName ); + self Attach( attach_model_1 + DESTROYED_ATTACHMENT_SUFFIX, tagName, false ); + + if ( IsDefined( attach_model_2 ) && attach_model_2 != "" ) + { + self Detach( attach_model_2, tagName ); + self Attach( attach_model_2 + DESTROYED_ATTACHMENT_SUFFIX, tagName, false ); + } + } + else + { + spawnedModels[ 0 ] SetModel( attach_model_1 + DESTROYED_ATTACHMENT_SUFFIX ); + if ( IsDefined( attach_model_2 ) && attach_model_2 != "" ) + spawnedModels[ 1 ] SetModel( attach_model_2 + DESTROYED_ATTACHMENT_SUFFIX ); + } +} + +get_closest_with_targetname( origin, targetname ) +{ + closestDist = undefined; + closestEnt = undefined; + ents = getentarray( targetname, "targetname" ); + foreach ( ent in ents ) + { + d = distanceSquared( origin, ent.origin ); + + if ( !isdefined( closestDist ) || ( d < closestDist ) ) + { + closestDist = d; + closestEnt = ent; + } + } + + return closestEnt; +} + +player_touching_post_clip() +{ + post_clip = undefined; + + if ( !IsDefined( self.target ) ) + { + return false; + } + + targets = GetEntArray( self.target, "targetname" ); + foreach ( target in targets ) + { + if ( IsDefined( target.script_destruct_collision ) && target.script_destruct_collision == "post" ) + { + post_clip = target; + break; + } + } + + if ( !IsDefined( post_clip ) ) + { + return false; + } + + player = get_player_touching( post_clip ); + + if ( IsDefined( player ) ) + { + return true; + } + + return false; +} + +get_player_touching( ent ) +{ + foreach ( player in level._players ) + { + if ( !IsAlive( player ) ) + { + continue; + } + + if ( ent IsTouching( player ) ) + { + return player; + } + } + + return undefined; +} + +is_so() +{ + return GetDvar( "specialops" ) == "1"; +} + +destructible_handles_collision_brushes() +{ + targets = GetEntArray( self.target, "targetname" ); + collision_funcs = []; + collision_funcs[ "pre" ] = ::collision_brush_pre_explosion; + collision_funcs[ "post" ] = ::collision_brush_post_explosion; + + foreach ( target in targets ) + { + if ( !isdefined( target.script_destruct_collision ) ) + continue; + self thread [[ collision_funcs[ target.script_destruct_collision ] ]]( target ); + } +} + +collision_brush_pre_explosion( clip ) +{ + waittillframeend;// wait for same area post brushes to connect before we disconnect + + if ( isSP() ) + clip call [[ level._disconnectPathsFunction ]](); + + self waittill( "exploded" ); + + if ( isSP() ) + clip call [[ level._connectPathsFunction ]](); + + clip Delete(); +} + +collision_brush_post_explosion( clip ) +{ + clip NotSolid(); + + if ( isSP() ) + clip call [[ level._connectPathsFunction ]](); + + self waittill( "exploded" ); + waittillframeend;// wait for same area pre brushes to connect before we disconnect + + if ( isSP() ) + { + clip call [[ level._disconnectPathsFunction ]](); + + if ( is_so() ) + { + player = get_player_touching( clip ); + if ( isdefined( player ) ) + { + assertex( isdefined( level._func_destructible_crush_player ), "Special Ops requires level.func_destructible_crush_player to be defined." ); + self thread [[ level._func_destructible_crush_player ]]( player ); + } + } + else + { +/# + thread debug_player_in_post_clip( clip ); +#/ + } + } + + clip Solid(); +} + +debug_player_in_post_clip( clip ) +{ +/# + wait( 0.1 ); + player = get_player_touching( clip ); + if ( IsDefined( player ) ) + { + AssertEx( !IsAlive( player ), "Player is in a clip of a destructible, but is still alive. He's either in godmode or we're doing something wrong. Player will be stuck now." ); + } +#/ +} + + +destructible_get_my_breakable_light( range ) +{ + AssertEx( !isdefined( self.breakable_light ), "Tried to define my breakable light twice" ); + + // light = getClosest( self.origin, GetEntArray("light_destructible","targetname") ); + // beh getClosest is SP only.. to lazy to port right now. + // find the nearest light with targetname light_destructible within range and turn it out. scripting stuff in prefabs is still hard. + // + lights = GetEntArray( "light_destructible", "targetname" ); + if ( isSP() )// mp lacks noteworthy powers + { + lights2 = GetEntArray( "light_destructible", "script_noteworthy" ); + lights = array_combine( lights, lights2 ); + } + if ( !lights.size ) + return; + + shortest_distance = range * range; + the_light = undefined; + foreach ( light in lights ) + { + dist = DistanceSquared( self.origin, light.origin ); + if ( dist < shortest_distance ) + { + the_light = light; + shortest_distance = dist; + } + } + + if ( !isdefined( the_light ) ) + return; + + self.breakable_light = the_light; +} + +break_nearest_light( range ) +{ + if ( !isdefined( self.breakable_light ) ) + return; + + self.breakable_light SetLightIntensity( 0 ); +} + + +debug_radiusdamage_circle( center, radius, maxdamage, mindamage ) +{ + circle_sides = 16; + + angleFrac = 360 / circle_sides; + + // Z circle + circlepoints = []; + for ( i = 0; i < circle_sides; i++ ) + { + angle = ( angleFrac * i ); + xAdd = Cos( angle ) * radius; + yAdd = Sin( angle ) * radius; + x = center[ 0 ] + xAdd; + y = center[ 1 ] + yAdd; + z = center[ 2 ]; + circlepoints[ circlepoints.size ] = ( x, y, z ); + } + thread debug_circle_drawlines( circlepoints, 5.0, ( 1, 0, 0 ), center ); + + // X circle + circlepoints = []; + for ( i = 0; i < circle_sides; i++ ) + { + angle = ( angleFrac * i ); + xAdd = Cos( angle ) * radius; + yAdd = Sin( angle ) * radius; + x = center[ 0 ]; + y = center[ 1 ] + xAdd; + z = center[ 2 ] + yAdd; + circlepoints[ circlepoints.size ] = ( x, y, z ); + } + thread debug_circle_drawlines( circlepoints, 5.0, ( 1, 0, 0 ), center ); + + // Y circle + circlepoints = []; + for ( i = 0; i < circle_sides; i++ ) + { + angle = ( angleFrac * i ); + xAdd = Cos( angle ) * radius; + yAdd = Sin( angle ) * radius; + x = center[ 0 ] + yAdd; + y = center[ 1 ]; + z = center[ 2 ] + xAdd; + circlepoints[ circlepoints.size ] = ( x, y, z ); + } + thread debug_circle_drawlines( circlepoints, 5.0, ( 1, 0, 0 ), center ); + + // draw center and range with values + Print3d( center, maxdamage, ( 1, 1, 1 ), 1, 1, 100 ); + Print3d( center + ( radius, 0, 0 ), mindamage, ( 1, 1, 1 ), 1, 1, 100 ); +} + +debug_circle_drawlines( circlepoints, duration, color, center ) +{ + Assert( IsDefined( center ) ); + for ( i = 0; i < circlepoints.size; i++ ) + { + start = circlepoints[ i ]; + if ( i + 1 >= circlepoints.size ) + end = circlepoints[ 0 ]; + else + end = circlepoints[ i + 1 ]; + + thread debug_line( start, end, duration, color ); + thread debug_line( center, start, duration, color ); + } +} + +debug_line( start, end, duration, color ) +{ + if ( !isdefined( color ) ) + color = ( 1, 1, 1 ); + + for ( i = 0; i < ( duration * 20 ); i++ ) + { + Line( start, end, color ); + wait 0.05; + } +} + +spotlight_tag_origin_cleanup( tag_origin ) +{ + tag_origin endon( "death" ); + level waittill( "new_destructible_spotlight" ); + tag_origin Delete(); +} + +spotlight_fizzles_out( action_v, eModel, damageType, partIndex, tag_origin ) +{ + level endon( "new_destructible_spotlight" ); + thread spotlight_tag_origin_cleanup( tag_origin ); + + maxVal = action_v[ "spotlight_brightness" ]; + noself_func( "setsaveddvar", "r_spotlightbrightness", maxVal ); + + wait( RandomFloatRange( 2, 5 ) ); + + steps = RandomIntRange( 5, 11 ); + for ( i = 0; i < steps; i++ ) + { + noself_func( "setsaveddvar", "r_spotlightbrightness", maxVal * 0.65 ); + wait( 0.05 ); + noself_func( "setsaveddvar", "r_spotlightbrightness", maxVal ); + wait( 0.05 ); + } + + destructible_fx_think( action_v, eModel, damageType, partIndex ); + level._destructible_spotlight Delete(); + tag_origin Delete(); +} + +destructible_spotlight_think( action_v, eModel, damageType, partIndex ) +{ + // spotlights are MP only + if ( !isSP() ) + return; + + if ( !isdefined( self.breakable_light ) ) + return; + + emodel self_func( "startignoringspotLight" ); + + // set all the dvars for this light type + foreach ( dvar, val in action_v[ "dvars" ] ) + { + noself_func( "setsaveddvar", dvar, val ); + } + + if ( !isdefined( level._destructible_spotlight ) ) + { + level._destructible_spotlight = spawn_tag_origin(); + fx = getfx( action_v[ "spotlight_fx" ] ); + PlayFXOnTag( fx, level._destructible_spotlight, "tag_origin" ); + } + + //self.breakable_light thread maps\_debug::drawForwardForever( 200, (1,0,0) ); + //level.destructible_spotlight thread maps\_debug::drawForwardForever( 200, (1,1,0) ); + + level notify( "new_destructible_spotlight" ); + + + level._destructible_spotlight Unlink(); + + + tag_origin = spawn_tag_origin(); + tag_origin LinkTo( self, action_v[ "spotlight_tag" ], ( 0, 0, 0 ), ( 0, 0, 0 ) ); + + //eModel thread maps\_debug::drawTagForever( action_v[ "spotlight_tag" ] ); + + level._destructible_spotlight.origin = self.breakable_light.origin; + level._destructible_spotlight.angles = self.breakable_light.angles; + level._destructible_spotlight thread spotlight_fizzles_out( action_v, eModel, damageType, partIndex, tag_origin ); + + wait( 0.05 );// Wait for the spawned tag_origin to get to the right place before linking + if ( IsDefined( tag_origin ) ) + { + // can be deleted during wait + level._destructible_spotlight LinkTo( tag_origin ); + } + +} + +is_valid_damagetype( damageType, v, idx, groupNum ) +{ + valid_damagetype = undefined; + if ( IsDefined( v[ "fx_valid_damagetype" ] ) ) + valid_damagetype = v[ "fx_valid_damagetype" ][ groupNum ][ idx ]; + + if ( !isdefined( valid_damagetype ) ) + return true; + + return IsSubStr( valid_damagetype, damageType ); +} + +destructible_sound_think( action_v, eModel, damageType, groupNum ) +{ + if ( isdefined( self.exploded ) ) + return undefined; + + if ( !isDefined( action_v[ "sound" ] ) ) + return undefined; + + if ( !isdefined( groupNum ) ) + groupNum = 0; + + assert( isDefined( action_v[ "sound" ][ groupNum ] ) ); + + for ( i = 0; i < action_v[ "sound" ][ groupNum ].size; i++ ) + { + validSoundCause = self isValidSoundCause( "soundCause", action_v, i, damageType, groupNum ); + if ( !validSoundCause ) + continue; + + soundAlias = action_v[ "sound" ][ groupNum ][ i ]; + soundTagName = action_v[ "tagName" ]; //chad - dont think I need a groupnum index here, but now we probably can't support playing sounds on multiple tags within one group + eModel thread play_sound( soundAlias, soundTagName ); + } + + return groupNum; +} + +destructible_fx_think( action_v, eModel, damageType, partIndex, groupNum ) +{ + if ( !isdefined( action_v[ "fx" ] ) ) + return undefined; + + if ( !isdefined( groupNum ) ) + groupNum = randomInt( action_v[ "fx_filename" ].size ); + + if ( !isDefined( action_v[ "fx" ][ groupNum ] ) ) + { + println( "^1destructible tried to use custom groupNum for FX but that group didn't exist" ); + groupNum = randomInt( action_v[ "fx_filename" ].size ); + } + + assert( isDefined( action_v[ "fx" ][ groupNum ] ) ); + + fx_size = action_v[ "fx_filename" ][ groupNum ].size; + + for ( idx = 0; idx < fx_size; idx++ ) + { + if ( !is_valid_damagetype( damageType, action_v, idx, groupNum ) ) + continue; + + fx = action_v[ "fx" ][ groupNum ][ idx ]; + + if ( IsDefined( action_v[ "fx_tag" ][ groupNum ][ idx ] ) ) + { + fx_tag = action_v[ "fx_tag" ][ groupNum ][ idx ]; + self notify( "FX_State_Change" + partIndex ); + + if ( action_v[ "fx_useTagAngles" ][ groupNum ][ idx ] ) + { + PlayFXOnTag( fx, eModel, fx_tag ); + } + else + { + fxOrigin = eModel GetTagOrigin( fx_tag ); + forward = ( fxOrigin + ( 0, 0, 100 ) ) - fxOrigin; + PlayFX( fx, fxOrigin, forward ); + } + } + else + { + fxOrigin = eModel.origin; + forward = ( fxOrigin + ( 0, 0, 100 ) ) - fxOrigin; + PlayFX( fx, fxOrigin, forward ); + } + } + + return groupNum; +} + +destructible_animation_think( action_v, eModel, damageType, partIndex ) +{ + if ( IsDefined( self.exploded ) ) + return undefined; + + if ( !isdefined( action_v[ "animation" ] ) ) + return undefined; + + if ( IsDefined( action_v[ "randomly_flip" ] ) && !isdefined( self.script_noflip ) ) + { + if ( cointoss() ) + { + // flip it around for randomness + self.angles += ( 0, 180, 0 ); + } + } + + // this stuff is SP only + if ( IsDefined( action_v[ "spotlight_tag" ] ) ) + { + thread destructible_spotlight_think( action_v, eModel, damageType, partIndex ); + wait( 0.05 ); + } + + array = random( action_v[ "animation" ] ); + + animName = array[ "anim" ]; + animTree = array[ "animTree" ]; + groupNum = array[ "groupNum" ]; + mpAnim = array[ "mpAnim" ]; + + maxStartDelay = array[ "maxStartDelay" ]; + animRateMin = array[ "animRateMin" ]; + animRateMax = array[ "animRateMax" ]; + + if ( !isdefined( animRateMin ) ) + animRateMin = 1.0; + if ( !isdefined( animRateMax ) ) + animRateMax = 1.0; + if ( animRateMin == animRateMax ) + animRate = animRateMin; + else + animRate = RandomFloatRange( animRateMin, animRateMax ); + + vehicle_dodge_part_animation = array[ "vehicle_exclude_anim" ]; + + if ( self.code_classname == "script_vehicle" && vehicle_dodge_part_animation ) + return undefined; + + eModel self_func( "useanimtree", animTree ); + + animType = array[ "animType" ]; + + if ( !isdefined( self.animsApplied ) ) + self.animsApplied = []; + self.animsApplied[ self.animsApplied.size ] = animName; + + if ( IsDefined( self.exploding ) ) + self clear_anims( eModel ); + + if ( IsDefined( maxStartDelay ) && maxStartDelay > 0 ) + wait RandomFloat( maxStartDelay ); + + // Multiplayer animations work now + if ( !isSP() ) + { + if ( IsDefined( mpAnim ) ) + self self_func( "scriptModelPlayAnim", mpAnim ); + return groupNum; + } + + if ( animType == "setanim" ) + { + eModel self_func( "setanim", animName, 1.0, 1.0, animRate ); + return groupNum; + } + + if ( animType == "setanimknob" ) + { + eModel self_func( "setanimknob", animName, 1.0, 0, animRate ); + return groupNum; + } + + AssertMsg( "Tried to play an animation on a destructible with an invalid animType: " + animType ); + return undefined; +} + +clear_anims( eModel ) +{ + //clear all previously blended anims if the vehicle is exploding so the explosion doesn't have to blend with anything + if ( IsDefined( self.animsApplied ) ) + { + foreach ( animation in self.animsApplied ) + { + if ( isSP() ) + eModel self_func( "clearanim", animation, 0 ); + else + eModel self_func( "scriptModelClearAnim" ); + } + } +} + +init_destroyed_count() +{ + level._destroyedCount = 0; + level._destroyedCountTimeout = 0.5; + + if ( isSP() ) + level._maxDestructions = 20; + else + level._maxDestructions = 2; + +} + +add_to_destroyed_count() +{ + level._destroyedCount++; + + wait( level._destroyedCountTimeout ); + + level._destroyedCount--; + + Assert( level._destroyedCount >= 0 ); +} + +get_destroyed_count() +{ + return( level._destroyedCount ); +} + +get_max_destroyed_count() +{ + return( level._maxDestructions ); +} + + +init_destructible_frame_queue() +{ + level._destructibleFrameQueue = []; +} + +add_destructible_to_frame_queue( destructible, partInfo, damage ) +{ + entNum = self GetEntityNumber(); + + if ( !isDefined( level._destructibleFrameQueue[ entNum ] ) ) + { + level._destructibleFrameQueue[ entNum ] = SpawnStruct(); + level._destructibleFrameQueue[ entNum ].entNum = entNum; + level._destructibleFrameQueue[ entNum ].destructible = destructible; + level._destructibleFrameQueue[ entNum ].totalDamage = 0; + level._destructibleFrameQueue[ entNum ].nearDistance = 9999999; + level._destructibleFrameQueue[ entNum ].fxCost = 0; + } + + level._destructibleFrameQueue[ entNum ].fxCost += partInfo.v[ "fxcost" ]; + + level._destructibleFrameQueue[ entNum ].totalDamage += damage; + if ( partInfo.v[ "distance" ] < level._destructibleFrameQueue[ entNum ].nearDistance ) + level._destructibleFrameQueue[ entNum ].nearDistance = partInfo.v[ "distance" ]; + + thread handle_destructible_frame_queue(); +} + + +handle_destructible_frame_queue() +{ + level notify( "handle_destructible_frame_queue" ); + level endon( "handle_destructible_frame_queue" ); + + wait( 0.05 ); + + currentQueue = level._destructibleFrameQueue; + level._destructibleFrameQueue = []; + + sortedQueue = sort_destructible_frame_queue( currentQueue ); + + for ( i = 0; i < sortedQueue.size; i++ ) + { + if ( get_destroyed_count() < get_max_destroyed_count() ) + { + if ( sortedQueue[ i ].fxCost ) + thread add_to_destroyed_count(); + + sortedQueue[ i ].destructible notify( "queue_processed", true ); + } + else + { + sortedQueue[ i ].destructible notify( "queue_processed", false ); + } + } +} + + +sort_destructible_frame_queue( unsortedQueue ) +{ + sortedQueue = []; + foreach ( destructibleInfo in unsortedQueue ) + sortedQueue[ sortedQueue.size ] = destructibleInfo; + + // insertion sort + for ( i = 1; i < sortedQueue.size; i++ ) + { + queueStruct = sortedQueue[ i ]; + + for ( j = i - 1; j >= 0 && get_better_destructible( queueStruct, sortedQueue[ j ] ) == queueStruct; j-- ) + sortedQueue[ j + 1 ] = sortedQueue[ j ]; + + sortedQueue[ j + 1 ] = queueStruct; + } + + return sortedQueue; +} + + +get_better_destructible( destructibleInfo1, destructibleInfo2 ) +{ + // this is very basic; we can also account for distance, fxcost, etc... if we need to + if ( destructibleInfo1.totalDamage > destructibleInfo2.totalDamage ) + return destructibleInfo1; + else + return destructibleInfo2; +} + + +get_part_FX_cost_for_action_state( partIndex, actionStateIndex ) +{ + fxCost = 0; + + if ( !isDefined( level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ] ) ) + return fxCost; + + action_v = level._destructible_type[ self.destuctableInfo ].parts[ partIndex ][ actionStateIndex ].v; + + if ( IsDefined( action_v[ "fx" ] ) ) + { + foreach ( fxCostObj in action_v[ "fx_cost" ] ) + { + foreach ( fxCostVal in fxCostObj ) + fxCost += fxCostVal; + } + } + + return fxCost; +} \ No newline at end of file diff --git a/common_scripts/_destructible_types.gsc b/common_scripts/_destructible_types.gsc new file mode 100644 index 0000000..06a844d --- /dev/null +++ b/common_scripts/_destructible_types.gsc @@ -0,0 +1,5211 @@ +#include common_scripts\_destructible; +#using_animtree( "destructibles" ); + +makeType( destructibleType ) +{ + //println( destructibleType ); + + // if it's already been created dont create it again + infoIndex = getInfoIndex( destructibleType ); + if ( infoIndex >= 0 ) + return infoIndex; + + switch( destructibleType ) + { + case "toy_glass120x110": + toy_glass( "120x110" ); + break; + case "toy_glass120x44": + toy_glass( "120x44" ); + break; + case "toy_glass56x59": + toy_glass( "56x59" ); + break; + case "toy_glass74x110": + toy_glass( "74x110" ); + break; + case "toy_glass74x44": + toy_glass( "74x44" ); + break; + case "toy_dt_mirror": + toy_dt_mirror( "" ); + break; + case "toy_dt_mirror_large": + toy_dt_mirror( "_large" ); + break; + case "toy_tubetv_tv1": + toy_tubetv_( "tv1" ); + break; + case "toy_tubetv_tv2": + toy_tubetv_( "tv2" ); + break; + case "toy_tv_flatscreen_01": + toy_tvs_flatscreen( "01", "" ); + break; + case "toy_tv_flatscreen_02": + toy_tvs_flatscreen( "02", "" ); + break; + case "toy_tv_flatscreen_wallmount_01": + toy_tvs_flatscreen( "01", "wallmount_" ); + break; + case "toy_tv_flatscreen_wallmount_02": + toy_tvs_flatscreen( "02", "wallmount_" ); + break; + case "toy_transformer_ratnest01": + toy_transformer_ratnest01( destructibleType ); + break; + case "toy_transformer_small01": + toy_transformer_small01( destructibleType ); + break; + case "toy_generator": + toy_generator( destructibleType ); + break; + case "toy_generator_on": + toy_generator_on( destructibleType ); + break; + case "toy_solar_panel_01": + toy_solar_panel( "01" ); + break; + case "toy_oxygen_tank_01": + toy_oxygen_tank( "01" ); + break; + case "toy_oxygen_tank_02": + toy_oxygen_tank( "02" ); + break; + case "toy_moon_oxygen_tank_01": + toy_moon_oxygen_tank( "01" ); + break; + case "toy_electricbox2": + toy_electricbox2( destructibleType ); + break; + case "toy_electricbox4": + toy_electricbox4( destructibleType ); + break; + case "toy_airconditioner": + toy_airconditioner( destructibleType ); + break; + case "toy_ceiling_fan": + toy_ceiling_fan( destructibleType ); + break; + case "toy_wall_fan": + toy_wall_fan( destructibleType ); + break; + case "toy_propane_tank02": + toy_propane_tank02( destructibleType ); + break; + case "toy_propane_tank02_small": + toy_propane_tank02_small( destructibleType ); + break; + case "toy_copier": + toy_copier( destructibleType ); + break; + case "toy_firehydrant": + toy_firehydrant( destructibleType ); + break; + case "toy_parkingmeter": + toy_parkingmeter( destructibleType ); + break; + case "toy_mailbox": + toy_mailbox( destructibleType ); + break; + case "toy_mailbox2_black": + toy_mailbox2( "black" ); + break; + case "toy_mailbox2_green": + toy_mailbox2( "green" ); + break; + case "toy_mailbox2_yellow": + toy_mailbox2( "yellow" ); + break; + case "toy_newspaper_stand_red": + toy_newspaper_stand_red( destructibleType ); + break; + case "toy_newspaper_stand_blue": + toy_newspaper_stand_blue( destructibleType ); + break; + case "toy_filecabinet": + toy_filecabinet( destructibleType ); + break; + case "toy_trashbin_01": + toy_trashbin_01( destructibleType ); + break; + case "toy_trashbin_02": + toy_trashbin_02( destructibleType ); + break; + case "toy_recyclebin_01": + toy_recyclebin_01( destructibleType ); + break; + case "toy_trashcan_metal_closed": + toy_trashcan_metal_closed( destructibleType ); + break; + case "toy_water_collector": + toy_water_collector( destructibleType ); + break; + case "toy_foliage_tree_oak_1": + toy_foliage_tree_oak_1( destructibleType ); + break; + case "toy_usa_gas_station_trash_bin_01": + toy_usa_gas_station_trash_bin_01( destructibleType ); + break; + case "toy_usa_gas_station_trash_bin_02": + toy_usa_gas_station_trash_bin_02( destructibleType ); + break; + case "toy_light_ceiling_round": + toy_light_ceiling_round( destructibleType ); + break; + case "toy_light_ceiling_fluorescent": + toy_light_ceiling_fluorescent( destructibleType ); + break; + case "toy_light_ceiling_fluorescent_spotlight": + toy_light_ceiling_fluorescent_spotlight( destructibleType ); + break; + case "toy_light_ceiling_fluorescent_single": + toy_light_ceiling_fluorescent_single( destructibleType ); + break; + case "toy_light_ceiling_fluorescent_single_spotlight": + toy_light_ceiling_fluorescent_single_spotlight( destructibleType ); + break; + case "toy_bookstore_bookstand4_books": + toy_bookstore_bookstand4_books( destructibleType ); + break; + case "toy_locker_double": + toy_locker_double( destructibleType ); + break; + case "toy_chicken": + toy_chicken( "" ); + break; + case "toy_chicken_white": + toy_chicken( "_white" ); + break; + case "toy_chicken_black_white": + toy_chicken( "_black_white" ); + break; + case "vehicle_bus_destructible": + vehicle_bus_destructible(); + break; + case "vehicle_80s_sedan1_green": + vehicle_80s_sedan1( "green" ); + break; + case "vehicle_80s_sedan1_red": + vehicle_80s_sedan1( "red" ); + break; + case "vehicle_80s_sedan1_silv": + vehicle_80s_sedan1( "silv" ); + break; + case "vehicle_80s_sedan1_tan": + vehicle_80s_sedan1( "tan" ); + break; + case "vehicle_80s_sedan1_yel": + vehicle_80s_sedan1( "yel" ); + break; + case "vehicle_80s_sedan1_brn": + vehicle_80s_sedan1( "brn" ); + break; + case "vehicle_80s_hatch1_green": + vehicle_80s_hatch1( "green" ); + break; + case "vehicle_80s_hatch1_red": + vehicle_80s_hatch1( "red" ); + break; + case "vehicle_80s_hatch1_silv": + vehicle_80s_hatch1( "silv" ); + break; + case "vehicle_80s_hatch1_tan": + vehicle_80s_hatch1( "tan" ); + break; + case "vehicle_80s_hatch1_yel": + vehicle_80s_hatch1( "yel" ); + break; + case "vehicle_80s_hatch1_brn": + vehicle_80s_hatch1( "brn" ); + break; + case "vehicle_80s_hatch2_green": + vehicle_80s_hatch2( "green" ); + break; + case "vehicle_80s_hatch2_red": + vehicle_80s_hatch2( "red" ); + break; + case "vehicle_80s_hatch2_silv": + vehicle_80s_hatch2( "silv" ); + break; + case "vehicle_80s_hatch2_tan": + vehicle_80s_hatch2( "tan" ); + break; + case "vehicle_80s_hatch2_yel": + vehicle_80s_hatch2( "yel" ); + break; + case "vehicle_80s_hatch2_brn": + vehicle_80s_hatch2( "brn" ); + break; + case "vehicle_80s_wagon1_green": + vehicle_80s_wagon1( "green" ); + break; + case "vehicle_80s_wagon1_red": + vehicle_80s_wagon1( "red" ); + break; + case "vehicle_80s_wagon1_silv": + vehicle_80s_wagon1( "silv" ); + break; + case "vehicle_80s_wagon1_tan": + vehicle_80s_wagon1( "tan" ); + break; + case "vehicle_80s_wagon1_yel": + vehicle_80s_wagon1( "yel" ); + break; + case "vehicle_80s_wagon1_brn": + vehicle_80s_wagon1( "brn" ); + break; + case "vehicle_small_hatch_blue": + vehicle_small_hatch( "blue" ); + break; + case "vehicle_small_hatch_green": + vehicle_small_hatch( "green" ); + break; + case "vehicle_small_hatch_instant_green": + vehicle_small_hatch_instant( "green" ); + break; + case "vehicle_small_hatch_turq": + vehicle_small_hatch( "turq" ); + break; + case "vehicle_small_hatch_white": + vehicle_small_hatch( "white" ); + break; + case "vehicle_pickup": + vehicle_pickup( destructibleType ); + break; + case "vehicle_hummer": + vehicle_hummer( destructibleType ); + break; + case "vehicle_nx_hummer": + vehicle_nx_hummer( destructibleType ); + break; + case "vehicle_moving_truck": + vehicle_moving_truck( destructibleType ); + break; + case "vehicle_bm21_mobile_bed": + vehicle_bm21( destructibleType, "vehicle_bm21_mobile_bed_dstry" ); + break; + case "vehicle_bm21_cover": + vehicle_bm21( destructibleType, "vehicle_bm21_mobile_cover_dstry" ); + break; + case "vehicle_luxurysedan_2008": + vehicle_luxurysedan( ""); + break; + case "vehicle_luxurysedan_2008_gray": + vehicle_luxurysedan( "_gray"); + break; + case "vehicle_luxurysedan_2008_white": + vehicle_luxurysedan( "_white"); + break; + case "vehicle_uaz_winter": + vehicle_uaz_winter( destructibleType ); + break; + case "vehicle_uaz_fabric": + vehicle_uaz_fabric( destructibleType ); + break; + case "vehicle_uaz_hardtop": + vehicle_uaz_hardtop( destructibleType ); + break; + case "vehicle_uaz_open": + vehicle_uaz_open( destructibleType ); + break; + case "vehicle_policecar": + vehicle_policecar( destructibleType ); + break; + case "vehicle_policecar_russia": + vehicle_policecar_russia( destructibleType ); + break; + case "nx_vehicle_exfil_policecar": + nx_vehicle_exfil_policecar( destructibleType ); + break; + case "nx_vehicle_policecar_mexico": + nx_vehicle_policecar_mexico( destructibleType ); + break; + case "vehicle_taxi": + vehicle_taxi( destructibleType ); + break; + case "vehicle_mig29_landed": + vehicle_mig29_landed( destructibleType ); + break; + case "vehicle_mack_truck_short_snow": + vehicle_mack_truck_short( "snow" ); + break; + case "vehicle_mack_truck_short_green": + vehicle_mack_truck_short( "green" ); + break; + case "vehicle_mack_truck_short_white": + vehicle_mack_truck_short( "white" ); + break; + case "vehicle_motorcycle_01": + vehicle_motorcycle( "01" ); + break; + case "vehicle_motorcycle_02": + vehicle_motorcycle( "02" ); + break; + case "vehicle_subcompact_black": + vehicle_subcompact( "black" ); + break; + case "vehicle_subcompact_blue": + vehicle_subcompact( "blue" ); + break; + case "vehicle_subcompact_dark_gray": + vehicle_subcompact( "dark_gray" ); + break; + case "vehicle_subcompact_deep_blue": + vehicle_subcompact( "deep_blue" ); + break; + case "vehicle_subcompact_gold": + vehicle_subcompact( "gold" ); + break; + case "vehicle_subcompact_gray": + vehicle_subcompact( "gray" ); + break; + case "vehicle_subcompact_green": + vehicle_subcompact( "green" ); + break; + case "vehicle_subcompact_mica": + vehicle_subcompact( "mica" ); + break; + case "vehicle_subcompact_slate": + vehicle_subcompact( "slate" ); + break; + case "vehicle_subcompact_tan": + vehicle_subcompact( "tan" ); + break; + case "vehicle_subcompact_white": + vehicle_subcompact( "white" ); + break; + case "vehicle_coupe_black": + vehicle_coupe( "black" ); + break; + case "vehicle_coupe_blue": + vehicle_coupe( "blue" ); + break; + case "vehicle_coupe_dark_gray": + vehicle_coupe( "dark_gray" ); + break; + case "vehicle_coupe_deep_blue": + vehicle_coupe( "deep_blue" ); + break; + case "vehicle_coupe_gold": + vehicle_coupe( "gold" ); + break; + case "vehicle_coupe_gray": + vehicle_coupe( "gray" ); + break; + case "vehicle_coupe_green": + vehicle_coupe( "green" ); + break; + case "vehicle_coupe_mica": + vehicle_coupe( "mica" ); + break; + case "vehicle_coupe_slate": + vehicle_coupe( "slate" ); + break; + case "vehicle_coupe_tan": + vehicle_coupe( "tan" ); + break; + case "vehicle_coupe_white": + vehicle_coupe( "white" ); + break; + case "vehicle_van_black": + vehicle_van( "black" ); + break; + case "vehicle_van_blue": + vehicle_van( "blue" ); + break; + case "vehicle_van_dark_gray": + vehicle_van( "dark_gray" ); + break; + case "vehicle_van_deep_blue": + vehicle_van( "deep_blue" ); + break; + case "vehicle_van_gold": + vehicle_van( "gold" ); + break; + case "vehicle_van_gray": + vehicle_van( "gray" ); + break; + case "vehicle_van_green": + vehicle_van( "green" ); + break; + case "vehicle_van_mica": + vehicle_van( "mica" ); + break; + case "vehicle_van_slate": + vehicle_van( "slate" ); + break; + case "vehicle_van_tan": + vehicle_van( "tan" ); + break; + case "vehicle_van_white": + vehicle_van( "white" ); + break; + case "vehicle_suburban": + vehicle_suburban( destructibleType, "" ); + break; + case "vehicle_suburban_beige": + vehicle_suburban( destructibleType, "_beige" ); + break; + case "vehicle_suburban_dull": + vehicle_suburban( destructibleType, "_dull" ); + break; + case "vehicle_suburban_red": + vehicle_suburban( destructibleType, "_red" ); + break; + case "vehicle_snowmobile": + vehicle_snowmobile( destructibleType ); + break; + case "destructible_gaspump": + destructible_gaspump( destructibleType ); + break; + case "destructible_electrical_transformer_large": + destructible_electrical_transformer_large( destructibleType ); + break; + case "nx_vehicle_lapd": + nx_vehicle_lapd( destructibleType ); + break; + case "nx_vehicle_sedan": + nx_vehicle_sedan( destructibleType, "" ); + break; + case "nx_vehicle_sedan_black": + nx_vehicle_sedan( destructibleType, "black" ); + break; + case "nx_vehicle_sedan_blue": + nx_vehicle_sedan( destructibleType, "blue" ); + break; + case "nx_vehicle_sedan_darkgray": + nx_vehicle_sedan( destructibleType, "darkgray" ); + break; + case "nx_vehicle_sedan_gray": + nx_vehicle_sedan( destructibleType, "gray" ); + break; + case "nx_vehicle_sedan_green": + nx_vehicle_sedan( destructibleType, "green" ); + break; + case "nx_vehicle_sedan_red": + nx_vehicle_sedan( destructibleType, "red" ); + break; + case "nx_vehicle_sedan_tan": + nx_vehicle_sedan( destructibleType, "tan" ); + break; + case "nx_vehicle_sedan_yellow": + nx_vehicle_sedan( destructibleType, "yellow" ); + break; + case "nx_vehicle_micro_black": + nx_vehicle_micro( destructibleType, "black" ); + break; + case "nx_vehicle_micro_brightblue": + nx_vehicle_micro( destructibleType, "brightblue" ); + break; + case "nx_vehicle_micro_brightgreen": + nx_vehicle_micro( destructibleType, "brightgreen" ); + break; + case "nx_vehicle_micro_brightred": + nx_vehicle_micro( destructibleType, "brightred" ); + break; + case "nx_vehicle_micro_brightyellow": + nx_vehicle_micro( destructibleType, "brightyellow" ); + break; + case "nx_vehicle_micro_orange": + nx_vehicle_micro( destructibleType, "orange" ); + break; + case "nx_vehicle_micro_white": + nx_vehicle_micro( destructibleType, "white" ); + break; + case "nx_vehicle_civilian_suv_black": + nx_vehicle_civilian_suv( destructibleType, "black" ); + break; + case "nx_vehicle_civilian_suv_blue": + nx_vehicle_civilian_suv( destructibleType, "blue" ); + break; + case "nx_vehicle_civilian_suv_burgundy": + nx_vehicle_civilian_suv( destructibleType, "burgundy" ); + break; + case "nx_vehicle_civilian_suv_bronze": + nx_vehicle_civilian_suv( destructibleType, "bronze" ); + break; + case "nx_vehicle_civilian_suv_darkgray": + nx_vehicle_civilian_suv( destructibleType, "darkgray" ); + break; + case "nx_vehicle_civilian_suv_gray": + nx_vehicle_civilian_suv( destructibleType, "gray" ); + break; + case "nx_vehicle_civilian_suv_green": + nx_vehicle_civilian_suv( destructibleType, "green" ); + break; + case "nx_vehicle_civilian_suv_red": + nx_vehicle_civilian_suv( destructibleType, "red" ); + break; + case "nx_vehicle_civilian_suv_silver": + nx_vehicle_civilian_suv( destructibleType, "silver" ); + break; + case "nx_vehicle_civilian_suv_tan": + nx_vehicle_civilian_suv( destructibleType, "tan" ); + break; + case "nx_destructible_display_screen_01_1": + nx_destructible_display_screen_01( "_1" ); + break; + case "nx_toy_lunar_trash_can": + nx_toy_lunar_trash_can( destructibleType ); + break; + case "nx_toy_lunar_oxygen_tank_01": + nx_toy_lunar_oxygen_tank( "01" ); + break; + case "nx_toy_lunar_door_interface": + nx_toy_lunar_door_interface( destructibleType); + break; + case "nx_destructible_wind_turbine": + nx_destructible_wind_turbine( destructibleType ); + break; + case "nx_jow_destructible_line6_ld300_bass": + nx_jow_destructible_line6_ld300_bass(destructibleType); + break; + case "nx_jow_destructible_mansion_globe": + nx_jow_destructible_mansion_globe(destructibleType); + break; + case "vehicle_scooter_vespa": + vehicle_scooter( "vehicle_scooter_vespa" ); + break; + case "nx_toy_propane_tank_hospital": + nx_toy_propane_tank_hospital( destructibleType ); + break; + case "nx_toy_industrial_light_01_off": + nx_toy_industrial_light_01( destructibleType ); + break; + + // Default means invalid type + default: + assertMsg( "Destructible object 'destructible_type' key/value of '" + destructibleType + "' is not valid" ); + break; + } + + infoIndex = getInfoIndex( destructibleType ); + assert( infoIndex >= 0 ); + return infoIndex; +} + +getInfoIndex( destructibleType ) +{ + if ( !isdefined( level._destructible_type ) ) + return - 1; + if ( level._destructible_type.size == 0 ) + return - 1; + + for ( i = 0 ; i < level._destructible_type.size ; i++ ) + { + if ( destructibleType == level._destructible_type[ i ].v[ "type" ] ) + return i; + } + + // didn't find it in the array, must not exist + return - 1; +} + +toy_glass( size ) +{ + //--------------------------------------------------------------------- + // glass break test 120x110inches + //--------------------------------------------------------------------- + destructible_create( "toy_glass" + size, "tag_origin", 50 ); + destructible_splash_damage_scaler( 5 ); + destructible_sound( "building_glass_shatter" ); + // Glass + tag = "tag_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/highrise_glass_" + size ); + //destructible_fx( tag, "props/highrise_glass_120x110_fountain" ); + destructible_sound( "building_glass_blowout" ); + destructible_state( tag + "_des", undefined, 100, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/highrise_glass_" + size + "_edge"); + destructible_sound( "building_glass_blowout" ); + destructible_state( undefined ); +} + +toy_dt_mirror( size ) +{ + //--------------------------------------------------------------------- + // dt_mirror + //--------------------------------------------------------------------- + destructible_create( "toy_dt_mirror" + size, "tag_origin", 150, undefined, 32 ); + destructible_splash_damage_scaler( 5 ); + destructible_fx( "tag_fx", "props/mirror_shatter" + size ); + destructible_sound( "mirror_shatter" ); + destructible_state( "tag_origin", "dt_mirror" + size + "_dam", 150, undefined ); + destructible_fx( "tag_fx", "props/mirror_dt_panel" + size + "_broken" ); + destructible_explode( 1000, 2000, 32, 32, 32, 48, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( "tag_origin", "dt_mirror" + size + "_des", 150, undefined ); +} + +toy_tubetv_( version ) +{ + //--------------------------------------------------------------------- + // Tube TV + //--------------------------------------------------------------------- + destructible_create( "toy_tubetv_" + version, "tag_origin", 1, undefined, 32 ); + destructible_splash_damage_scaler( 1 ); + destructible_fx( "tag_fx", "explosions/tv_explosion" ); + destructible_sound( "tv_shot_burst" ); + destructible_explode( 20, 2000, 9, 9, 3, 3, undefined, 12 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "com_" + version + "_d", undefined, undefined, "no_melee" ); +} + +toy_tvs_flatscreen( version, mounting ) +{ + //--------------------------------------------------------------------- + // Flatscreen TVs + //--------------------------------------------------------------------- + destructible_create( "toy_tv_flatscreen_" + mounting + version, "tag_origin", 1, undefined, 32 ); + destructible_splash_damage_scaler( 1 ); + destructible_fx( "tag_fx", "explosions/tv_flatscreen_explosion" ); + destructible_sound( "tv_shot_burst" ); + destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "ma_flatscreen_tv_" + mounting + "broken_" + version, 200, undefined, "no_melee" ); +} + +toy_transformer_ratnest01( destructibleType ) +{ + //--------------------------------------------------------------------- + // Transformer w/ wires for Favela + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 75, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 75, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 150, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_sparks", "explosions/transformer_spark_runner", .5 ); + destructible_loopsound( "transformer_spark_loop" ); + destructible_healthdrain( 24, 0.2 ); + destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_sparks", "explosions/transformer_spark_runner", .5 ); + destructible_loopfx( "tag_fx", "fire/transformer_blacksmoke_fire", .4 ); + destructible_sound( "transformer01_flareup_med" ); + destructible_loopsound( "transformer_spark_loop" ); + destructible_healthdrain( 24, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 400, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "explosions/transformer_explosion", false ); + destructible_fx( "tag_fx", "fire/firelp_small_pm" ); + destructible_sound( "transformer01_explode" ); + destructible_explode( 7000, 8000, 150, 256, 16, 100, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "utility_transformer_ratnest01_dest", undefined, undefined, "no_melee" ); +} + +toy_transformer_small01( destructibleType ) +{ + //--------------------------------------------------------------------- + // Small hanging Transformer box for Favela + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 75, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 75, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 150, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx", "explosions/transformer_spark_runner", .5 ); + destructible_loopsound( "transformer_spark_loop" ); + destructible_healthdrain( 24, 0.2 ); + destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx", "explosions/transformer_spark_runner", .5 ); + destructible_loopfx( "tag_fx", "fire/transformer_small_blacksmoke_fire", .4 ); + destructible_sound( "transformer01_flareup_med" ); + destructible_loopsound( "transformer_spark_loop" ); + destructible_healthdrain( 24, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 400, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "explosions/transformer_explosion", false ); + destructible_fx( "tag_fx", "fire/firelp_small_pm" ); + destructible_sound( "transformer01_explode" ); + destructible_explode( 7000, 8000, 150, 256, 16, 100, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "utility_transformer_small01_dest", undefined, undefined, "no_melee" ); +} + +toy_generator( destructibleType ) +{ + //--------------------------------------------------------------------- + // Red Generator + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_bounce", 75, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 75, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_blacksmoke", 0.4 ); + destructible_loopfx( "tag_fx4", "explosions/generator_spark_runner", .9 ); + destructible_loopfx( "tag_fx3", "explosions/generator_spark_runner", .6123 ); + destructible_loopsound( "generator_spark_loop" ); + destructible_healthdrain( 24, 0.2, 64, "allies" ); + destructible_state( undefined, undefined, 400, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "explosions/generator_explosion", false ); + destructible_fx( "tag_fx", "fire/generator_des_fire" ); + destructible_sound( "generator01_explode" ); + destructible_explode( 7000, 8000, 128, 128, 16, 50, undefined, 0 ); // force_min, force_max, range, mindamage, maxdamage + destructible_anim( get_precached_anim( "generator_explode" ), #animtree, "setanimknob", undefined, undefined, "generator_explode" ); + destructible_state( undefined, "machinery_generator_des", undefined, undefined, "no_melee" ); +} + +toy_generator_on( destructibleType ) +{ + //--------------------------------------------------------------------- + // Red Generator, on... with sound and vibration animation + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_bounce", 0, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_fx2", "smoke/generator_exhaust", 0.4 ); + destructible_anim( get_precached_anim( "generator_vibration" ), #animtree, "setanimknob", undefined, undefined, "generator_vibration" ); + destructible_loopsound( "generator_running" ); + destructible_state( "tag_origin", "machinery_generator", 100 ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_whitesmoke", 0.4 ); + destructible_loopsound( "generator_running" ); + destructible_state( undefined, undefined, 25, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_blacksmoke", 0.4 ); + destructible_loopsound( "generator_damage_loop" ); + destructible_state( undefined, undefined, 50, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx2", "smoke/generator_damage_blacksmoke", 0.4 ); + destructible_loopfx( "tag_fx4", "explosions/generator_spark_runner", .9 ); + destructible_loopfx( "tag_fx3", "explosions/generator_spark_runner", .6123 ); + destructible_loopsound( "generator_spark_loop" ); + destructible_loopsound( "generator_damage_loop" ); + destructible_healthdrain( 24, 0.2, 64, "allies" ); + destructible_state( undefined, undefined, 75, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "explosions/generator_explosion", false ); + destructible_fx( "tag_fx", "fire/generator_des_fire" ); + destructible_sound( "generator01_explode" ); + destructible_explode( 7000, 8000, 128, 128, 16, 50, undefined, 0 ); // force_min, force_max, range, mindamage, maxdamage + destructible_anim( get_precached_anim( "generator_explode" ), #animtree, "setanimknob", undefined, 0, "generator_explode" ); + destructible_anim( get_precached_anim( "generator_explode_02" ), #animtree, "setanimknob", undefined, 0, "generator_explode_02" ); + destructible_anim( get_precached_anim( "generator_explode_03" ), #animtree, "setanimknob", undefined, 0, "generator_explode_03" ); + destructible_state( undefined, "machinery_generator_des", undefined, undefined, "no_melee" ); +} + +toy_solar_panel( version ) +{ + //--------------------------------------------------------------------- + // Destructible Solar Panel + //--------------------------------------------------------------------- + destructible_create( "toy_solar_panel_" + version, "tag_origin", 750, undefined, 32, "no_melee_yes_impact" ); + destructible_fx( "tag_fx", "nx/props/nx_lunar_solar_panel_glass_large" ); + destructible_state( undefined, "nx_lunar_solar_panel_damage", 1500, undefined, 32, "no_melee_yes_impact" ); + destructible_explode( 7000, 8000, 150, 256, 16, 48, undefined, 32 ); + destructible_fx( "tag_fx", "nx/props/nx_lunar_solar_panel_explosion" ); + destructible_state( undefined, "nx_lunar_solar_panel_damage_02", undefined, undefined, "no_melee_yes_impact" ); +} + +toy_oxygen_tank( version ) +{ + //--------------------------------------------------------------------- + // Oxygen Tanks 01 and 02 + //--------------------------------------------------------------------- + destructible_create( "toy_oxygen_tank_" + version, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_healthdrain( 12, 0.2, 64, "allies" ); + destructible_loopsound( "oxygen_tank_leak_loop" ); + destructible_fx( "tag_cap", "props/oxygen_tank" + version + "_cap" ); + destructible_loopfx( "tag_cap", "distortion/oxygen_tank_leak", 0.4 ); + destructible_state( undefined, "machinery_oxygen_tank" + version + "_dam", 300, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "explosions/oxygen_tank" + version + "_explosion", false ); + destructible_sound( "oxygen_tank_explode" ); + destructible_explode( 7000, 8000, 150, 256, 16, 150, undefined, 32 ); + destructible_state( undefined, "machinery_oxygen_tank" + version + "_des", undefined, undefined, "no_melee" ); +} + +toy_moon_oxygen_tank( version ) +{ + //--------------------------------------------------------------------- + // Moon Oxygen Tanks 01 and 02 + //--------------------------------------------------------------------- + destructible_create( "toy_moon_oxygen_tank_" + version, "tag_origin", 50, undefined, 32, "no_melee" ); + destructible_healthdrain( 12, 0.2, 100, "allies" ); + destructible_loopsound( "oxygen_tank_leak_loop" ); + destructible_loopfx( "tag_cap", "distortion/oxygen_tank_leak", 0.4 ); + destructible_state( undefined, "nx_lunar_exploding_object", 50, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "explosions/oxygen_tank" + version + "_explosion", false ); + destructible_sound( "oxygen_tank_explode" ); + destructible_explode( 90000, 95000, 200, 256, 75, 500, undefined, 0 ); + destructible_state( undefined, "machinery_oxygen_tank" + version + "_des", undefined, undefined, "no_melee" ); +} + +toy_electricbox2( destructibleType ) +{ + //--------------------------------------------------------------------- + // electric box large toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_fx( "tag_fx", "props/electricbox4_explode", undefined, undefined, undefined, 1 ); + destructible_sound( "exp_fusebox_sparks" ); + destructible_explode( 1000, 2000, 32, 32, 32, 48, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( undefined, "me_electricbox2_dest", undefined, undefined, "no_melee" ); + // door + destructible_part( "tag_fx", "me_electricbox2_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + + // door upper + destructible_part( "tag_door_upper", "me_electricbox2_door_upper", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_electricbox4( destructibleType ) +{ + //--------------------------------------------------------------------- + // electric box medium toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_fx( "tag_fx", "props/electricbox4_explode", undefined, undefined, undefined, 1 ); + destructible_sound( "exp_fusebox_sparks" ); + destructible_explode( 20, 2000, 32, 32, 32, 48, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( undefined, "me_electricbox4_dest", undefined, undefined, "no_melee" ); + // door + destructible_part( "tag_fx", "me_electricbox4_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +toy_airconditioner( destructibleType ) +{ + //--------------------------------------------------------------------- + // Small Airconditioner hanging on wall + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 0, undefined, 32 ); + destructible_anim( get_precached_anim( "ex_airconditioner_fan" ), #animtree, "setanimknob", undefined, undefined, "ex_airconditioner_fan" ); + destructible_loopsound( "airconditioner_running_loop" ); + destructible_state( "tag_origin", "com_ex_airconditioner", 300 ); + destructible_fx( "tag_fx", "explosions/airconditioner_ex_explode", undefined, undefined, undefined, 1 ); + destructible_sound( "airconditioner_burst" ); + destructible_explode( 1000, 2000, 32, 32, 32, 48, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( undefined, "com_ex_airconditioner_dam", undefined, undefined, "no_melee" ); + // door + destructible_part( "tag_fx", "com_ex_airconditioner_fan", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + + +toy_ceiling_fan( destructibleType ) +{ + //--------------------------------------------------------------------- + // ceiling fan + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 0, undefined, 32 ); + destructible_anim( get_precached_anim( "me_fanceil1_spin" ), #animtree, "setanimknob", undefined, undefined, "me_fanceil1_spin" ); + destructible_loopsound( "nx_ceiling_fan_loop" ); + destructible_state( "tag_origin", "me_fanceil1", 150 ); + destructible_anim( get_precached_anim( "me_fanceil1_spin_stop" ), #animtree, "setanimknob", undefined, undefined, "me_fanceil1_spin_stop" ); + destructible_fx( "tag_fx", "explosions/ceiling_fan_explosion" ); + destructible_sound( "ceiling_fan_sparks" ); + destructible_explode( 1000, 2000, 32, 32, 5, 32, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( undefined, "me_fanceil1_des", undefined, undefined, "no_melee" ); + destructible_part( "tag_fx", undefined, 150, undefined, undefined, undefined, 1.0 ); +} + + +toy_wall_fan( destructibleType ) +{ + //--------------------------------------------------------------------- + // wall fan + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_swivel", 0, undefined, 32 ); + destructible_anim( get_precached_anim( "wall_fan_rotate" ), #animtree, "setanimknob", undefined, undefined, "wall_fan_rotate" ); + destructible_loopsound( "wall_fan_fanning" ); + destructible_state( "tag_wobble", "cs_wallfan1", 150 ); + destructible_anim( get_precached_anim( "wall_fan_stop" ), #animtree, "setanimknob", undefined, undefined, "wall_fan_wobble" ); + destructible_fx( "tag_fx", "explosions/wallfan_explosion_dmg" ); + destructible_sound( "wall_fan_sparks" ); + // destructible_loopsound( "wall_fan_malfuntioning" ); + destructible_state( "tag_wobble", "cs_wallfan1", 150, undefined, "no_melee" ); + // destructible_anim( get_precached_anim( "wall_fan_stop" ), #animtree, "setanimknob", undefined, undefined, "wall_fan_stop" ); + destructible_fx( "tag_fx", "explosions/wallfan_explosion_des" ); + destructible_sound( "wall_fan_break" ); + destructible_state( undefined, "cs_wallfan1_dmg", undefined, undefined, "no_melee" ); +} + +toy_propane_tank02( destructibleType ) +{ + //--------------------------------------------------------------------- + // Large Propane tank goes KaBooM + //--------------------------------------------------------------------- + + destructible_create( destructibleType, "tag_origin", 50, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 5 ); + destructible_state( undefined, undefined, 350, undefined, 32, "no_melee" ); + destructible_loopsound( "propanetank02_gas_leak_loop" ); + destructible_loopfx( "tag_cap", "distortion/propane_cap_distortion", 0.1 ); + destructible_state( undefined, undefined, 350, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_cap", "fire/propane_capfire_leak", 0.1 ); + destructible_sound( "propanetank02_flareup_med" ); + destructible_loopsound( "propanetank02_fire_med" ); + destructible_healthdrain( 12, 0.2, 300, "allies" ); + destructible_state( undefined, undefined, 150, undefined, 32, "no_melee" ); + destructible_physics( "tag_cap", ( 50, 0, 0 ) ); + destructible_loopfx( "tag_cap", "fire/propane_capfire", 0.6 ); + destructible_fx( "tag_valve", "fire/propane_valvefire_flareup" ); + destructible_physics( "tag_valve", ( 50, 0, 0 ) ); + destructible_fx( "tag_cap", "fire/propane_capfire_flareup" ); + destructible_loopfx( "tag_valve", "fire/propane_valvefire", 0.1 ); + destructible_sound( "propanetank02_flareup2_med" ); + destructible_loopsound( "propanetank02_fire_med" ); + destructible_state( undefined, undefined, 150, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "fire/propane_small_fire" ); + destructible_fx( "tag_fx", "explosions/propane_large_exp_fireball" ); + destructible_fx( "tag_fx", "explosions/propane_large_exp", false ); + destructible_sound( "propanetank02_explode" ); + destructible_loopsound( "propanetank02_fire_blown_med" ); + destructible_explode( 7000, 8000, 600, 600, 32, 300 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "com_propane_tank02_DES", undefined, undefined, "no_melee" ); + // Lower Valve + destructible_part( "tag_valve", "com_propane_tank02_valve" ); + // Top Cap + destructible_part( "tag_cap", "com_propane_tank02_cap" ); + +} + +toy_propane_tank02_small( destructibleType ) +{ + //--------------------------------------------------------------------- + // Small Propane tank goes KaBooM + //--------------------------------------------------------------------- + + destructible_create( destructibleType, "tag_origin", 50, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 10 ); + destructible_state( undefined, undefined, 350, undefined, 32, "no_melee" ); + destructible_loopsound( "propanetank02_gas_leak_loop" ); + destructible_loopfx( "tag_cap", "distortion/propane_cap_distortion", 0.1 ); + destructible_state( undefined, undefined, 350, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_cap", "fire/propane_capfire_leak", 0.1 ); + destructible_sound( "propanetank02_flareup_med" ); + destructible_loopsound( "propanetank02_fire_med" ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_physics( "tag_cap", ( 50, 0, 0 ) ); + destructible_loopfx( "tag_cap", "fire/propane_capfire", 0.6 ); + destructible_fx( "tag_valve", "fire/propane_valvefire_flareup" ); + destructible_physics( "tag_valve", ( 50, 0, 0 ) ); + destructible_fx( "tag_cap", "fire/propane_capfire_flareup" ); + destructible_loopfx( "tag_valve", "fire/propane_valvefire", 0.1 ); + destructible_sound( "propanetank02_flareup_med" ); + destructible_loopsound( "propanetank02_fire_med" ); + destructible_state( undefined, undefined, 200, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "fire/propane_small_fire" ); + //destructible_fx( "tag_fx", "explosions/propane_large_exp_fireball" ); + destructible_fx( "tag_fx", "explosions/propane_large_exp", false ); + destructible_sound( "propanetank02_explode" ); + destructible_explode( 7000, 8000, 400, 400, 32, 100 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "com_propane_tank02_small_DES", undefined, undefined, "no_melee" ); + // Lower Valve + destructible_part( "tag_valve", "com_propane_tank02_small_valve" ); + // Top Cap + destructible_part( "tag_cap", "com_propane_tank02_small_cap" ); + +} + +toy_copier( destructibleType ) +{ + //--------------------------------------------------------------------- + // copier toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_left_feeder", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_left_feeder", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 500, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_fx", "props/photocopier_sparks", 3 ); + //destructible_loopsound( "copier_spark_loop" ); + destructible_healthdrain( 12, 0.2 ); + destructible_state( undefined, undefined, 800, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "props/photocopier_exp", false ); + destructible_fx( "tag_fx", "props/photocopier_fire" ); + //destructible_sound( "copier_exp" ); + //destructible_loopsound( "copier_fire_loop" ); + destructible_explode( 7000, 8000, 96, 96, 32, 48 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "prop_photocopier_destroyed", undefined, undefined, "no_melee" ); + + + // left feeder part + destructible_part( "tag_left_feeder", "prop_photocopier_destroyed_left_feeder", 4, undefined, undefined, undefined, 1.0, 1.0 ); + // right shelf + destructible_part( "tag_right_shelf", "prop_photocopier_destroyed_right_shelf", 4, undefined, undefined, undefined, 1.0, 1.0 ); + // top cover + destructible_part( "tag_top", "prop_photocopier_destroyed_top", 4, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_firehydrant( destructibleType ) +{ + //--------------------------------------------------------------------- + // fire hydrant toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 250, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 11 ); + destructible_state( undefined, undefined, 500, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_cap", "props/firehydrant_leak", 0.1 ); + destructible_loopsound( "firehydrant_spray_loop" ); + destructible_healthdrain( 12, 0.2 ); + destructible_state( undefined, undefined, 800, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "props/firehydrant_exp", false ); + destructible_fx( "tag_fx", "props/firehydrant_spray_10sec", false ); + destructible_sound( "firehydrant_burst" ); + destructible_explode( 17000, 18000, 96, 96, 32, 48 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "com_firehydrant_dest", undefined, undefined, "no_melee" ); + + // destroyed hydrant + destructible_part( "tag_fx", "com_firehydrant_dam", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // side cap + destructible_part( "tag_cap", "com_firehydrant_cap", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +toy_parkingmeter( destructibleType ) +{ + //--------------------------------------------------------------------- + // parking meter toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_meter", 120 ); + destructible_fx( "tag_fx", "props/parking_meter_coins", true, damage_not( "splash" ) ); // coin drop + destructible_fx( "tag_fx", "props/parking_meter_coins_exploded", true, "splash" ); // coin drop + destructible_sound( "exp_parking_meter_sweet" ); // coin drop sounds + destructible_explode( 2800, 3000, 64, 64, 0, 0, true ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue to take damage + destructible_state( undefined, "com_parkingmeter_damaged", 20, undefined, undefined, "splash" ); + destructible_state( undefined, "com_parkingmeter_destroyed", undefined, undefined, undefined, undefined, undefined, true ); + + // coin collector's cap + destructible_part( "tag_cap", "com_parkingmeter_cap", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +toy_mailbox( destructibleType ) +{ + //--------------------------------------------------------------------- + // mail box without pole + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 200 ); + destructible_fx( "tag_fx", "props/mail_box_explode", true ); // mail flying + destructible_sound( "exp_mailbox_sweet" ); // mail paper sounds + destructible_explode( 100, 2000, 64, 64, 0, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( "tag_origin", "com_mailbox_dam" ); + destructible_part( "tag_door", "com_mailbox_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_flag", "com_mailbox_flag", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_mailbox2( color ) +{ + //--------------------------------------------------------------------- + // mailbox2 w/ pole toy + //--------------------------------------------------------------------- + destructible_create( "toy_mailbox2_" + color, "tag_origin", 120 ); + destructible_fx( "tag_fx", "props/mail_box_explode", true, damage_not( "splash" ) ); // bullet damages + destructible_fx( "tag_fx", "props/mail_box_explode", true, "splash" ); // grenade damages + destructible_sound( "exp_mailbox_sweet" ); + destructible_explode( 2800, 3000, 64, 64, 0, 0, true ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue to take damage + destructible_state( undefined, "mailbox_" + color + "_dam", 20, undefined, undefined, "splash" ); + destructible_state( undefined, "mailbox_black_dest", undefined, undefined, undefined, undefined, undefined, true ); + + // mailbox door + destructible_part( "tag_door", "mailbox_" + color + "_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_flag", "mailbox_black_flag", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + + +toy_newspaper_stand_red( destructibleType ) +{ + //--------------------------------------------------------------------- + // newspaper stand toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120 ); + destructible_fx( "tag_door", "props/news_stand_paper_spill", true, damage_not( "splash" ) ); // coin drop + destructible_sound( "exp_newspaper_box" ); // coin drop sounds + destructible_explode( 2500, 2501, 64, 64, 0, 0, true ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue to take damage + destructible_state( undefined, "com_newspaperbox_red_dam", 20, undefined, undefined, "splash" ); + destructible_fx( "tag_fx", "props/news_stand_explosion", true, "splash" ); // coin drop + destructible_state( undefined, "com_newspaperbox_red_des", undefined, undefined, undefined, undefined, undefined, false ); + + // front door + destructible_part( "tag_door", "com_newspaperbox_red_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +toy_newspaper_stand_blue( destructibleType ) +{ + //--------------------------------------------------------------------- + // newspaper stand toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120 ); + destructible_fx( "tag_door", "props/news_stand_paper_spill_shatter", true, damage_not( "splash" ) ); // coin drop + destructible_sound( "exp_newspaper_box" ); // coin drop sounds + destructible_explode( 800, 2001, 64, 64, 0, 0, true ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue to take damage + destructible_state( undefined, "com_newspaperbox_blue_dam", 20, undefined, undefined, "splash" ); + destructible_fx( "tag_fx", "props/news_stand_explosion", true, "splash" ); // coin drop + destructible_state( undefined, "com_newspaperbox_blue_des", undefined, undefined, undefined, undefined, undefined, false ); + + // front door + destructible_part( "tag_door", "com_newspaperbox_blue_door", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_filecabinet( destructibleType ) +{ + //--------------------------------------------------------------------- + // filecabinet toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120 ); + destructible_fx( "tag_drawer_lower", "props/filecabinet_dam", true, damage_not( "splash" ) ); // coin drop + destructible_sound( "exp_filecabinet" ); + destructible_state( undefined, "com_filecabinetblackclosed_dam", 20, undefined, undefined, "splash" ); + destructible_fx( "tag_drawer_upper", "props/filecabinet_des", true, "splash" ); // coin drop + destructible_sound( "exp_filecabinet" ); // coin drop sounds + destructible_physics( "tag_drawer_upper", ( 50, -10, 5 ) ); // coin drop sounds + destructible_state( undefined, "com_filecabinetblackclosed_des", undefined, undefined, undefined, undefined, undefined, false ); + + // front door + destructible_part( "tag_drawer_upper", "com_filecabinetblackclosed_drawer", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_trashbin_01( destructibleType ) +{ + //--------------------------------------------------------------------- + // trashbin01 toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_sound( "exp_trashcan_sweet" ); + destructible_explode( 1300, 1351, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "com_trashbin01_dmg", undefined, undefined, undefined, undefined, undefined, false ); + + destructible_part( "tag_fx", "com_trashbin01_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_trashbin_02( destructibleType ) +{ + //--------------------------------------------------------------------- + // trashbin02 toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_sound( "exp_trashcan_sweet" ); + destructible_explode( 600, 800, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "com_trashbin02_dmg", undefined, undefined, undefined, undefined, undefined, false ); + + destructible_part( "tag_fx", "com_trashbin02_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_recyclebin_01( destructibleType ) +{ + //--------------------------------------------------------------------- + // recyclebin toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_sound( "exp_trashcan_sweet" ); + destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "com_recyclebin01_dmg", undefined, undefined, undefined, undefined, undefined, false ); + + + destructible_part( "tag_fx", "com_recyclebin01_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_trashcan_metal_closed( destructibleType ) +{ + //--------------------------------------------------------------------- + // trashcan_metal_closed + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_sound( "exp_trashcan_sweet" ); + destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "com_trashcan_metal_with_trash", undefined, undefined, undefined, undefined, undefined, false ); + + destructible_part( "tag_fx", "com_trashcan_metalLID", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +toy_water_collector( destructibleType ) +{ + //--------------------------------------------------------------------- + // utility_water_collector - big blue odd shaped water barrels + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 220, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "explosions/water_collector_explosion" ); + destructible_sound( "water_collector_splash" ); + destructible_explode( 500, 800, 32, 32, 1, 10, undefined, 32 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue damage, originoffset + destructible_state( undefined, "utility_water_collector_base_dest", undefined, undefined, "no_melee", undefined, undefined, false ); + + destructible_part( "tag_lid", undefined, 220, undefined, undefined, "no_melee", 1.0 ); + destructible_state( undefined ); +} + +toy_foliage_tree_oak_1( destructibleType ) +{ + //--------------------------------------------------------------------- + // foliage_tree_oak_1 destructible tree (splash damage only) + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "splash" ); + destructible_fx( "tag_fx", "explosions/tree_trunk_explosion_oak_1", true, "splash" ); + destructible_sound( "large_oak_tree_impact" ); + destructible_sound( "large_oak_tree_fall" ); + //destructible_fx( "tag_fx", "explosions/tree_trunk_explosion_oak_1", true, damage_not( "splash" ) ); + destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "foliage_tree_oak_1_destroyed_trunk", undefined, undefined, undefined, undefined, undefined, false ); + +} + + +toy_usa_gas_station_trash_bin_01( destructibleType ) +{ + //--------------------------------------------------------------------- + // usa_gas_station_trash_bin_01 toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "usa_gas_station_trash_bin_01_base", undefined, undefined, undefined, undefined, undefined, false ); + + destructible_part( "tag_fx", "usa_gas_station_trash_bin_01_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + +toy_usa_gas_station_trash_bin_02( destructibleType ) +{ + //--------------------------------------------------------------------- + // usa_gas_station_trash_bin_02 toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 120, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx_high", "props/garbage_spew_des", true, "splash" ); + destructible_fx( "tag_fx_high", "props/garbage_spew", true, damage_not( "splash" ) ); + destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + + destructible_state( undefined, "usa_gas_station_trash_bin_02_base", undefined, undefined, undefined, undefined, undefined, false ); + + + destructible_part( "tag_fx_high", "usa_gas_station_trash_bin_02_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + +} + + +toy_light_ceiling_round( destructibleType ) +{ + //--------------------------------------------------------------------- + // Ceiling round light + //--------------------------------------------------------------------- + //println( "Ceiling light round being destroyed�" ); + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_lights_out( 16 ); + destructible_fx( "tag_fx", "misc/light_blowout_runner" ); + destructible_state( undefined, "com_light_ceiling_round_off", undefined, undefined, "no_melee" ); +} + +toy_light_ceiling_fluorescent( destructibleType ) +{ + //--------------------------------------------------------------------- + // Ceiling fluorescent light + //--------------------------------------------------------------------- + println( "Ceiling light fluorescent being destroyed�" ); + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_fx( "tag_fx", "misc/light_fluorescent_blowout_runner" ); + destructible_fx( "tag_swing_fx", "misc/light_blowout_swinging_runner" ); + destructible_lights_out( 16 ); + destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_anim( get_precached_anim( "light_fluorescent_swing" ), #animtree, "setanimknob", undefined, 0, "light_fluorescent_swing" ); + destructible_sound( "fluorescent_light_fall", undefined, 0 ); + destructible_sound( "fluorescent_light_bulb", undefined, 0 ); + //destructible_sound( "fluorescent_light_spark", undefined, 0 ); + destructible_anim( get_precached_anim( "light_fluorescent_swing_02" ), #animtree, "setanimknob", undefined, 1, "light_fluorescent_swing_02" ); + destructible_sound( "fluorescent_light_fall", undefined, 1 ); + destructible_sound( "fluorescent_light_bulb", undefined, 1 ); + //destructible_sound( "fluorescent_light_spark", undefined, 1 ); + destructible_anim( get_precached_anim( "light_fluorescent_null" ), #animtree, "setanimknob", undefined, 2, "light_fluorescent_null" ); + destructible_state( undefined, "me_lightfluohang_double_destroyed", undefined, undefined, "no_melee" ); + + +} + +toy_light_ceiling_fluorescent_spotlight( destructibleType ) +{ + //--------------------------------------------------------------------- + // Ceiling fluorescent light + //--------------------------------------------------------------------- + println( "Ceiling light fluorescent being destroyed�" ); + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_sound( "fluorescent_light_bulb" ); + //destructible_sound( "fluorescent_light_spark" ); //played in effect + destructible_fx( "tag_fx", "misc/light_fluorescent_blowout_runner" ); + destructible_fx( "tag_swing_fx", "misc/light_blowout_swinging_runner" ); + destructible_lights_out( 16 ); + destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_anim( get_precached_anim( "light_fluorescent_swing" ), #animtree, "setanimknob", undefined, 0, "light_fluorescent_swing" ); + destructible_sound( "fluorescent_light_fall", undefined, 0 ); + destructible_sound( "fluorescent_light_bulb", undefined, 0 ); + //destructible_sound( "fluorescent_light_spark", undefined, 0 ); + destructible_spotlight( "tag_swing_r_far" ); + destructible_sound( "fluorescent_light_fall" ); + destructible_state( undefined, "me_lightfluohang_double_destroyed", undefined, undefined, "no_melee" ); +} + +toy_light_ceiling_fluorescent_single( destructibleType ) +{ + //--------------------------------------------------------------------- + // Ceiling fluorescent light + //--------------------------------------------------------------------- + println( "Ceiling light fluorescent single being destroyed�" ); + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_fx( "tag_fx", "misc/light_fluorescent_single_blowout_runner" ); + destructible_fx( "tag_swing_center_fx", "misc/light_blowout_swinging_runner" ); + destructible_fx( "tag_swing_center_fx_far", "misc/light_blowout_swinging_runner" ); + destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_anim( get_precached_anim( "light_fluorescent_single_swing" ), #animtree, "setanimknob", undefined, 0, "light_fluorescent_single_swing" ); + destructible_sound( "fluorescent_light_fall", undefined, 0 ); + destructible_sound( "fluorescent_light_bulb", undefined, 0 ); + //destructible_sound( "fluorescent_light_spark", undefined, 0 ); + destructible_anim( get_precached_anim( "light_fluorescent_single_swing_02" ), #animtree, "setanimknob", undefined, 1, "light_fluorescent_single_swing_02" ); + destructible_sound( "fluorescent_light_hinge", undefined, 1 ); + destructible_sound( "fluorescent_light_bulb", undefined, 1 ); + //destructible_sound( "fluorescent_light_spark", undefined, 1 ); + destructible_anim( get_precached_anim( "light_fluorescent_single_swing_03" ), #animtree, "setanimknob", undefined, 2, "light_fluorescent_single_swing_03" ); + destructible_sound( "fluorescent_light_fall", undefined, 2 ); + destructible_sound( "fluorescent_light_bulb", undefined, 2 ); + //destructible_sound( "fluorescent_light_spark", undefined, 2 ); + destructible_anim( get_precached_anim( "light_fluorescent_single_null" ), #animtree, "setanimknob", undefined, 3, "light_fluorescent_single_null" ); + destructible_state( undefined, "me_lightfluohang_single_destroyed", undefined, undefined, "no_melee" ); +} + +toy_light_ceiling_fluorescent_single_spotlight( destructibleType ) +{ + //--------------------------------------------------------------------- + // Ceiling fluorescent light + //--------------------------------------------------------------------- + println( "Ceiling light fluorescent single being destroyed�" ); + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_lights_out( 16 ); + destructible_sound( "fluorescent_light_bulb" ); + //destructible_sound( "fluorescent_light_spark" ); //played in effect + destructible_fx( "tag_fx", "misc/light_fluorescent_single_blowout_runner" ); + destructible_fx( "tag_swing_center_fx", "misc/light_blowout_swinging_runner" ); + destructible_fx( "tag_swing_center_fx_far", "misc/light_blowout_swinging_runner" ); + destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_anim( get_precached_anim( "light_fluorescent_single_swing_02" ), #animtree, "setanimknob", undefined, undefined, "light_fluorescent_single_swing_02" ); + destructible_sound( "fluorescent_light_fall" ); + destructible_spotlight( "tag_swing_center_fx_far" ); + destructible_state( undefined, "me_lightfluohang_single_destroyed", undefined, undefined, "no_melee" ); +} + +toy_bookstore_bookstand4_books( destructibleType ) +{ + //--------------------------------------------------------------------- + // bookstore_bookstand4_books + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 200, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 7 ); + destructible_fx( "tag_fx", "props/bookshelf4_dmg", true, damage_not( "splash" ) ); + //destructible_sound( "copier_exp" ); + destructible_state( undefined, "bookstore_bookstand4", 100, undefined, undefined, "splash" ); + destructible_fx( "tag_fx", "props/bookshelf4_des", true, "splash" ); + destructible_explode( 2000, 3800, 32, 32, 1, 5, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continueDamage, originOffset, earthQuakeScale, earthQuakeRadius + destructible_state( undefined, "bookstore_bookstand4_null", undefined, undefined, undefined, undefined, undefined, false ); +} + +toy_locker_double( destructibleType ) +{ + //--------------------------------------------------------------------- + // Locker Double + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + + destructible_anim( get_precached_anim( "locker_broken_both_doors_1" ), #animtree, "setanimknob", undefined, 0, "locker_broken_both_doors_1" ); + destructible_fx( "tag_fx", "props/locker_double_des_02_right", undefined, undefined, 0 ); + destructible_sound( "lockers_fast", undefined, 0 ); + + destructible_anim( get_precached_anim( "locker_broken_both_doors_2" ), #animtree, "setanimknob", undefined, 1, "locker_broken_both_doors_2" ); + destructible_fx( "tag_fx", "props/locker_double_des_01_left", undefined, undefined, 1 ); + destructible_sound( "lockers_fast", undefined, 1 ); + + destructible_anim( get_precached_anim( "locker_broken_both_doors_4" ), #animtree, "setanimknob", undefined, 2, "locker_broken_both_doors_4" ); + destructible_fx( "tag_fx", "props/locker_double_des_03_both", undefined, undefined, 2 ); + destructible_sound( "lockers_double", undefined, 2 ); + + destructible_anim( get_precached_anim( "locker_broken_door1_fast" ), #animtree, "setanimknob", undefined, 3, "locker_broken_door1_fast" ); + destructible_fx( "tag_fx", "props/locker_double_des_01_left", undefined, undefined, 3 ); + destructible_sound( "lockers_fast", undefined, 3 ); + + destructible_anim( get_precached_anim( "locker_broken_door2_fast" ), #animtree, "setanimknob", undefined, 4, "locker_broken_door2_fast" ); + destructible_fx( "tag_fx", "props/locker_double_des_02_right", undefined, undefined, 4 ); + destructible_sound( "lockers_fast", undefined, 4 ); + + destructible_anim( get_precached_anim( "locker_broken_both_doors_3" ), #animtree, "setanimknob", undefined, 5, "locker_broken_both_doors_3" ); + destructible_fx( "tag_fx", "misc/no_effect", undefined, undefined, 5 ); + destructible_sound( "lockers_minor", undefined, 5 ); + + destructible_anim( get_precached_anim( "locker_broken_door1_slow" ), #animtree, "setanimknob", undefined, 6, "locker_broken_door1_slow" ); + destructible_fx( "tag_fx", "misc/no_effect", undefined, undefined, 6 ); + destructible_sound( "lockers_minor", undefined, 6 ); + + destructible_anim( get_precached_anim( "locker_broken_door2_slow" ), #animtree, "setanimknob", undefined, 7, "locker_broken_door2_slow" ); + destructible_fx( "tag_fx", "misc/no_effect", undefined, undefined, 7 ); + destructible_sound( "lockers_minor", undefined, 7 ); + + destructible_state( undefined, "com_locker_double_destroyed", undefined, undefined, "no_melee" ); +} + + +toy_chicken( version ) +{ + //--------------------------------------------------------------------- + // Chicken + //--------------------------------------------------------------------- + destructible_create( "toy_chicken" + version, "tag_origin", 0, undefined, 32 ); + destructible_anim( get_precached_anim( "chicken_cage_loop_01" ), #animtree, "setanimknob", undefined, 0, "chicken_cage_loop_01", 1.6 ); + destructible_anim( get_precached_anim( "chicken_cage_loop_02" ), #animtree, "setanimknob", undefined, 1, "chicken_cage_loop_02", 1.6 ); + destructible_loopsound( "animal_chicken_idle_loop" ); + destructible_state( "tag_origin", "chicken" + version, 25 ); + destructible_fx( "tag_origin", "props/chicken_exp" + version ); + destructible_anim( get_precached_anim( "chicken_cage_death" ), #animtree, "setanimknob", undefined, 0, "chicken_cage_death" ); + destructible_anim( get_precached_anim( "chicken_cage_death_02" ), #animtree, "setanimknob", undefined, 1, "chicken_cage_death_02" ); + destructible_sound( "animal_chicken_death" ); + destructible_state( undefined, "chicken" + version, undefined, undefined, "no_melee" ); +} + + +vehicle_bus_destructible() +{ + //--------------------------------------------------------------------- + // Bus + //--------------------------------------------------------------------- + destructible_create( "vehicle_bus_destructible" ); + // Glass ( Front Left ) + tag = "tag_window_front_left"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Front Right ) + tag = "tag_window_front_right"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Driver Side ) + tag = "tag_window_driver"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Back of bus ) + tag = "tag_window_back"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Right Side ) + tag = "tag_window_side_1"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Right Side ) + tag = "tag_window_side_2"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Right Side ) + tag = "tag_window_side_3"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Right Side ) + tag = "tag_window_side_4"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Right Side ) + tag = "tag_window_side_5"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_6"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_7"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_8"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_9"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_10"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + + // Glass ( Left Side ) + tag = "tag_window_side_11"; + destructible_part( tag, undefined, 99, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 200, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + +} + +vehicle_80s_sedan1( color ) +{ + //--------------------------------------------------------------------- + // 80's Sedan + //--------------------------------------------------------------------- + destructible_create( "vehicle_80s_sedan1_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_80s_sedan1_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_80s_sedan1_" + color + "_hood", undefined, undefined, undefined, undefined, 1.0, 2.5 ); + //Trunk + tag = "tag_trunk"; + destructible_part( tag, "vehicle_80s_sedan1_" + color + "_trunk", undefined, undefined, undefined, undefined, 1.0 ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_80s_sedan1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_80s_sedan1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_left_back", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_80s_sedan1_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_back", "vehicle_80s_sedan1_" + color + "_door_RB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front", "vehicle_80s_sedan1_" + color + "_bumper_F", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_bumper_back", "vehicle_80s_sedan1_" + color + "_bumper_B", undefined, undefined, undefined, undefined, undefined, 1.0 ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_80s_sedan1_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_80s_sedan1_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_80s_hatch1( color ) +{ + //--------------------------------------------------------------------- + // 80's hatchback + //--------------------------------------------------------------------- + destructible_create( "vehicle_80s_hatch1_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_80s_hatch1_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_80s_hatch1_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_80s_hatch1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_80s_hatch1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_80s_hatch1_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 10, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front" ); + destructible_part( "tag_bumper_back" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_80s_hatch1_" + color + "_mirror_L", 40 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_80s_hatch1_" + color + "_mirror_R", 40 ); + destructible_physics(); +} + +vehicle_80s_hatch2( color ) +{ + //--------------------------------------------------------------------- + // 80's hatchback 2 + //--------------------------------------------------------------------- + destructible_create( "vehicle_80s_hatch2_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_80s_hatch2_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_80s_hatch2_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_80s_hatch2_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_80s_hatch2_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_80s_hatch2_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front" ); + destructible_part( "tag_bumper_back" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_80s_hatch2_" + color + "_mirror_L", 40 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_80s_hatch2_" + color + "_mirror_R", 40 ); + destructible_physics(); +} + +vehicle_80s_wagon1( color ) +{ + //--------------------------------------------------------------------- + // 80's wagon + //--------------------------------------------------------------------- + destructible_create( "vehicle_80s_wagon1_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_80s_wagon1_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_80s_wagon1_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_80s_wagon1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_80s_wagon1_" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_left_back", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_right_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_door_right_back", "vehicle_80s_wagon1_" + color + "_door_RB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back2"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back2_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back2"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back2_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front", "vehicle_80s_wagon1_" + color + "_bumper_F", undefined, undefined, undefined, undefined, 1.0, 0.7 ); + destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, undefined, 0.6 ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_80s_wagon1_" + color + "_mirror_L", 40 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_80s_wagon1_" + color + "_mirror_R", 40 ); + destructible_physics(); +} + +vehicle_small_hatch( color ) +{ + //--------------------------------------------------------------------- + // small hatch + //--------------------------------------------------------------------- + destructible_create( "vehicle_small_hatch_" + color, "tag_body", 250, undefined, 32 ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32 ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32 ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_small_hatch_" + color + "_destroyed", undefined, 32 ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_small_hatch_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_small_hatch_" + color + "_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_small_hatch_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, 0.5 ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_small_hatch_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_small_hatch_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_small_hatch_instant( color ) +{ + //--------------------------------------------------------------------- + // small hatch + //--------------------------------------------------------------------- + destructible_create( "vehicle_small_hatch_instant_" + color, "tag_body", 250, undefined, 32 ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + /*destructible_state( undefined, undefined, 200, undefined, 32 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32 ); + destructible_loopsound( "fire_vehicle_med" );*/ + destructible_state( undefined, undefined, 400, undefined, 32 ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_small_hatch_" + color + "_destroyed", undefined, 32 ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_small_hatch_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_small_hatch_" + color + "_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_small_hatch_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, 0.5 ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_small_hatch_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_small_hatch_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + + +vehicle_pickup( destructibleType ) +{ + //--------------------------------------------------------------------- + // White Pickup Truck + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 300, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_pickup_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_pickup_hood", 800, undefined, undefined, undefined, 1.0, 2.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_pickup_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_pickup_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Left ) + tag = "tag_light_left_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Tail Light ( Right ) + tag = "tag_light_right_back"; + destructible_part( tag, undefined, 20 ); + destructible_fx( tag, "props/car_glass_brakelight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Bumpers + destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, undefined, 1.0 ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_pickup_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_pickup_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_hummer( destructibleType ) +{ + //--------------------------------------------------------------------- + // Hummer + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 400, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_deathfx", "explosions/vehicle_explosion_hummer", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_hummer_destroyed", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); +} + +vehicle_nx_hummer( destructibleType ) +{ + //--------------------------------------------------------------------- + // Hummer + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 200, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 150, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_fx( "tag_deathfx", "explosions/vehicle_explosion_hummer", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_hummer_destroyed", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); +} + +vehicle_bm21( destructibleType, destroyedModel ) +{ + //--------------------------------------------------------------------- + // BM21 + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 300, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_deathfx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, destroyedModel, undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); +} + +vehicle_moving_truck( destructibleType ) +{ + //--------------------------------------------------------------------- + // White Moving Truck + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 300, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/vehicle_explosion_medium", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_moving_truck_dst", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Bumpers + //destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0, 1.0 ); + //destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, undefined, 1.0 ); +} + +vehicle_luxurysedan( color ) +{ + //--------------------------------------------------------------------- + // Luxury Sedan + //--------------------------------------------------------------------- + destructible_create( "vehicle_luxurysedan_2008" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_car_alarm(); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_luxurysedan_2008" + color + "_destroy", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_luxurysedan_2008" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 2.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_luxurysedan_2008" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "left_wheel_02_jnt", "vehicle_luxurysedan_2008" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_01_jnt", "vehicle_luxurysedan_2008" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_02_jnt", "vehicle_luxurysedan_2008" + color + "_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + // Doors + destructible_part( "tag_door_left_front", "vehicle_luxurysedan_2008" + color + "_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_luxurysedan_2008" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_back", "vehicle_luxurysedan_2008" + color + "_door_LB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_back", "vehicle_luxurysedan_2008" + color + "_door_RB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_luxurysedan_2008" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_luxurysedan_2008" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + + +vehicle_mig29_landed( destructibleType ) +{ + //--------------------------------------------------------------------- + // Mig 29 Landed Airplane + //--------------------------------------------------------------------- + destructible_create( destructibleType, "TAG_ORIGIN", 250, undefined, 32, "splash" ); + destructible_splash_damage_scaler( 11 ); + destructible_loopfx( "TAG_front_fire", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_loopfx( "TAG_rear_fire", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "splash" ); + destructible_loopfx( "TAG_front_fire", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_loopfx( "TAG_rear_fire", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "splash" ); + destructible_loopfx( "TAG_front_fire", "smoke/airplane_damage_blacksmoke_fire", 0.4 ); + destructible_loopfx( "TAG_rear_fire", "smoke/airplane_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 512, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "splash" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "splash" ); + destructible_fx( "TAG_FX", "explosions/vehicle_explosion_mig29", false ); + destructible_sound( "car_explode" ); + destructible_explode( 8000, 10000, 512, 512, 50, 300, undefined, undefined, 0.4, 1000 ); + destructible_anim( %vehicle_mig29_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_mig29_destroy" ); + destructible_state( undefined, "vehicle_mig29_v2_dest", undefined, 32, "splash" ); + + destructible_part( "TAG_COCKPIT", "vehicle_mig29_dest_cockpit", 40, undefined, undefined, undefined, undefined, 1.0 ); +} + +vehicle_mack_truck_short( color ) +{ + //--------------------------------------------------------------------- + // Mack Truck + //--------------------------------------------------------------------- + destructible_create( "vehicle_mack_truck_short_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/mack_truck_damage_blacksmoke_fire", 0.4 ); + destructible_loopfx( "tag_gastank", "smoke/motorcycle_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "mack_truck_flareup_med" ); + destructible_loopsound( "mack_truck_fire_med" ); + destructible_healthdrain( 15, 0.25, 300, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "mack_truck_fire_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_gastank", "smoke/motorcycle_damage_blacksmoke_fire", 0.4 ); + destructible_fx( "tag_cab_fire", "fire/firelp_med_pm" ); + destructible_fx( "tag_death_fx", "nx/explosions/nx_propane_large_exp", false ); + destructible_sound( "mack_truck_explode" ); + destructible_loopsound( "fire_metal_large" ); + destructible_explode( 8000, 10000, 512, 512, 100, 400, undefined, undefined, 0.4, 1000 ); + //destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_mack_truck_short_" + color + "_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_mack_truck_short_" + color + "_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 8.0 ); + destructible_part( "left_wheel_02_jnt", "vehicle_mack_truck_short_" + color + "_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 81.0 ); + destructible_part( "left_wheel_03_jnt", "vehicle_mack_truck_short_" + color + "_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 8.0 ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_mack_truck_short_" + color + "_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "mack_truck_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "mack_truck_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "mack_truck_glass_break_small" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "mack_truck_glass_break_small" ); + destructible_state( undefined ); +} + +vehicle_motorcycle( number ) +{ + explode_anim = undefined; + explode_anim = get_precached_anim( "vehicle_motorcycle_destroy_" + number ); + + //--------------------------------------------------------------------- + // Motorcycle + //--------------------------------------------------------------------- + destructible_create( "vehicle_motorcycle_" + number, "body_animate_jnt", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_death_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_death_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_death_fx", "smoke/motorcycle_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 128, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 3000, 4000, 128, 150, 50, 300 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_anim( explode_anim, #animtree, "setanimknob", undefined, undefined, "vehicle_motorcycle_destroy_" + number ); + destructible_state( undefined, "vehicle_motorcycle_" + number + "_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "front_wheel", "vehicle_motorcycle_01_front_wheel_d", 20, undefined, undefined, "no_melee", undefined, 1.7 ); +// destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); +// destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "rear_wheel", "vehicle_motorcycle_01_rear_wheel_d", 20, undefined, undefined, "no_melee", undefined, 1.7 ); +// destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); +// destructible_sound( "veh_tire_deflate", "bullet" ); +} + +vehicle_subcompact( color ) +{ + //--------------------------------------------------------------------- + // Modern Subcompact - shares textures with coupee and Van + //--------------------------------------------------------------------- + destructible_create( "vehicle_subcompact_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, 0, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_subcompact_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_subcompact_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_subcompact_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_back", "vehicle_subcompact_" + color + "_door_LB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_back", "vehicle_subcompact_" + color + "_door_RB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_subcompact_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_subcompact_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_van( color ) +{ + //--------------------------------------------------------------------- + // Modern van - shares textures with Subcompact and Coupe + //--------------------------------------------------------------------- + destructible_create( "vehicle_van_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_van_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Hood + tag = "tag_hood"; + destructible_part( tag, "vehicle_van_" + color + "_hood", undefined, undefined, undefined, undefined, 1.0, 2.5 ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_van_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_van_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_right_back", "vehicle_van_" + color + "_door_RB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_van_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_van_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_suburban( destructibleType, color ) +{ + //--------------------------------------------------------------------- + // Suburban + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_car_alarm(); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 300, 300, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_suburban_destroyed" + color, undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_01_jnt", "vehicle_suburban_wheel_rf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "left_wheel_02_jnt", "vehicle_suburban_wheel_rf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + // Doors + destructible_part( "tag_door_left_back", "vehicle_suburban_door_lb" + color, undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_car_alarm(); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_car_alarm(); + destructible_state( tag + "_d" ); +} + +vehicle_snowmobile( destructibleType ) +{ + //--------------------------------------------------------------------- + // Snowmobile + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/snowmobile_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 150, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( get_precached_anim( "vehicle_snowmobile_destroy_01" ), #animtree, "setanimknob", undefined, undefined, "vehicle_snowmobile_destroy_01" ); + destructible_state( undefined, "vehicle_snowmobile_destroyed", undefined, 32, "no_melee" ); + // Front Ski + tag = "right_wheel_01_jnt"; + destructible_part( tag, "vehicle_snowmobile_ski_right", 800, undefined, undefined, undefined, 1.0, 2.5 ); + // Bags + destructible_part( "TAG_BAG_CENTER", "vehicle_snowmobile_bag_center", undefined, undefined, undefined, undefined, 1.0, 2.0 ); + destructible_part( "TAG_BAG_LEFT", "vehicle_snowmobile_bag_left", undefined, undefined, undefined, undefined, 1.0, 2.0 ); + destructible_part( "TAG_BAG_RIGHT", "vehicle_snowmobile_bag_right", undefined, undefined, undefined, undefined, 1.0, 2.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); +} + +destructible_gaspump( destructibleType ) +{ + //--------------------------------------------------------------------- + // Gas Pump 01 + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_loopfx( "tag_death_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 150, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_death_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_death_fx", "fire/gas_pump_fire_damage", .4 ); + destructible_sound( "gaspump01_flareup_med" ); + destructible_loopsound( "gaspump01_fire_med" ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 300, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_death_fx", "fire/gas_pump_fire_damage", .4 ); + destructible_loopsound( "gaspump01_fire_med" ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_sound( "gaspump01_flareup_med" ); + destructible_loopfx( "tag_fx", "fire/gas_pump_fire_handle", 0.05 ); + destructible_anim( %gaspump01_hose, #animtree, "setanimknob", undefined, undefined, "gaspump01_hose" ); + destructible_state( undefined, undefined, 400, undefined, 5, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/gas_pump_exp", false ); + destructible_sound( "gaspump01_explode" ); + destructible_explode( 6000, 8000, 210, 300, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_state( undefined, "furniture_gaspump01_destroyed", undefined, undefined, "no_melee" ); + + // Large Front Bottom panel + destructible_part( "tag_panel_front01", "furniture_gaspump01_panel01", 80, undefined, undefined, undefined, 1.0, 1.0, undefined, 1.0 ); + destructible_physics(); + // Medium Front Middle panel + destructible_part( "tag_panel_front02", "furniture_gaspump01_panel02", 40, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_physics(); + // Small Front Top Panel + destructible_part( "tag_panel_front03", "furniture_gaspump01_panel03", 40, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_sound( "exp_gaspump_sparks" ); + destructible_fx( "tag_panel_front03", "props/electricbox4_explode" ); + destructible_physics(); + + // Large Back Bottom panel + destructible_part( "tag_panel_back01", "furniture_gaspump01_panel01", 110, undefined, undefined, undefined, 1.0, 1.0, undefined, 1.0 ); + destructible_physics(); + // Medium Back Middle panel + destructible_part( "tag_panel_back02", "furniture_gaspump01_panel02", 40, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_physics(); + // Small Back Top Panel + destructible_part( "tag_panel_back03", "furniture_gaspump01_panel03", 40, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_sound( "exp_gaspump_sparks" ); + destructible_fx( "tag_panel_back03", "props/electricbox4_explode" ); + destructible_physics(); + +} + +destructible_electrical_transformer_large( destructibleType ) +{ + //--------------------------------------------------------------------- + // Electrical transformer 01 + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 1500, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 2 ); + destructible_loopsound( "electrical_transformer_sparks" ); + destructible_loopfx( "tag_fx", "explosions/electrical_transformer_spark_runner", 0.8 ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 500, undefined, 32, "no_melee" ); + destructible_loopsound( "electrical_transformer_sparks" ); + destructible_fx( "tag_fx_junction", "explosions/generator_sparks_c", false ); + destructible_loopfx( "tag_fx_junction", "fire/electrical_transformer_blacksmoke_fire", 0.4 ); + destructible_loopfx( "tag_fx", "explosions/electrical_transformer_spark_runner", 0.8 ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 300, undefined, 32, "no_melee" ); + destructible_loopsound( "electrical_transformer_sparks" ); + destructible_loopfx( "tag_fx_junction", "fire/electrical_transformer_blacksmoke_fire", 0.4 ); + destructible_loopfx( "tag_fx", "explosions/electrical_transformer_spark_runner", 0.8 ); + destructible_loopfx( "tag_fx_valve", "explosions/generator_spark_runner", 0.6 ); + destructible_healthdrain( 12, 0.2, 210, "allies" ); + destructible_state( undefined, undefined, 500, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/electrical_transformer_explosion", false ); + destructible_sound( "electrical_transformer01_explode" ); + destructible_explode( 6000, 8000, 210, 300, 20, 300, undefined, undefined, 0.3, 500 ); + destructible_state( undefined, "com_electrical_transformer_large_des", undefined, undefined, "no_melee" ); + + // door 1 + destructible_part( "tag_door1", "com_electrical_transformer_large_dam_door1", 1500, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_sound( "electrical_transformer01_explode_detail" ); + destructible_fx( "tag_door1", "explosions/generator_explosion" ); + destructible_physics(); + + // door 2 + destructible_part( "tag_door2", "com_electrical_transformer_large_dam_door2", 150, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_physics(); + + // door 3 + destructible_part( "tag_door3", "com_electrical_transformer_large_dam_door3", 150, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_physics(); + + // door 4 + destructible_part( "tag_door4", "com_electrical_transformer_large_dam_door4", 150, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_physics(); + + // door 5 + destructible_part( "tag_door5", "com_electrical_transformer_large_dam_door5", 1500, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_sound( "electrical_transformer01_explode_detail" ); + destructible_fx( "tag_door5", "explosions/generator_explosion" ); + destructible_physics(); + + // door 6 + destructible_part( "tag_door6", "com_electrical_transformer_large_dam_door6", 150, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_physics(); + + // door 7 + destructible_part( "tag_door7", "com_electrical_transformer_large_dam_door7", 150, undefined, undefined, undefined, 0, 1.0, undefined, 1 ); + destructible_loopsound( "electrical_transformer_sparks" ); + destructible_fx( "tag_door7", "props/electricbox4_explode" ); + destructible_physics(); + +} + + +get_precached_anim( animname ) +{ + println( animname ); + assertEX( isdefined( level._destructible_preanims ) && isdefined( level._destructible_preanims[ animname ] ),"Can't find destructible anim: "+animname+" check the Build Precache Scripts and Repackage Zone boxes In launcher when you compile your map. " ); + return level._destructible_preanims[ animname ]; +} + +#using_animtree ( "vehicles" ); + +vehicle_coupe( color ) +{ + //--------------------------------------------------------------------- + // Modern coupe - shares textures with Subcompact and Van + //--------------------------------------------------------------------- + destructible_create( "vehicle_coupe_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 12, 0.2, 150, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_coupe_" + color + "_destroyed", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_coupe_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 2.3 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_coupe_" + color + "_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Spoiler (rear) + destructible_part( "tag_spoiler", "vehicle_coupe_" + color + "_spoiler", undefined, undefined, undefined, undefined, 1.0, 2.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_coupe_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_coupe_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + +} + +vehicle_uaz_winter( destructibleType ) +{ + //--------------------------------------------------------------------- + // UAZ - Winter Version + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_uaz_winter_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee", undefined, 1.0 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee", undefined, 10.0 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_uaz_winter_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_uaz_winter_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_uaz_fabric( destructibleType ) +{ + //--------------------------------------------------------------------- + // UAZ - Winter Version + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_uaz_fabric_dsr", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_uaz_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_uaz_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_uaz_hardtop( destructibleType ) +{ + //--------------------------------------------------------------------- + // UAZ - Winter Version + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_uaz_hardtop_dsr", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_uaz_wheel_RF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back2"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back2_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back2"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back2_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_uaz_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_uaz_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_uaz_open( destructibleType ) +{ + //--------------------------------------------------------------------- + // UAZ - Open Version + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_uaz_open_dsr", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_uaz_wheel_LF_d", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim", true ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back 2 ) + tag = "tag_glass_left_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back 2 ) + tag = "tag_glass_right_back_02"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_02_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_uaz_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_uaz_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_policecar( destructibleType ) +{ + //--------------------------------------------------------------------- + // Police Car + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode_police" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_policecar_lapd_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_policecar_lapd_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_policecar_lapd_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_policecar_lapd_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_policecar_lapd_wheel_LF", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_policecar_lapd_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_policecar_lapd_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_back", "vehicle_policecar_lapd_door_LB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "TAG_CENTER_GLASS_FX", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_policecar_lapd_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_policecar_lapd_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_policecar_russia( destructibleType ) +{ + //--------------------------------------------------------------------- + // Police Car + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode_police" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_policecar_russia_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_policecar_russia_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "vehicle_policecar_russia_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "vehicle_policecar_russia_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "vehicle_policecar_russia_wheel_LF", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "vehicle_policecar_russia_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "vehicle_policecar_russia_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_back", "vehicle_policecar_russia_door_LB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "TAG_CENTER_GLASS_FX", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_policecar_russia_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_policecar_russia_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +nx_vehicle_exfil_policecar( destructibleType ) +{ + //--------------------------------------------------------------------- + // Police Car + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode_police" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_exfil_policecar_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_exfil_policecar_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_exfil_policecar_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_exfil_policecar_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_exfil_policecar_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "nx_vehicle_exfil_policecar_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_exfil_policecar_door_rf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_back", "nx_vehicle_exfil_policecar_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "TAG_CENTER_GLASS_FX", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "nx_vehicle_exfil_policecar_mirror_l", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "nx_vehicle_exfil_policecar_mirror_r", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +nx_vehicle_policecar_mexico( destructibleType ) +{ + //--------------------------------------------------------------------- + // Police Car + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode_police" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_policecar_mexico_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_policecar_mexico_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_policecar_mexico_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_policecar_mexico_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_policecar_mexico_wheel_LF", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + // Doors + destructible_part( "tag_door_left_front", "nx_vehicle_policecar_mexico_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_policecar_mexico_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_back", "nx_vehicle_policecar_mexico_door_LB", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "TAG_CENTER_GLASS_FX", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "nx_vehicle_policecar_mexico_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "nx_vehicle_policecar_mexico_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +vehicle_taxi( destructibleType ) +{ + //--------------------------------------------------------------------- + // Taxi with random roof ads + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + random_dynamic_attachment( "tag_ad", "vehicle_taxi_rooftop_ad_base", "vehicle_taxi_rooftop_ad_1" ); + random_dynamic_attachment( "tag_ad", "vehicle_taxi_rooftop_ad_base", "vehicle_taxi_rooftop_ad_2" ); + random_dynamic_attachment( "tag_ad", "vehicle_taxi_rooftop_ad_base", "vehicle_taxi_rooftop_ad_3" ); + random_dynamic_attachment( "tag_ad", "vehicle_taxi_rooftop_ad_base", "vehicle_taxi_rooftop_ad_4" ); + random_dynamic_attachment( "tag_ad", "vehicle_taxi_toplight", undefined, "taxi_ad_clip" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_car_alarm(); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/small_vehicle_explosion", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "vehicle_taxi_yellow_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "vehicle_taxi_wheel_LF", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "left_wheel_02_jnt", "vehicle_taxi_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_01_jnt", "vehicle_taxi_wheel_LF", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + destructible_part( "right_wheel_02_jnt", "vehicle_taxi_wheel_LF", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_car_alarm(); + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Center Divider ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "TAG_CENTER_GLASS_FX", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Side Mirrors + destructible_part( "tag_mirror_left", "vehicle_taxi_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); + destructible_part( "tag_mirror_right", "vehicle_taxi_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 ); + destructible_physics(); +} + +nx_vehicle_lapd( destructibleType ) +{ + //--------------------------------------------------------------------- + // LAPD Car + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "nx/smoke/nx_car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "nx/explosions/nx_vehicle_explosion_small", false ); + destructible_sound( "car_explode_police" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_lapd_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_lapd_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_lapd_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_lapd_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_lapd_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + //doors + destructible_part( "tag_door_left_back", "nx_vehicle_lapd_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_front", "nx_vehicle_lapd_destroy_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_lapd_destroy_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_back", "nx_vehicle_lapd_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + +} + +nx_vehicle_sedan( destructibleType, color ) +{ + //--------------------------------------------------------------------- + // Sedan Car + //--------------------------------------------------------------------- + destructible_create( "nx_vehicle_sedan_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "nx/smoke/nx_car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "nx/explosions/nx_vehicle_explosion_small", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_sedan_" + color + "_destroy", undefined, 32, "no_melee" ); + // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_sedan_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_sedan_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_sedan_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_sedan_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + //doors + destructible_part( "tag_door_left_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined ); + destructible_part( "tag_door_right_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Front ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Front ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left Back ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_left_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right Back ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_right_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); +} + +vehicle_scooter( destructibleType ) +{ + //explode_anim = undefined; + //explode_anim = get_precached_anim( "vehicle_motorcycle_destroy_" + 1 ); + + //--------------------------------------------------------------------- + // Scooter + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 100, undefined, 32, "no_melee" ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_engine", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_engine", "smoke/scooter_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 128, "allies" ); + destructible_state( undefined, undefined, 150, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "explosions/vehicle_explosion_scooter", false ); + destructible_sound( "car_explode" ); + destructible_explode( 3000, 4000, 128, 150, 50, 300 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + //destructible_anim( explode_anim, #animtree, "setanimknob", undefined, undefined, explode_anim ); + destructible_state( undefined, "vehicle_scooter_vespa_destroyed", undefined, 32, "no_melee" ); + // Tires + //destructible_part( "front_wheel", "vehicle_motorcycle_01_front_wheel_d", 20, undefined, undefined, "no_melee", undefined, 1.7 ); +// destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); +// destructible_sound( "veh_tire_deflate", "bullet" ); + //destructible_part( "rear_wheel", "vehicle_motorcycle_01_rear_wheel_d", 20, undefined, undefined, "no_melee", undefined, 1.7 ); +// destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); +// destructible_sound( "veh_tire_deflate", "bullet" ); +} + + +nx_vehicle_micro( destructibleType, color ) +{ + //--------------------------------------------------------------------- + // micro mobile future car + //--------------------------------------------------------------------- + destructible_create( "nx_vehicle_micro_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "nx/smoke/nx_car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "nx/explosions/nx_vehicle_explosion_small", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_micro_" + color + "_destroy", undefined, 32, "no_melee" ); +/* // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + + //doors + destructible_part( "tag_door_left_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined ); + destructible_part( "tag_door_right_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +*/ + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d_01", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_front_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( tag + "_d_02", undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( undefined ); + // Glass ( Back ) + tag = "tag_glass_back"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d_01", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_back_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( tag + "_d_02", undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( undefined ); + // Glass ( Left Door ) + tag = "tag_glass_door_left"; + destructible_part( tag, undefined, 120, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d_01", undefined, 31, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_door_left_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( tag + "_d_02", undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( undefined ); + // Glass ( Right Door ) + tag = "tag_glass_door_right"; + destructible_part( tag, undefined, 120, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d_01", undefined, 31, undefined, undefined, undefined, true ); + destructible_fx( "tag_glass_door_right_fx", "props/car_glass_large" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( tag + "_d_02", undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( undefined ); + + +/* // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); +*/ +} + +nx_vehicle_civilian_suv( destructibleType, color ) +{ + //--------------------------------------------------------------------- + // micro mobile future car + //--------------------------------------------------------------------- + destructible_create( "nx_vehicle_civilian_suv_" + color, "tag_body", 250, undefined, 32, "no_melee" ); + //destructible_splash_damage_scaler( 18 ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_whitesmoke", 0.4 ); + destructible_state( undefined, undefined, 300, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "smoke/car_damage_blacksmoke", 0.4 ); + destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_hood_fx", "nx/smoke/nx_car_damage_blacksmoke_fire", 0.4 ); + destructible_sound( "fire_vehicle_flareup_med" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_healthdrain( 15, 0.25, 210, "allies" ); + destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" ); + destructible_loopsound( "fire_vehicle_med" ); + destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" ); + destructible_fx( "tag_death_fx", "nx/explosions/nx_vehicle_explosion_small", false ); + destructible_sound( "car_explode" ); + destructible_explode( 4000, 5000, 200, 250, 50, 300, undefined, undefined, 0.3, 500 ); + destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" ); + destructible_state( undefined, "nx_vehicle_civilian_suv_" + color + "_destroy", undefined, 32, "no_melee" ); +/* // Tires + destructible_part( "left_wheel_01_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "left_wheel_02_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_01_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee", undefined, 1.7 ); + destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + destructible_part( "right_wheel_02_jnt", "nx_vehicle_micro_" + color + "_destroy_wheel_lf", 20, undefined, undefined, "no_melee" ); + destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" ); + destructible_sound( "veh_tire_deflate", "bullet" ); + + //doors + destructible_part( "tag_door_left_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_left_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_door_right_front", "nx_vehicle_sedan_" + color + "_destroy_door_lf", undefined, undefined, undefined, undefined ); + destructible_part( "tag_door_right_back", "nx_vehicle_sedan_" + color + "_destroy_door_lb", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +*/ + // Glass ( Front ) + tag = "tag_glass_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back Right) + tag = "tag_glass_back_right"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Back left) + tag = "tag_glass_back_left"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left front Door ) + tag = "tag_glass_left_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right front Door ) + tag = "tag_glass_right_front"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left back Door ) + tag = "tag_glass_left_back"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right back Door ) + tag = "tag_glass_right_back"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Left back Door_02 ) + tag = "tag_glass_left_back_02"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( Right back Door_02 ) + tag = "tag_glass_right_back_02"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( tag + "_fx", "props/car_glass_med" ); + destructible_sound( "veh_glass_break_large" ); + destructible_car_alarm(); + destructible_state( undefined ); + // Glass ( center/roof ) + tag = "tag_center_glass"; + destructible_part( tag, undefined, 80, undefined, undefined, undefined, undefined, undefined, true ); + destructible_state( tag + "_d", undefined, undefined, undefined, undefined, undefined, true ); + destructible_car_alarm(); + destructible_state( undefined ); + + +/* // Head Light ( Left ) + tag = "tag_light_left_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); + // Head Light ( Right ) + tag = "tag_light_right_front"; + destructible_part( tag, undefined, 60, undefined, undefined, undefined, 0.5 ); + destructible_fx( tag, "props/car_glass_headlight" ); + destructible_sound( "veh_glass_break_small" ); + destructible_state( tag + "_d" ); +*/ +} + + +#using_animtree( "animated_props" ); + +nx_destructible_wind_turbine( destructibleType ) { + destructible_create( destructibleType, "tag_orgin", 0, undefined, 32); + destructible_anim( get_precached_anim( "wind_turbine_rotate" ), #animtree, "setanimknob", undefined, undefined, "wind_turbine_rotate" ); + destructible_state( undefined, "nx_wind_turbine_model", 360, undefined, "no_melee" ); + destructible_anim( get_precached_anim( "wind_turbine_stop" ), #animtree, "setanimknob", undefined, undefined, "wind_turbine_stop" ); + destructible_fx( "j_turbine_main_anim_jnt", "nx/destructibles/nx_wind_turbine_sparks" ); +} + +nx_jow_destructible_line6_ld300_bass(destructibleType) { + destructible_create( destructibleType, "tag_origin", 120, undefined, 32 ); + destructible_splash_damage_scaler( 1 ); + destructible_fx( "tag_fx", "test/nx_jow_line6_ld300_bass_destructible" ); + destructible_sound( "nx_amp_destruction" ); + destructible_explode( 20, 2000, 9, 9, 3, 3, undefined, 12 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "nx_jow_line6_ld300_bass_damaged_xmdl", undefined, undefined, "no_melee" ); +} + +nx_jow_destructible_mansion_globe(destructibleType) { + destructible_create( destructibleType, "tag_origin", 80, undefined, 32 ); + destructible_splash_damage_scaler( 1 ); + destructible_physics( "tag_holder", ( 10, 0, 0 ) ); + destructible_physics( "tag_globe", ( 5, 0, 0 ) ); + + destructible_sound( "nx_globe_destruction" ); + destructible_state( undefined, "nx_jow_mansion_globe_damaged_xmdl", 120, undefined, "no_melee" ); + + destructible_part("tag_holder", "nx_jow_mansion_globe_damaged_holder_xmdl", 30, undefined, undefined, undefined, undefined, 1.0 ); + destructible_part("tag_globe", "nx_jow_mansion_globe_damaged_globe_xmdl", 30, undefined, undefined, undefined, undefined, 1.0 ); +} + +nx_destructible_display_screen_01( version ) +{ + //--------------------------------------------------------------------- + // hh_display_screens_first pass + //--------------------------------------------------------------------- + destructible_create( "nx_destructible_display_screen_01" + version, "tag_origin", 50, undefined, 32 ); + destructible_splash_damage_scaler( 1.25 ); + destructible_fx( "tag_fx", "explosions/tv_flatscreen_explosion" ); + destructible_sound( "tv_shot_burst" ); + destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "nx_display_screen_01_1_d", 200, undefined, "no_melee" ); +} + +nx_toy_lunar_trash_can( destructibleType ) +{ + //--------------------------------------------------------------------- + // space waste basket toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 30, undefined, 32, "no_melee" ); + destructible_fx( "tag_fx", "nx/props/nx_lunar_trash_burst_small", true, "splash" ); + destructible_fx( "tag_fx", "nx/props/nx_lunar_trash_burst_small", true, damage_not( "splash" ) ); + destructible_sound( "exp_trashcan_sweet" ); + destructible_explode( 100, 151, 30, 1, 1, 2 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + //destructible_state( "tag_origin", "nx_lunar_trash_can_dmg", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_origin", "nx_lunar_trash_can_dmg", undefined, undefined, undefined, undefined, 1.0, 1.0 ); + destructible_part( "tag_fx", "nx_lunar_trash_can_lid", undefined, undefined, undefined, undefined, 1.0, 1.0 ); +} + +nx_toy_lunar_oxygen_tank( version ) +{ + //--------------------------------------------------------------------- + // lunar Oxygen Tanks 01 + //--------------------------------------------------------------------- + destructible_create( "nx_toy_lunar_oxygen_tank_" + version, "tag_origin", 80, undefined, 32, "no_melee" ); + destructible_healthdrain( 12, 0.2, 100, "allies" ); + destructible_loopsound( "oxygen_tank_leak_loop" ); + destructible_loopfx( "tag_cap", "distortion/oxygen_tank_leak", 0.4 ); + destructible_state( undefined, undefined, 150, undefined, undefined, "no_melee" ); + destructible_fx( "tag_fx", "nx/explosions/nx_lunar_oxygen_tank_explosion_01", false ); + destructible_sound( "oxygen_tank_explode" ); + destructible_explode( 90000, 95000, 200, 256, 75, 500, undefined, 0 ); + destructible_state( "tag_origin", "machinery_oxygen_tank01_des", undefined, undefined, "no_melee" ); + //destructible_state( undefined, "nx_lunar_exploding_object", undefined, undefined, "no_melee" ); +} + +nx_toy_lunar_door_interface( destructibleType ) +{ + //--------------------------------------------------------------------- + // space waste basket toy + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 50, undefined, 32 ); + destructible_part( "tag_fx_screen_01", undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + //destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( "tag_fx_screen_01", "nx/props/nx_monitor_explosion_small" ); + //destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); + destructible_part( "tag_fx_screen_02", undefined, 40, undefined, undefined, undefined, undefined, undefined, true ); + //destructible_state( tag + "_d", undefined, 30, undefined, undefined, undefined, true ); + destructible_fx( "tag_fx_screen_02", "nx/props/nx_monitor_explosion_small" ); + //destructible_sound( "veh_glass_break_large" ); + //destructible_car_alarm(); + destructible_state( undefined ); +} + + +// Special propane tank explodable for nx_hospital level +nx_toy_propane_tank_hospital( destructibleType ) +{ + //--------------------------------------------------------------------- + // Large Propane tank goes KaBooM + //--------------------------------------------------------------------- + + destructible_create( destructibleType, "tag_origin", 50, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 5 ); + + // Spraying gas + destructible_state( undefined, undefined, 25, undefined, 32, "no_melee" ); + destructible_loopsound( "propanetank02_gas_leak_loop" ); + destructible_loopfx( "tag_cap", "distortion/propane_cap_distortion", 0.1 ); + + // Spraying fire - start health drain + destructible_state( undefined, undefined, 25, undefined, 32, "no_melee" ); + destructible_loopfx( "tag_cap", "fire/propane_capfire_leak", 0.1 ); + destructible_sound( "propanetank02_explode" ); + destructible_loopsound( "propanetank02_fire_med" ); + destructible_healthdrain( 100, 0.4, 300, "allies" ); + + // More fire spray + destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" ); + destructible_physics( "tag_cap", ( 50, 0, 0 ) ); + destructible_loopfx( "tag_cap", "fire/propane_capfire", 0.6 ); + destructible_fx( "tag_valve", "fire/propane_valvefire_flareup" ); + destructible_physics( "tag_valve", ( 50, 0, 0 ) ); + destructible_fx( "tag_cap", "fire/propane_capfire_flareup" ); + destructible_loopfx( "tag_valve", "fire/propane_valvefire", 0.1 ); + destructible_sound( "propanetank02_flareup2_med" ); + destructible_loopsound( "propanetank02_fire_med" ); + + // Trigger main explosion + destructible_state( undefined, undefined, 100, undefined, 5, "no_melee" ); + destructible_fx( "tag_fx", "fire/propane_small_fire" ); + //destructible_fx( "tag_fx", "explosions/propane_large_exp_fireball" ); + destructible_fx( "tag_fx", "nx/explosions/nx_propane_large_exp_debri_02", false ); + destructible_sound( "gaspump01_explode" ); + destructible_loopsound( "propanetank02_fire_blown_med" ); + destructible_explode( 45000, 50000, 500, 500, 750, 750, false, 0, 0.4, 5000 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage, continue_damage, offset, quake_scale, quake_radius + + // Swap to destroyed version + destructible_state( undefined, "nx_propane_tank_large_destruct01", undefined, undefined, "no_melee" ); + + // Lower Valve + destructible_part( "tag_valve", "com_propane_tank02_valve" ); + // Top Cap + destructible_part( "tag_cap", "com_propane_tank02_cap" ); +} + +nx_toy_industrial_light_01( destructibleType ) +{ + //--------------------------------------------------------------------- + // Industrial light + //--------------------------------------------------------------------- + destructible_create( destructibleType, "tag_origin", 150, undefined, 32, "no_melee" ); + destructible_splash_damage_scaler( 15 ); + destructible_fx( "tag_fx", "nx/props/nx_industrial_light_01_destroy" ); + destructible_lights_out( 16 ); + destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage + destructible_state( undefined, "nx_fx_industrial_light_01_destroyed", undefined, undefined, "no_melee" ); +} \ No newline at end of file diff --git a/common_scripts/_destructible_types_anim_airconditioner.gsc b/common_scripts/_destructible_types_anim_airconditioner.gsc new file mode 100644 index 0000000..e3f86aa --- /dev/null +++ b/common_scripts/_destructible_types_anim_airconditioner.gsc @@ -0,0 +1,5 @@ +#using_animtree( "destructibles" ); +main() +{ + level._destructible_preanims[ "ex_airconditioner_fan" ] = %ex_airconditioner_fan; +} \ No newline at end of file diff --git a/common_scripts/_destructible_types_anim_chicken.gsc b/common_scripts/_destructible_types_anim_chicken.gsc new file mode 100644 index 0000000..64f2fd2 --- /dev/null +++ b/common_scripts/_destructible_types_anim_chicken.gsc @@ -0,0 +1,9 @@ +#using_animtree( "destructibles" ); +main() +{ + level._destructible_preanims[ "chicken_cage_loop_01" ] = %chicken_cage_loop_01; + level._destructible_preanims[ "chicken_cage_loop_02" ] = %chicken_cage_loop_02; + level._destructible_preanims[ "chicken_cage_death" ] = %chicken_cage_death; + level._destructible_preanims[ "chicken_cage_death_02" ] = %chicken_cage_death_02; + +} \ No newline at end of file diff --git a/common_scripts/_destructible_types_anim_light_fluo_single.gsc b/common_scripts/_destructible_types_anim_light_fluo_single.gsc new file mode 100644 index 0000000..9a9d7cd --- /dev/null +++ b/common_scripts/_destructible_types_anim_light_fluo_single.gsc @@ -0,0 +1,11 @@ +#using_animtree( "destructibles" ); +main() +{ + level._destructible_preanims[ "light_fluorescent_single_swing" ] = %light_fluorescent_single_swing; + level._destructible_preanims[ "light_fluorescent_single_null" ] = %light_fluorescent_single_null; + level._destructible_preanims[ "light_fluorescent_single_swing_02" ] = %light_fluorescent_single_swing_02; + level._destructible_preanims[ "light_fluorescent_single_swing_03" ] = %light_fluorescent_single_swing_03; + + level._effect[ "spotlight_fx" ] = loadfx( "misc/fluorescent_spotlight" ); + +} \ No newline at end of file diff --git a/common_scripts/_destructible_types_anim_me_fanceil1_spin.gsc b/common_scripts/_destructible_types_anim_me_fanceil1_spin.gsc new file mode 100644 index 0000000..a966969 --- /dev/null +++ b/common_scripts/_destructible_types_anim_me_fanceil1_spin.gsc @@ -0,0 +1,6 @@ +#using_animtree( "destructibles" ); +main() +{ + level._destructible_preanims[ "me_fanceil1_spin" ] = %me_fanceil1_spin; + level._destructible_preanims[ "me_fanceil1_spin_stop" ] = %me_fanceil1_spin_stop; +} \ No newline at end of file diff --git a/common_scripts/_dynamic_world.gsc b/common_scripts/_dynamic_world.gsc new file mode 100644 index 0000000..33a4f47 --- /dev/null +++ b/common_scripts/_dynamic_world.gsc @@ -0,0 +1,1548 @@ +#include common_scripts\utility; + +/*QUAKED trigger_multiple_dyn_metal_detector (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_multiple_dyn_creaky_board (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_multiple_dyn_photo_copier (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_multiple_dyn_copier_no_light (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_radius_dyn_motion_light (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) +Comments to be added.*/ + +/*QUAKED trigger_radius_dyn_motion_dlight (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) +Comments to be added.*/ + +/*QUAKED trigger_multiple_dog_bark (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +Comments to be added.*/ + +/*QUAKED trigger_radius_bird_startle (0.12 0.23 1.0) (-16 -16 -16) (16 16 16) +Comments to be added.*/ + +/*QUAKED trigger_multiple_dyn_motion_light (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_multiple_dyn_door (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Comments to be added.*/ + +/*QUAKED trigger_multiple_freefall (0.12 0.23 1.0) ? AI_AXIS AI_ALLIES AI_NEUTRAL NOTPLAYER VEHICLE TRIGGER_SPAWN TOUCH_ONCE +defaulttexture="flag" +Player free falling with animation and screaming of doom.*/ + +// Crouch Speed 5.7-6.0 +// Run Speed 8.7-9.2 +// Sprint Speed 13.0-14.0 + + +// ========================= Constants ========================== + +// Vending Machine +CONST_vending_machine_health = 400; +CONST_soda_pop_time = 0.1; // seconds +CONST_soda_count = 12; // number of soda per machine +CONST_soda_launch_force = 1000; // soda shoot out force +CONST_soda_random_factor = 0.15; // in percentage 0.2 = 20% +CONST_soda_splash_dmg_scaler = 3; // splash damage multiplier + +// Metal Detector +CONST_alarm_tolerance = 0; // number of alarm sounds before silenced, 0 disables silencing +CONST_alarm_interval = 7; // alarm interval time in seconds +CONST_alarm_interval_sp = 2; // alarm interval time in seconds for single player + +// Civilian Jet +CONST_jet_speed = 2000; // jet while landing is 130 - 160mph( 2292inch / sec - 2820inch / sec ), emergency landing is 110mph +CONST_jet_extend = 20000; // units, each jet and flyto origin will extend from each other by + +init() +{ + + //rotate fan blades in mp_highrise + array_thread( getEntArray( "com_wall_fan_blade_rotate", "targetname" ), ::fan_blade_rotate, "slow" ); + array_thread( getEntArray( "com_wall_fan_blade_rotate_fast", "targetname" ), ::fan_blade_rotate, "fast" ); + array_thread( getEntArray( "com_wall_fan_blade_rotate_hydro", "targetname" ), ::fan_blade_rotate_hydro ); + + trigger_classes = []; + trigger_classes[ "trigger_multiple_dyn_metal_detector" ] = ::metal_detector; + trigger_classes[ "trigger_multiple_dyn_creaky_board" ] = ::creaky_board; + trigger_classes[ "trigger_multiple_dyn_photo_copier" ] = ::photo_copier; + trigger_classes[ "trigger_multiple_dyn_copier_no_light" ] = ::photo_copier_no_light; + trigger_classes[ "trigger_radius_motion_light" ] = ::motion_light; + trigger_classes[ "trigger_radius_dyn_motion_dlight" ] = ::outdoor_motion_dlight; + trigger_classes[ "trigger_multiple_dog_bark" ] = ::dog_bark; + trigger_classes[ "trigger_radius_bird_startle" ] = ::bird_startle; + trigger_classes[ "trigger_multiple_dyn_motion_light" ] = ::motion_light; + trigger_classes[ "trigger_multiple_dyn_door" ] = ::trigger_door; + //trigger_classes[ "trigger_multiple_freefall" ] = ::freefall; + + player_init(); + + foreach ( classname, function in trigger_classes ) + { + triggers = getEntArray( classname, "classname" ); + array_thread( triggers, ::triggerTouchThink ); + array_thread( triggers, function ); + } + + array_thread( getEntArray( "vending_machine", "targetname" ), ::vending_machine ); + array_thread( getEntArray( "toggle", "targetname" ), ::use_toggle ); + + level thread onPlayerConnect(); + + civilian_jet = getEnt( "civilian_jet_origin", "targetname" ); + if ( isDefined( civilian_jet ) ) + civilian_jet thread civilian_jet_flyby(); +} + +onPlayerConnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread movementTracker(); + } +} + +player_init() +{ + if ( isSP() ) + { + foreach ( player in level._players ) + { + player.touchTriggers = []; + player thread movementTracker(); + } + } +} + +ai_init() +{ + /*if ( !isdefined( level.registeredAI ) ) + level.registeredAI = []; + + level.registeredAI[ level.registeredAI.size ] = self; + */ + + // self is AI + self.touchTriggers = []; + self thread movementTracker(); +} + + +// ================================================================================ // +// Civilian Jet // +// ================================================================================ // + +civilian_jet_flyby() +{ + level endon( "game_ended" ); + + self jet_init(); + + level waittill( "prematch_over" ); + + while ( 1 ) + { + self thread jet_timer(); + self waittill( "start_flyby" ); + + self thread jet_flyby(); + self waittill( "flyby_done" ); + + self jet_reset(); + } +} + + +jet_init() +{ + // move jet plane and flyto origin out of the map and hide on level load + self.jet_parts = getentarray( self.target, "targetname" ); + self.jet_flyto = getent( "civilian_jet_flyto", "targetname" ); + self.engine_fxs = getentarray( "engine_fx", "targetname" ); + self.flash_fxs = getentarray( "flash_fx", "targetname" ); + + self.jet_engine_fx = loadfx( "fire/jet_afterburner" ); + self.jet_flash_fx_red = loadfx( "misc/aircraft_light_wingtip_red" ); + self.jet_flash_fx_green = loadfx( "misc/aircraft_light_wingtip_green" ); + self.jet_flash_fx_blink = loadfx( "misc/aircraft_light_red_blink" ); + + level._civilianJetFlyBy = undefined; // priority with air supremacies + + assertex( isdefined( self.jet_parts ), "Missing cilivian jet model" ); + assertex( isdefined( self.jet_flyto ), "Missing cilivian jet flyto script_origin: civilian_jet_flyto" ); + assertex( isdefined( self.engine_fxs ), "Missing cilivian jet engine fxs script_origins: engine_fx" ); + assertex( isdefined( self.flash_fxs ), "Missing cilivian jet signal light script_origins: flash_fxs" ); + + // extending vector to place jet and flyto origin outside sky box + negative_vec = Vector_multiply( VectorNormalize( self.origin - self.jet_flyto.origin ), CONST_jet_extend ); + + // extend flyto origin + self.jet_flyto.origin -= negative_vec; + + // extend jet + self.origin += negative_vec; + foreach ( part in self.jet_parts ) + { + part.origin += negative_vec; + part.old_origin = part.origin; + part hide(); + } + + // extend jet's engine fx origins + foreach ( engine_fx in self.engine_fxs ) + engine_fx.origin += negative_vec; + + foreach ( flash_fx in self.flash_fxs ) + flash_fx.origin += negative_vec; + + // -------------- flight time and vector calculation ------------- + jet_origin = self.origin;// origin is the nose of the jet + jet_flyto_pos = self.jet_flyto.origin; + self.jet_fly_vec = jet_flyto_pos - jet_origin; + + jet_speed = CONST_jet_speed; + jet_flight_dist = abs( distance( jet_origin, jet_flyto_pos ) ); + self.jet_flight_time = jet_flight_dist / jet_speed; +} + + +jet_reset() +{ + foreach ( part in self.jet_parts ) + { + part.origin = part.old_origin; + part hide(); + } +} + + +jet_timer() +{ + level endon( "game_ended" ); + + match_timelimit = getTimeInterval(); + assert( isdefined( match_timelimit ) ); + timelimit = max( 10, match_timelimit ); + timelimit = min( timelimit, 100 ); + + if ( getdvar( "jet_flyby_timer" ) != "" ) + level._civilianJetFlyBy_timer = 5 + getdvarint( "jet_flyby_timer" ); + else + level._civilianJetFlyBy_timer = ( 0.25 + randomFloatRange( 0.3, 0.7 ) ) * 60 * timeLimit; // seconds into the match when jet flys by + + wait level._civilianJetFlyBy_timer; + + // wait till all the airborne kill streaks are done + while ( isDefined( level._airstrikeInProgress ) || isDefined( level._ac130player ) || isDefined( level._chopper ) || isDefined( level._remoteMissileInProgress ) ) + wait 0.05; + + // start flyby + self notify( "start_flyby" ); + + // blocks out all airborne kill streaks + level._civilianJetFlyBy = true; + self waittill( "flyby_done" ); + level._civilianJetFlyBy = undefined; +} + +getTimeInterval() +{ + if ( isSP() ) + return 10.0; + + if ( isDefined( game[ "status" ] ) && game[ "status" ] == "overtime" ) + return 1.0; + else + return getWatchedDvar( "timelimit" ); +} + +getWatchedDvar( dvarString ) +{ + dvarString = "scr_" + level._gameType + "_" + dvarString; + return( level._watchDvars[ dvarString ].value ); +} + + +jet_flyby() +{ + // show plane + foreach ( part in self.jet_parts ) + part show(); + + engine_fx_array = []; + flash_fx_array = []; + + foreach ( engine_fx in self.engine_fxs ) + { + engine_fx_ent = spawn( "script_model", engine_fx.origin ); + engine_fx_ent setModel( "tag_origin" ); + engine_fx_ent.angles = engine_fx.angles; + engine_fx_array [ engine_fx_array.size ] = engine_fx_ent; + } + + foreach ( flash_fx in self.flash_fxs ) + { + flash_fx_ent = spawn( "script_model", flash_fx.origin ); + flash_fx_ent setModel( "tag_origin" ); + flash_fx_ent.color = flash_fx.script_noteworthy; + flash_fx_ent.angles = flash_fx.angles; + flash_fx_array [ flash_fx_array.size ] = flash_fx_ent; + } + + assertex( isdefined( level._mapcenter ), "Calling for civilian jet flyby when level.mapcenter is not yet defined." ); + self thread jet_planeSound( self.jet_parts[ 0 ], level._mapcenter ); + + wait 0.05; + + // play engine fx on fx ents + foreach ( engine_fx_ent in engine_fx_array ) + playfxontag( self.jet_engine_fx, engine_fx_ent, "tag_origin" ); + + // play flash fx on fx ents + foreach ( flash_fx_ent in flash_fx_array ) + { + if ( isdefined( flash_fx_ent.color ) && flash_fx_ent.color == "blink" ) + playfxontag( self.jet_flash_fx_blink, flash_fx_ent, "tag_origin" ); + else if ( isdefined( flash_fx_ent.color ) && flash_fx_ent.color == "red" ) + playfxontag( self.jet_flash_fx_red, flash_fx_ent, "tag_origin" ); + else + playfxontag( self.jet_flash_fx_green, flash_fx_ent, "tag_origin" ); + } + + // move plane + foreach ( part in self.jet_parts ) + part moveTo( part.origin + self.jet_fly_vec, self.jet_flight_time ); + + // move fx ents + foreach ( engine_fx_ent in engine_fx_array ) + engine_fx_ent moveTo( engine_fx_ent.origin + self.jet_fly_vec, self.jet_flight_time ); + foreach ( flash_fx_ent in flash_fx_array ) + flash_fx_ent moveTo( flash_fx_ent.origin + self.jet_fly_vec, self.jet_flight_time ); + + wait( self.jet_flight_time + 1 ); + + // delete fxs + foreach ( engine_fx_ent in engine_fx_array ) + engine_fx_ent delete(); + foreach ( flash_fx_ent in flash_fx_array ) + flash_fx_ent delete(); + + self notify( "flyby_done" ); +} + + +jet_planeSound( plane, bombsite ) +{ + plane thread playsound_loop_on_ent( "veh_mig29_dist_loop" ); + while ( !targetisclose( plane, bombsite ) ) + wait .05; + + plane thread playsound_loop_on_ent( "veh_mig29_close_loop" ); + while ( targetisinfront( plane, bombsite ) ) + wait .05; + wait .5; + + plane thread playsound_float( "veh_mig29_sonic_boom" ); + while ( targetisclose( plane, bombsite ) ) + wait .05; + + plane notify( "stop sound" + "veh_mig29_close_loop" ); + self waittill( "flyby_done" ); + + plane notify( "stop sound" + "veh_mig29_dist_loop" ); +} + + +playsound_float( alias, origin, master ) +{ + org = spawn( "sound_emitter", ( 0, 0, 1 ) ); + org hide(); + if ( !isdefined( origin ) ) + origin = self.origin; + org.origin = origin; + if ( isdefined( master ) && master ) + org playsoundasmaster( alias ); + else + org playsound( alias ); + wait( 10.0 ); + org delete(); +} + + +playsound_loop_on_ent( alias, offset ) +{ + org = spawn( "sound_emitter", ( 0, 0, 0 ) ); + org hide(); + org endon( "death" ); + thread delete_on_death( org ); + if ( isdefined( offset ) ) + { + org.origin = self.origin + offset; + org.angles = self.angles; + org linkto( self ); + } + else + { + org.origin = self.origin; + org.angles = self.angles; + org linkto( self ); + } +// org endon ("death"); + org playloopsound( alias ); +// println ("playing loop sound ", alias," on entity at origin ", self.origin, " at ORIGIN ", org.origin); + self waittill( "stop sound" + alias ); + org stoploopsound( alias ); + org delete(); +} + +targetisinfront( other, target ) +{ + forwardvec = anglestoforward( flat_angle( other.angles ) ); + normalvec = vectorNormalize( flat_origin( target ) - other.origin ); + dot = vectordot( forwardvec, normalvec ); + + if ( dot > 0 ) + return true; + else + return false; +} + +targetisclose( other, target ) +{ + infront = targetisinfront( other, target ); + + if ( infront ) + dir = 1; + else + dir = -1; + + a = flat_origin( other.origin ); + b = a + Vector_Multiply( anglestoforward( flat_angle( other.angles ) ), ( dir * 100000 ) ); + point = pointOnSegmentNearestToPoint( a, b, target ); + dist = distance( a, point ); + + if ( dist < 3000 ) + return true; + else + return false; +} + +// ================================================================================ // +// Vending Machine // +// ================================================================================ // + +vending_machine() +{ + level endon( "game_ended" ); + self endon( "death" ); + + // self is use trigger + self SetCursorHint( "HINT_ACTIVATE" ); + + self.vm_normal = getent( self.target, "targetname" ); + assertex( isdefined( self.vm_normal ), "Vending machine use trigger is missing target to the normal vending machine script_model" ); + vm_soda_start = getent( self.vm_normal.target, "targetname" ); + assertex( isdefined( vm_soda_start ), "Vending machine normal script_model is missing target to the start-soda can script_model" ); + vm_soda_stop = getent( vm_soda_start.target, "targetname" ); + assertex( isdefined( vm_soda_start ), "Start-soda can script_model is missing target to the end-soda can script_model" ); + self.vm_launch_from = getent( vm_soda_stop.target, "targetname" ); + assertex( isdefined( self.vm_launch_from ), "End-soda can script_model is missing target to the physics launch-from script_origin" ); + self.vm_launch_to = getent( self.vm_launch_from.target, "targetname" ); + assertex( isdefined( self.vm_launch_to ), "launch-from can script_origin is missing target to the physics launch-to script_origin" ); + + if ( isdefined( self.vm_launch_to.target ) ) + self.vm_fx_loc = getent( self.vm_launch_to.target, "targetname" ); + + //assertex( isdefined( self.vm_launch_to ), "launch-to can script_origin is missing target to the fx location script_origin" ); + + self.vm_normal setCanDamage( true ); + + self.vm_normal_model = self.vm_normal.model; + self.vm_damaged_model = self.vm_normal.script_noteworthy; + self.vm_soda_model = vm_soda_start.model; + + self.vm_soda_start_pos = vm_soda_start.origin; + self.vm_soda_start_angle = vm_soda_start.angles; + self.vm_soda_stop_pos = vm_soda_stop.origin; + self.vm_soda_stop_angle = vm_soda_stop.angles; + + // precache damage model + precacheModel( self.vm_damaged_model ); + + // ride the no longer needed models + vm_soda_start delete(); + vm_soda_stop delete(); + + self.soda_array = []; + self.soda_count = CONST_soda_count; + self.soda_slot = undefined;// the soda can thats resting in the slot + self.hp = CONST_vending_machine_health; + + self thread vending_machine_damage_monitor( self.vm_normal ); + self playloopsound( "vending_machine_hum" ); + + while ( 1 ) + { + self waittill( "trigger", player ); + //level.players[0] iprintln( "used" ); + + self playsound( "vending_machine_button_press" ); + if ( !self.soda_count ) + continue; + + // drop a can, and shoot out the previous one if in slot + if ( isdefined( self.soda_slot ) ) + self soda_can_eject(); + soda_can_drop( spawn_soda() ); + wait 0.05; + } +} + +vending_machine_damage_monitor( vending_machine ) +{ + level endon( "game_ended" ); + + exp_dmg = "mod_grenade mod_projectile mod_explosive mod_grenade_splash mod_projectile_splash splash"; + sparks_fx = loadfx( "explosions/tv_explosion" ); + + while ( 1 ) + { + vending_machine waittill( "damage", damage, other, direction_vec, P, type ); + + if ( isdefined( type ) ) + { + if ( isSubStr( exp_dmg, ToLower( type ) ) ) + damage *= CONST_soda_splash_dmg_scaler; // multiply explosive dmg + + self.hp -= damage; + if ( self.hp > 0 ) + continue; + + // vending machine is now dead, button usage is disabled + self notify( "death" ); + + // disable use trigger + self.origin += ( 0, 0, 10000 ); + + if( !isdefined( self.vm_fx_loc ) ) + playfx_loc = self.vm_normal.origin + ( ( 17, -13, 52 ) - ( -20, 18, 0 ) ); + else + playfx_loc = self.vm_fx_loc.origin; + + playfx( sparks_fx, playfx_loc ); + + // when vending machine is explosively damaged, shoots out soda cans + self.vm_normal setmodel( self.vm_damaged_model ); + + while ( self.soda_count > 0 ) + { + // drop a can, and shoot out the previous one if in slot + if ( isdefined( self.soda_slot ) ) + self soda_can_eject(); + soda_can_drop( spawn_soda() ); + wait 0.05; + } + + self stoploopsound( "vending_machine_hum" ); + return; + } + } +} + +spawn_soda() +{ + soda = spawn( "script_model", self.vm_soda_start_pos ); + soda setmodel( self.vm_soda_model ); + soda.origin = self.vm_soda_start_pos; + soda.angles = self.vm_soda_start_angle; + return soda; +} + +soda_can_drop( soda ) +{ + soda MoveTo( self.vm_soda_stop_pos, CONST_soda_pop_time ); + soda playsound( "vending_machine_soda_drop" ); // soda can drop sound + wait CONST_soda_pop_time; + + self.soda_slot = soda; + self.soda_count -- ; +} + +soda_can_eject() +{ + self endon( "death" ); + + if( isdefined( self.soda_slot.ejected ) && self.soda_slot.ejected == true ) + return; + + // physics launch + force_max = CONST_soda_launch_force * ( 1 + CONST_soda_random_factor ); + force_min = force_max * 0.75 * ( 1 + CONST_soda_random_factor ); + + launch_vec = vectorNormalize( self.vm_launch_to.origin - self.vm_launch_from.origin ); + force_vec = vector_multiply( launch_vec, randomfloatrange( force_min, force_max ) ); + launch_force_vec = ( force_vec[ 0 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ), force_vec[ 1 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ), force_vec[ 2 ] * randomfloatrange( 1, 1 + CONST_soda_random_factor ) ); + + self.soda_slot PhysicsLaunchClient( self.vm_launch_from.origin, launch_force_vec ); + self.soda_slot.ejected = true; +} + +// ================================================================================ // +// Free Fall // +// ================================================================================ // + +freefall() +{ + level endon( "game_ended" ); + + freefall_weapon = "briefcase_bomb_mp"; + precacheItem( freefall_weapon ); + + while ( 1 ) + { + self waittill( "trigger_enter", player ); + + if ( !( player hasWeapon( freefall_weapon ) ) ) + { + player playsound( "freefall_death" ); + + player giveweapon( freefall_weapon ); + player setWeaponAmmoStock( freefall_weapon, 0 ); + player setWeaponAmmoClip( freefall_weapon, 0 ); + player switchToWeapon( freefall_weapon ); + } + } +} + +// ================================================================================ // +// Metal Detector // +// ================================================================================ // + +metal_detector() +{ + // self is trigger: trigger_multiple_dyn_metal_detector + + level endon( "game_ended" ); + assertex( isdefined( self.target ), "trigger_multiple_dyn_metal_detector is missing target damage trigger used for detecting entities other than players" ); + + damage_trig = getent( self.target, "targetname" ); + damage_trig EnableGrenadeTouchDamage(); + + bound_org_1 = getent( damage_trig.target, "targetname" ); + bound_org_2 = getent( bound_org_1.target, "targetname" ); + + assertex( isdefined( bound_org_1 ) && isdefined( bound_org_2 ), "Metal detector missing bound origins for claymore test" ); + + detector_1 = getent( bound_org_2.target, "targetname" ); + detector_2 = getent( detector_1.target, "targetname" ); + + assertex( isdefined( detector_1 ) && isdefined( detector_2 ), "Recompile the bsp to fix this, metal detector prefab changed." ); + + bounds = []; + bound_x_min = min( bound_org_1.origin[ 0 ], bound_org_2.origin[ 0 ] ); bounds[ 0 ] = bound_x_min; + bound_x_max = max( bound_org_1.origin[ 0 ], bound_org_2.origin[ 0 ] ); bounds[ 1 ] = bound_x_max; + bound_y_min = min( bound_org_1.origin[ 1 ], bound_org_2.origin[ 1 ] ); bounds[ 2 ] = bound_y_min; + bound_y_max = max( bound_org_1.origin[ 1 ], bound_org_2.origin[ 1 ] ); bounds[ 3 ] = bound_y_max; + bound_z_min = min( bound_org_1.origin[ 2 ], bound_org_2.origin[ 2 ] ); bounds[ 4 ] = bound_z_min; + bound_z_max = max( bound_org_1.origin[ 2 ], bound_org_2.origin[ 2 ] ); bounds[ 5 ] = bound_z_max; + + bound_org_1 delete(); + bound_org_2 delete(); + + if ( !isSP() ) + self.alarm_interval = CONST_alarm_interval; + else + self.alarm_interval = CONST_alarm_interval_sp; + + self.alarm_playing = 0; + self.alarm_annoyance = 0; + self.tolerance = CONST_alarm_tolerance; + + self thread metal_detector_dmg_monitor( damage_trig ); + self thread metal_detector_touch_monitor(); + self thread metal_detector_weapons( bounds, "weapon_claymore", "weapon_c4" ); + + light_pos1 = ( detector_1.origin[ 0 ], detector_1.origin[ 1 ], bound_z_max ); + light_pos2 = ( detector_2.origin[ 0 ], detector_2.origin[ 1 ], bound_z_max ); + + //light_pos1 = ( bound_x_min, bound_y_min, bound_z_max ); + //light_pos2 = ( bound_x_max, bound_y_max, bound_z_max ); + md_light = loadfx( "props/metal_detector_light" ); + + while ( 1 ) + { + self waittill_any( "dmg_triggered", "touch_triggered", "weapon_triggered" ); + self thread playsound_and_light( "alarm_metal_detector", md_light, light_pos1, light_pos2 ); + } +} + +playsound_and_light( sound, light, light_pos1, light_pos2 ) +{ + level endon( "game_ended" ); + + if ( !self.alarm_playing ) + { + self.alarm_playing = 1; + self thread annoyance_tracker(); + + if ( !self.alarm_annoyance ) + self playsound( sound ); + + // 1000ms red light fx + playfx( light, light_pos1 ); + playfx( light, light_pos2 ); + + wait self.alarm_interval; + self.alarm_playing = 0; + } +} + +annoyance_tracker() +{ + level endon( "game_ended" ); + + if ( !self.tolerance ) + return; + + interval = self.alarm_interval + 0.15; + if ( self.tolerance ) + self.tolerance -- ; + else + self.alarm_annoyance = 1; + + current_time = gettime();// ms + + alarm_timeout = CONST_alarm_interval; + if ( isSP() ) + alarm_timeout = CONST_alarm_interval_sp; + + self waittill_any_or_timeout( "dmg_triggered", "touch_triggered", "weapon_triggered", ( alarm_timeout + 2 ) ); + + time_delta = ( gettime() - current_time ); + if ( time_delta > ( ( alarm_timeout * 1000 ) + 1150 ) ) + { + self.alarm_annoyance = 0; + self.tolerance = CONST_alarm_tolerance; + } +} + +waittill_any_or_timeout( msg1, msg2, msg3, timer ) +{ + level endon( "game_ended" ); + + self endon( msg1 ); + self endon( msg2 ); + self endon( msg3 ); + wait timer; +} + +metal_detector_weapons( bounds, weapon_1, weapon_2 ) +{ + level endon( "game_ended" ); + while ( 1 ) + { + self waittill_weapon_placed(); + + all_grenades = getentarray( "grenade", "classname" ); + foreach ( grenade in all_grenades ) + { + if ( isdefined( grenade.model ) && ( grenade.model == weapon_1 || grenade.model == weapon_2 ) ) + { + if ( isInBound( grenade, bounds ) ) + self thread weapon_notify_loop( grenade, bounds ); + } + } + } +} + +waittill_weapon_placed() +{ + level endon( "game_ended" ); + self endon( "dmg_triggered" ); + self waittill( "touch_triggered" ); +} + +weapon_notify_loop( grenade, bounds ) +{ + grenade endon( "death" ); + + while ( isInBound( grenade, bounds ) ) + { + self notify( "weapon_triggered" ); + wait self.alarm_interval; + } +} + +isInBound( ent, bounds ) +{ + bound_x_min = bounds[ 0 ]; bound_x_max = bounds[ 1 ]; + bound_y_min = bounds[ 2 ]; bound_y_max = bounds[ 3 ]; + bound_z_min = bounds[ 4 ]; bound_z_max = bounds[ 5 ]; + + ent_x = ent.origin[ 0 ]; + ent_y = ent.origin[ 1 ]; + ent_z = ent.origin[ 2 ]; + + if ( isInBound_single( ent_x, bound_x_min, bound_x_max ) ) + { + if ( isInBound_single( ent_y, bound_y_min, bound_y_max ) ) + { + if ( isInBound_single( ent_z, bound_z_min, bound_z_max ) ) + return true; + } + } + return false; +} + +isInBound_single( var, v_min, v_max ) +{ + if ( var > v_min && var < v_max ) + return true; + return false; +} + + +metal_detector_dmg_monitor( damage_trig ) +{ + level endon( "game_ended" ); + while ( 1 ) + { + damage_trig waittill( "damage", damage, other, direction_vec, P, type ); + if ( isdefined( type ) && alarm_validate_damage( type ) ) + self notify( "dmg_triggered" ); + } +} + +metal_detector_touch_monitor() +{ + level endon( "game_ended" ); + while ( 1 ) + { + self waittill( "trigger_enter" ); + while ( anythingTouchingTrigger( self ) ) + { + self notify( "touch_triggered" ); + wait self.alarm_interval; + } + } +} + +alarm_validate_damage( damageType ) +{ + //disallowed_dmg = "mod_pistol_bullet mod_rifle_bullet bullet mod_crush mod_grenade_splash mod_projectile_splash splash unknown"; + //disallowed_dmg_array = strtok( disallowed_damage, " " ); + + allowed_dmg = "mod_melee melee mod_grenade mod_projectile mod_explosive mod_impact"; + allowed_dmg_array = strtok( allowed_dmg, " " ); + + foreach ( dmg in allowed_dmg_array ) + { + if ( ToLower( dmg ) == ToLower( damageType ) ) + return true; + } + return false; +} + + +// ================================================================================ // + + +creaky_board() +{ + level endon( "game_ended" ); + + for ( ;; ) + { + self waittill( "trigger_enter", player ); + player thread do_creak( self ); + } +} + + +do_creak( trigger ) +{ + self endon( "disconnect" ); + self endon( "death" ); + + self playSound( "step_walk_plr_woodcreak_on" ); + + for ( ;; ) + { + self waittill( "trigger_leave", leftTrigger ); + if ( trigger != leftTrigger ) + continue; + + self playSound( "step_walk_plr_woodcreak_off" ); + return; + } +} + + +motion_light() +{ + level endon( "game_ended" ); + self.moveTracker = true; + + self.lightsOn = false; + lights = getEntArray( self.target, "targetname" ); + assertEx( lights.size, "ERROR: trigger_ * _motion_light with no targets at " + self.origin ); + + precacheModel( "com_two_light_fixture_off" ); + precacheModel( "com_two_light_fixture_on" ); + + foreach ( light in lights ) + { + light.lightRigs = []; + infoNull = getEnt( light.target, "targetname" ); + if ( !isDefined( infoNull.target ) ) + continue; + + light.lightRigs = getEntArray( infoNull.target, "targetname" ); + } + + + for ( ;; ) + { + self waittill( "trigger_enter" ); + + while ( anythingTouchingTrigger( self ) ) + { + objectMoved = false; + foreach ( object in self.touchList ) + { + if ( isDefined( object.distMoved ) && object.distMoved > 5.0 ) + objectMoved = true; + } + + if ( objectMoved ) + { + if ( !self.lightsOn ) + { + self.lightsOn = true; + lights[ 0 ] playSound( "switch_auto_lights_on" ); + + foreach ( light in lights ) + { + light setLightIntensity( 1.0 ); + + if ( isdefined( light.lightRigs ) ) + { + foreach ( rig in light.lightRigs ) + rig setModel( "com_two_light_fixture_on" ); + } + } + } + self thread motion_light_timeout( lights, 10.0 ); + } + + wait( 0.05 ); + } + } +} + + +motion_light_timeout( lights, timeOut ) +{ + self notify( "motion_light_timeout" ); + self endon( "motion_light_timeout" ); + + wait( timeOut ); + + foreach ( light in lights ) + { + light setLightIntensity( 0 ); + if ( isdefined( light.lightRigs ) ) + { + foreach ( rig in light.lightRigs ) + rig setModel( "com_two_light_fixture_off" ); + } + } + + lights[ 0 ] playSound( "switch_auto_lights_off" ); + + self.lightsOn = false; +} + + +outdoor_motion_dlight() +{ + + if( !isdefined( level._outdoor_motion_light ) ) + { + level._outdoor_motion_light = loadFx( "misc/outdoor_motion_light" ); + } + + level endon( "game_ended" ); + self.moveTracker = true; + + self.lightsOn = false; + lightRig = getEnt( self.target, "targetname" ); + assertEx( lightRig.size, "ERROR: trigger_ * _motion_light with no targets at " + self.origin ); + lights = getEntArray( lightRig.target, "targetname" ); + assertEx( lights.size, "ERROR: trigger_ * _motion_light model target with no light targets at " + lightRig.origin ); + + precacheModel( "com_two_light_fixture_off" ); + precacheModel( "com_two_light_fixture_on" ); + + for ( ;; ) + { + self waittill( "trigger_enter" ); + + while ( anythingTouchingTrigger( self ) ) + { + objectMoved = false; + foreach ( object in self.touchList ) + { + if ( isDefined( object.distMoved ) && object.distMoved > 5.0 ) + objectMoved = true; + } + + if ( objectMoved ) + { + if ( !self.lightsOn ) + { + self.lightsOn = true; + lightRig playSound( "switch_auto_lights_on" ); + lightRig setModel( "com_two_light_fixture_on" ); + + foreach ( light in lights ) + { + assert( !isDefined( light.lightEnt ) ); + light.lightEnt = spawn( "script_model", light.origin ); + light.lightEnt setModel( "tag_origin" ); + playFxOnTag( level._outdoor_motion_light, light.lightEnt, "tag_origin" ); + } + } + self thread outdoor_motion_dlight_timeout( lightRig, lights, 10.0 ); + } + + wait( 0.05 ); + } + } +} + + +outdoor_motion_dlight_timeout( lightRig, lights, timeOut ) +{ + self notify( "motion_light_timeout" ); + self endon( "motion_light_timeout" ); + + wait( timeOut ); + + foreach ( light in lights ) + { + assert( isDefined( light.lightEnt ) ); + light.lightEnt delete(); + } + + lightRig playSound( "switch_auto_lights_off" ); + lightRig setModel( "com_two_light_fixture_off" ); + + self.lightsOn = false; +} + +dog_bark() +{ + level endon( "game_ended" ); + self.moveTracker = true; + + dogOrigin = getEnt( self.target, "targetname" ); + assertEx( isDefined( dogOrigin ), "ERROR: trigger_multiple_dog_bark with no target at " + self.origin ); + + for ( ;; ) + { + self waittill( "trigger_enter", player ); + + while ( anythingTouchingTrigger( self ) ) + { + maxDistMoved = 0; + foreach ( object in self.touchList ) + { + if ( isDefined( object.distMoved ) && object.distMoved > maxDistMoved ) + maxDistMoved = object.distMoved; + } + + if ( maxDistMoved > 6.0 ) + { + dogOrigin playSound( "dyn_anml_dog_bark" ); + wait( randomFloatRange( 16 / maxDistMoved, 16 / maxDistMoved + randomFloat( 1.0 ) ) ); + } + else + { + wait( 0.05 ); + } + } + } +} + + +trigger_door() +{ + doorEnt = getEnt( self.target, "targetname" ); + assertEx( isDefined( doorEnt ), "ERROR: trigger_multiple_dyn_door with no door brush at " + self.origin ); + + self.doorEnt = doorEnt; + self.doorAngle = getVectorRightAngle( vectorNormalize( self getOrigin() - doorEnt getOrigin() ) ); + doorEnt.baseYaw = doorEnt.angles[ 1 ]; + openTime = 1.0; + + for ( ;; ) + { + self waittill( "trigger_enter", player ); + + doorEnt thread doorOpen( openTime, self getDoorSide( player ) ); + + if ( anythingTouchingTrigger( self ) ) + self waittill( "trigger_empty" ); + + wait( 3.0 ); + + if ( anythingTouchingTrigger( self ) ) + self waittill( "trigger_empty" ); + + doorEnt thread doorClose( openTime ); + } +} + + +doorOpen( openTime, doorSide ) +{ + if ( doorSide ) + self rotateTo( ( 0, self.baseYaw + 90, 1 ), openTime, 0.1, 0.75 ); + else + self rotateTo( ( 0, self.baseYaw - 90, 1 ), openTime, 0.1, 0.75 ); + + self playSound( "door_generic_house_open" ); + + wait( openTime + 0.05 ); +} + + +doorClose( openTime ) +{ + self rotateTo( ( 0, self.baseYaw, 1 ), openTime ); + self playSound( "door_generic_house_close" ); + + wait( openTime + 0.05 ); +} + +getDoorSide( player ) +{ + return( vectorDot( self.doorAngle, vectornormalize( player.origin - self.doorEnt getOrigin() ) ) > 0 ); +} + + +getVectorRightAngle( vDir ) +{ + return( vDir[ 1 ], 0 - vDir[ 0 ], vDir[ 2 ] ); +} + +use_toggle() +{ + if ( self.classname != "trigger_use_touch" ) + return; + + lights = getEntArray( self.target, "targetname" ); + assert( lights.size ); + + self.lightsOn = 1; + foreach ( light in lights ) + light setLightIntensity( 1.5 * self.lightsOn ); + + + for ( ;; ) + { + self waittill( "trigger" ); + + self.lightsOn = !self.lightsOn; + if ( self.lightsOn ) + { + foreach ( light in lights ) + light setLightIntensity( 1.5 ); + + self playSound( "switch_auto_lights_on" ); + } + else + { + foreach ( light in lights ) + light setLightIntensity( 0 ); + + self playSound( "switch_auto_lights_off" ); + } + } +} + + +bird_startle() +{ +} + + +photo_copier_init( trigger ) +{ + // self is trigger + + self.copier = get_photo_copier( trigger ); + assertex( self.copier.classname == "script_model", "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); + + copy_bar = getent( self.copier.target, "targetname" ); + assertex( copy_bar.classname == "script_brushmodel", "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); + + light = getent( copy_bar.target, "targetname" ); + assertex( light.classname == "light_spot" || light.classname == "light", "Photocopier at " + trigger.origin + " doesn't have a light" ); + + light.intensity = light getlightintensity(); + light setlightintensity( 0 ); + trigger.copy_bar = copy_bar; + trigger.start_pos = copy_bar.origin; + trigger.light = light; + + angles = self.copier.angles + ( 0, 90, 0 ); + forward = anglestoforward( angles ); + trigger.end_pos = trigger.start_pos + vector_multiply( forward, 30 ); +} + +get_photo_copier( trigger ) +{ + if ( !isdefined( trigger.target ) ) + { + //cant target directly to a destructible toy, so we are grabing the nearest one, since primary light requires them to be far anyway + toys = getentarray( "destructible_toy", "targetname" ); + copier = toys[ 0 ]; + foreach ( toy in toys ) + { + if ( isdefined( toy.destructible_type ) && toy.destructible_type == "toy_copier" ) + { + if ( distance( trigger.origin, copier.origin ) > distance( trigger.origin, toy.origin ) ) + copier = toy; + } + } + assertex( distance( trigger.origin, copier.origin ) < 128, "Photocopier at " + trigger.origin + " doesn't contain a photo copier" ); + } + else + { + copier = getent( trigger.target, "targetname" ); + assertex( isdefined( copier ), "Photocopier at " + trigger.origin + " doesn't target a photo copier" ); + copier setcandamage( true ); + } + + return copier; +} + +waittill_copier_copies() +{ + self.copier endon( "FX_State_Change0" ); + self.copier endon( "death" ); + + self waittill( "trigger_enter" ); +} + +photo_copier() +{ + level endon( "game_ended" ); + photo_copier_init( self ); + + self.copier endon( "FX_State_Change0" ); // this is when copier breaks + self thread photo_copier_stop(); // monitor copier for quick stop + + for ( ;; ) + { + waittill_copier_copies(); + + self playSound( "mach_copier_run" ); + + if ( isdefined( self.copy_bar ) ) + { + reset_copier( self ); + thread photo_copier_copy_bar_goes(); + thread photo_copier_light_on(); + } + wait( 3 ); + } +} + +photo_copier_no_light() +{ + level endon( "game_ended" ); + + self.copier = get_photo_copier( self ); + assertex( self.copier.classname == "script_model", "Photocopier at " + self.origin + " doesn't target or contain a photo copier" ); + self.copier endon( "FX_State_Change0" ); // this is when copier breaks + + for ( ;; ) + { + waittill_copier_copies(); + self playSound( "mach_copier_run" ); + wait( 3 ); + } +} + +// reset light and copy bar position, interruptes previous copy in progress +reset_copier( trigger ) +{ + trigger.copy_bar moveto( trigger.start_pos, 0.2 ); // reset position + trigger.light setlightintensity( 0 ); +} + +photo_copier_copy_bar_goes() +{ + self.copier notify( "bar_goes" ); + self.copier endon( "bar_goes" ); + self.copier endon( "FX_State_Change0" ); + self.copier endon( "death" ); + + copy_bar = self.copy_bar; + wait( 2.0 ); + copy_bar moveto( self.end_pos, 1.6 ); + wait( 1.8 ); + copy_bar moveto( self.start_pos, 1.6 ); + wait( 1.6 ); // wait( 13.35 ); + + light = self.light; + timer = 0.2; + steps = timer / 0.05; + + for ( i = 0; i < steps; i++ ) + { + intensity = i * 0.05; + intensity /= timer; + intensity = 1 - ( intensity * light.intensity ); + if ( intensity > 0 ) + light setlightintensity( intensity ); + wait( 0.05 ); + } +} + +photo_copier_light_on() +{ + self.copier notify( "light_on" ); + self.copier endon( "light_on" ); + self.copier endon( "FX_State_Change0" ); + self.copier endon( "death" ); + + light = self.light; + timer = 0.2; + steps = timer / 0.05; + + for ( i = 0; i < steps; i++ ) + { + intensity = i * 0.05; + intensity /= timer; + light setlightintensity( intensity * light.intensity ); + wait( 0.05 ); + } + + photo_light_flicker( light ); +} + +// stopping light and bar move on death +photo_copier_stop() +{ + self.copier waittill( "FX_State_Change0" ); + self.copier endon( "death" ); + + reset_copier( self ); +} + +photo_light_flicker( light ) +{ + // flicker + light setlightintensity( 1 ); + wait( 0.05 ); + light setlightintensity( 0 ); + wait( 0.10 ); + light setlightintensity( 1 ); + wait( 0.05 ); + light setlightintensity( 0 ); + wait( 0.10 ); + light setlightintensity( 1 ); +} + + +fan_blade_rotate( type ) +{ + assert( isdefined( type ) ); + + speed = 0; + time = 20000; + + speed_multiplier = 1.0; + if( isdefined( self.speed ) ) + { + speed_multiplier = self.speed; + } + + if ( type == "slow" ) + speed = randomfloatrange( 100*speed_multiplier, 360*speed_multiplier ); + else if ( type == "fast" ) + speed = randomfloatrange( 720*speed_multiplier, 1000*speed_multiplier ); + else + assertmsg( "Type must be fast or slow" ); + + wait randomfloatrange( 0, 1 ); + + fan_angles = self.angles; + fan_vec = Vector_multiply( AnglesToRight( self.angles ), 100 ); // assures normalized vector is length of "1" + fan_vec = VectorNormalize( fan_vec ); + + while ( true ) + { + dot_x = abs( vectorDot( fan_vec, ( 1, 0, 0 ) ) ); + dot_y = abs( vectorDot( fan_vec, ( 0, 1, 0 ) ) ); + dot_z = abs( vectorDot( fan_vec, ( 0, 0, 1 ) ) ); + + if ( dot_x > 0.9 ) + self rotatevelocity( ( speed, 0, 0 ), time ); + else if ( dot_y > 0.9 ) + self rotatevelocity( ( speed, 0, 0 ), time ); + else if ( dot_z > 0.9 ) + self rotatevelocity( ( 0, speed, 0 ), time ); + else + self rotatevelocity( ( 0, speed, 0 ), time ); + + wait time; + } +} + +fan_blade_rotate_hydro() +{ + speed = 0; + time = 20000; + + speed_multiplier = 1.0; + if( isdefined( self.speed ) ) + { + speed_multiplier = self.speed; + } + + speed = randomfloatrange( 100*speed_multiplier, 360*speed_multiplier ); + wait randomfloatrange( 0, 1 ); + + while ( true ) + { + self rotatevelocity( ( 0, 0, speed ), time ); + wait time; + } +} + + +triggerTouchThink( enterFunc, exitFunc ) +{ + level endon( "game_ended" ); + + self.entNum = self getEntityNumber(); + + while ( true ) + { + self waittill( "trigger", player ); + + if ( !isPlayer( player ) && !isDefined( player.finished_spawning ) ) + continue; + + if ( !isAlive( player ) ) + continue; + + if ( !isDefined( player.touchTriggers[ self.entNum ] ) ) + player thread playerTouchTriggerThink( self, enterFunc, exitFunc ); + } +} + + +playerTouchTriggerThink( trigger, enterFunc, exitFunc ) +{ + if ( !isPlayer( self ) ) + self endon( "death" ); + + if ( !isSP() ) + touchName = self.guid; // generate GUID + else + touchName = "player" + gettime(); // generate GUID + + trigger.touchList[ touchName ] = self; + if ( isDefined( trigger.moveTracker ) ) + self.moveTrackers++ ; + + trigger notify( "trigger_enter", self ); + self notify( "trigger_enter", trigger ); + + if ( isDefined( enterFunc ) ) + self thread [[ enterFunc ]]( trigger ); + + self.touchTriggers[ trigger.entNum ] = trigger; + + while ( isAlive( self ) && self isTouching( trigger ) && ( isSP() || !level._gameEnded ) ) + wait( 0.05 ); + + // disconnected player will skip this code + if ( isDefined( self ) ) + { + self.touchTriggers[ trigger.entNum ] = undefined; + if ( isDefined( trigger.moveTracker ) ) + self.moveTrackers -- ; + + self notify( "trigger_leave", trigger ); + + if ( isDefined( exitFunc ) ) + self thread [[ exitFunc ]]( trigger ); + } + + if ( !isSP() && level._gameEnded ) + return; + + trigger.touchList[ touchName ] = undefined; + trigger notify( "trigger_leave", self ); + + if ( !anythingTouchingTrigger( trigger ) ) + trigger notify( "trigger_empty" ); +} + + +movementTracker() +{ + self endon( "disconnect" ); + + if ( !isPlayer( self ) ) + self endon( "death" ); + + self.moveTrackers = 0; + self.distMoved = 0; + + for ( ;; ) + { + self waittill( "trigger_enter" ); + + lastOrigin = self.origin; + while ( self.moveTrackers ) + { + self.distMoved = distance( lastOrigin, self.origin ); + lastOrigin = self.origin; + wait( 0.05 ); + } + + self.distMoved = 0; + } +} + + +anythingTouchingTrigger( trigger ) +{ + return( trigger.touchList.size ); +} + + +playerTouchingTrigger( player, trigger ) +{ + assert( isDefined( trigger.entNum ) ); + return( isDefined( player.touchTriggers[ trigger.entNum ] ) ); +} \ No newline at end of file diff --git a/common_scripts/_elevator.gsc b/common_scripts/_elevator.gsc new file mode 100644 index 0000000..790a2a5 --- /dev/null +++ b/common_scripts/_elevator.gsc @@ -0,0 +1,1285 @@ +//#include maps\mp\_utility; +#include common_scripts\utility; + +init() +{ + if ( getdvar( "scr_elevator_disabled" ) == "1" ) + return; + + // skip if no elevators in this level + elevator_groups = getentarray( "elevator_group", "targetname" ); + if ( !isdefined( elevator_groups ) ) + return; + if ( !elevator_groups.size ) + return; + + // Press and hold &&1 to call elevator. + precacheString( &"ELEVATOR_CALL_HINT" ); + // Press and hold &&1 to use elevator. + precacheString( &"ELEVATOR_USE_HINT" ); + // Press and hold &&1 to select floor. + precacheString( &"ELEVATOR_FLOOR_SELECT_HINT" ); + + precacheMenu( "elevator_floor_selector" ); + + thread elevator_update_global_dvars(); + + // find and build all elevators in the level + level._elevators = []; + + // elevator construction dvars: + // vertical units for "call button" to link near by elevator per floor + level._elevator_callbutton_link_v = elevator_get_dvar_int( "scr_elevator_callbutton_link_v", "96" ); + // horizontal units for "call button" to link near by elevator per floor + level._elevator_callbutton_link_h = elevator_get_dvar_int( "scr_elevator_callbutton_link_h", "256" ); + + build_elevators(); + position_elevators(); + elevator_call(); + + if ( !level._elevators.size ) + return; + + foreach ( elevator in level._elevators ) + { + elevator thread elevator_think(); + elevator thread elevator_sound_think(); + } + + thread elevator_debug(); +} + +elevator_update_global_dvars() +{ + while ( 1 ) + { + level._elevator_accel = elevator_get_dvar( "scr_elevator_accel", "0.2" ); // acceleration time in seconds + level._elevator_decel = elevator_get_dvar( "scr_elevator_decel", "0.2" ); // deceleration time in seconds + level._elevator_music = elevator_get_dvar_int( "scr_elevator_music", "1" ); // elevator music + level._elevator_speed = elevator_get_dvar_int( "scr_elevator_speed", "96" ); // units per second + level._elevator_innerdoorspeed = elevator_get_dvar_int( "scr_elevator_innerdoorspeed", "14" ); // inner door speed + level._elevator_outterdoorspeed = elevator_get_dvar_int( "scr_elevator_outterdoorspeed", "16" ); // outter door speed + level._elevator_return = elevator_get_dvar_int( "scr_elevator_return", "0" ); // 1: elevator returns to original floor + level._elevator_waittime = elevator_get_dvar_int( "scr_elevator_waittime", "6" ); // wait in seconds before closing door + level._elevator_aggressive_call = elevator_get_dvar_int( "scr_elevator_aggressive_call", "0" ); // calls all available elevators to floor + level._elevator_debug = elevator_get_dvar_int( "debug_elevator", "0" ); // 2: full 1: simple, 0: debug off + + // mp & sp default differences: + if ( isSP() ) + { + level._elevator_motion_detection = elevator_get_dvar_int( "scr_elevator_motion_detection", "0" );// calls elevators via motion detection + } + else + { + level._elevator_motion_detection = elevator_get_dvar_int( "scr_elevator_motion_detection", "1" );// calls elevators via motion detection + } + + wait 1; + } +} + +//==========================================================================// +// === ELEVATOR LOGIC === // +//==========================================================================// + +elevator_think() +{ + // self is elevator, self.e[] + self elevator_fsm( "[A]" ); +} + +elevator_call() +{ + foreach ( callbutton in level._elevator_callbuttons ) + callbutton thread monitor_callbutton(); +} + +floor_override( inside_trig ) +{ + self endon( "elevator_moving" ); + + self.floor_override = 0; + self.overrider = undefined; + + while ( 1 ) + { + inside_trig waittill( "trigger", player ); + self.floor_override = 1; + self.overrider = player; + break; + } + self notify( "floor_override" ); +} + +elevator_fsm( state ) +{ + /* finite state machine + + state A: rest + state B: closing doors - interrupt threaded + state C: opening doors + state D: moving elevator + ?1: if not resting at initial floor + + .-------delay-------. + | | + ?1 V + start --> [A] --inside_trig--> [B] --delay--> [D] + ^ | | + | door_trig | + | | | + | V | + '-----delay------- [C] <---delay---' + */ + + /* self is elevator, self.e[] */ + + self.eState = state; + + door_trig = self get_housing_door_trigger(); // triggers door interrupt + inside_trig = self get_housing_inside_trigger(); // presence + + while ( 1 ) + { + //state A: rest + if ( self.eState == "[A]" ) + { + // ?1: if not resting at initial floor + if ( level._elevator_return && ( self get_curFloor() != self get_initFloor() ) ) + { + self.moveto_floor = self get_initFloor(); + self thread floor_override( inside_trig ); + self waittill_or_timeout( "floor_override", level._elevator_waittime ); + + if ( self.floor_override && isdefined( self.overrider ) && isPlayer( self.overrider ) ) + self get_floor( self.overrider ); + + self.eState = "[B]"; + continue; + } + + // wait for player use trigger + while ( 1 ) + { + // if elevator already has destination but interrupted, it should continue previous order + if ( self.moveto_floor == self get_curFloor() ) + param = inside_trig discrete_waittill( "trigger" ); + else + param = "elevator_called"; // as if called onto the destination floor + + // elevator call hack + if ( isString( param ) && ( param == "elevator_called" ) && ( self.moveto_floor != self get_curFloor() ) ) + { + self.eState = "[B]"; + break; + } + + if ( isdefined( param ) && isPlayer( param ) && isAlive( param ) ) + { + isTouching_trigger = ( param istouching( inside_trig ) ); + isTouching_motion_trigger = ( isdefined( inside_trig.motion_trigger ) && param istouching( inside_trig.motion_trigger ) ); + player_isTouching_trigger = ( isTouching_trigger || isTouching_motion_trigger ); + + if ( player_isTouching_trigger ) + { + player = param; + self get_floor( player ); + + if ( self.moveto_floor == self get_curFloor() ) + continue; + + self.eState = "[B]"; + break; + } + } + } + } + + //state B: closing doors - interrupt threaded + if ( self.eState == "[B]" ) + { + self thread elevator_interrupt( door_trig ); + floor_num = self get_curFloor(); + + // call to close doors + self thread close_inner_doors(); + self thread close_outer_doors( floor_num ); + + self waittill_any( "closed_inner_doors", "interrupted" ); // Wait for inner doors to close for the safty of our valued customers. + + if ( self.elevator_interrupted ) + { + self.eState = "[C]"; + continue; + } + + self.eState = "[D]"; + continue; + } + + //state C: opening doors + if ( self.eState == "[C]" ) + { + floor_num = self get_curFloor(); + + self thread open_inner_doors(); + self thread open_outer_doors( floor_num ); + + self waittill( "opened_floor_" + floor_num + "_outer_doors" ); + + if ( self.elevator_interrupted ) + { + self.eState = "[B]"; + continue; + } + + self.eState = "[A]"; + continue; + } + + //state D: moving elevator + if ( self.eState == "[D]" ) + { + assertex( isdefined( self.moveto_floor ), "Missing destination floor number" ); + + if ( self.moveto_floor != self get_curFloor() ) + { + self thread elevator_move( self.moveto_floor ); + self waittill( "elevator_moved" ); + } + + self.eState = "[C]"; + continue; + } + } +} + +monitor_callbutton() +{ + while ( 1 ) + { + // call button used by player + player = self discrete_waittill( "trigger" ); + + call_floor = undefined; + call_elevators = []; + // fake loop, always loop only once + foreach ( idx, linked_elevators in self.e ) + { + call_floor = idx; + call_elevators = linked_elevators; + } + assert( isdefined( call_floor ) && isdefined( call_elevators ) && call_elevators.size ); + + elevator_called = 0; + + // prefilter elevators to see if any already at this floor + foreach ( elevator in call_elevators ) + { + moving = elevator elevator_floor_update(); + + // if in non-aggressive mode; this elevator is already stationary at the requested floor, we skip! + if ( !level._elevator_aggressive_call && !moving ) + { + if ( elevator get_curFloor() == call_floor ) + { + elevator_called = 1; + call_elevators = []; + break; + } + } + } + + // check all elevators to see if any can be called to this floor + foreach ( elevator in call_elevators ) + { + if ( elevator.eState == "[A]" ) + { + // call only elevators in a state of rest [A] + elevator call_elevator( call_floor ); + + elevator_called = 1; + + // aggressive call + if ( !level._elevator_aggressive_call ) + break; + } + } + + if ( elevator_called ) + self playsound( "elev_bell_ding" ); + } +} + +call_elevator( call_floor ) +{ + self.moveto_floor = call_floor; + + // call elevator via trigger hack + inside_trigger = self get_housing_inside_trigger(); + inside_trigger notify( "trigger", "elevator_called" ); + if ( level._elevator_motion_detection ) + inside_trigger.motion_trigger notify( "trigger", "elevator_called" ); +} + +// opens menu to select floors +get_floor( player ) +{ + // skips popup menu if only two floors present + bifloor = self get_outer_doorsets(); + if ( bifloor.size == 2 ) + { + curFloor = self get_curFloor(); + self.moveto_floor = !curFloor; + return; + } + + player openpopupmenu( "elevator_floor_selector" ); + player setClientDvar( "player_current_floor", self get_curFloor() ); + + while ( 1 ) + { + player waittill( "menuresponse", menu, response ); + + if ( menu == "elevator_floor_selector" ) + { + if ( response != "none" ) + self.moveto_floor = int( response ); + + break; + } + } +} + +elevator_interrupt( door_trig ) +{ + self notify( "interrupt_watch" ); + level notify( "elevator_interior_button_pressed" ); + self endon( "interrupt_watch" ); // no duplicate interrupts + self endon( "elevator_moving" ); + + self.elevator_interrupted = 0; + wait 0.5;// buffer time to have the door jitter... + door_trig waittill( "trigger", player ); + + /*while ( 1 ) + { + wait 0.5; // buffer time to have the door jitter... realisticaly, im serious! + + door_trig waittill( "trigger", player ); + if ( isdefined( player ) && isPlayer( player ) ) + break; + }*/ + + self notify( "interrupted" ); + self.elevator_interrupted = 1; + + //self elevator_fsm( "[C]" ); +} + +// returns if elevator is moving, also updates the floor number if not moving +elevator_floor_update() +{ + mainframe = self get_housing_mainframe(); + cur_pos = mainframe.origin; + + moving = 1; + foreach ( idx, eFloor in self get_outer_doorsets() ) + { + floor_pos = self.e[ "floor" + idx + "_pos" ]; + if ( cur_pos == floor_pos ) + { + self.e[ "current_floor" ] = idx; + moving = 0; + } + } + + return moving; +} + +elevator_sound_think() +{ + // self is elevator, self.e[] + // play elevator sounds on notify of behavior + + // always play musak + musak_model = self get_housing_musak_model(); + + if ( level._elevator_music && isdefined( musak_model ) ) + musak_model playloopsound( "elev_musak_loop" ); + + self thread listen_for ( "closing_inner_doors" ); + self thread listen_for ( "opening_inner_doors" ); + self thread listen_for ( "closed_inner_doors" ); + self thread listen_for ( "opened_inner_doors" ); + + foreach ( idx, eFloor in self get_outer_doorsets() ) + { + self thread listen_for ( "closing_floor_" + idx + "_outer_doors" ); + self thread listen_for ( "opening_floor_" + idx + "_outer_doors" ); + self thread listen_for ( "closed_floor_" + idx + "_outer_doors" ); + self thread listen_for ( "opened_floor_" + idx + "_outer_doors" ); + } + + self thread listen_for ( "interrupted" ); + //self thread listen_for( "interrupt_watch" ); + self thread listen_for ( "elevator_moving" ); + self thread listen_for ( "elevator_moved" ); +} + +/* +-elev_musak_loop,,music/mx_musak_stolen_elev_proc1.wav,1,1,foley,1,1,120,500,effects1,,,rlooping,,all_mp +-elev_door_open,,events/elev_door_open1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp +-elev_door_close,,events/elev_door_close1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp +-elev_door_interupt,,events/elev_door_interupt1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp +-elev_bell_ding,,events/elev_bell_ding1.wav,1,1,foley,1,1,120,2500,voice,,,,,all_mp +-elev_run_start,,events/elev_run_start01.wav,1,1,foley,1,1,120,500,voice,,,,,all_mp +-elev_run_loop,,events/elev_run_loop01.wav,1,1,foley,1,1,120,500,voice,,,rlooping,,all_mp +-elev_run_end,,events/elev_run_stop01.wav,1,1,foley,1,1,120,500,voice,,,,,all_mp +*/ + +listen_for ( msg ) +{ + while ( 1 ) + { + self waittill( msg ); + mainframe = self get_housing_mainframe(); + + if ( issubstr( msg, "closing_" ) ) + mainframe playsound( "elev_door_close" ); + + if ( issubstr( msg, "opening_" ) ) + mainframe playsound( "elev_door_open" ); + + if ( msg == "elevator_moving" ) + { + mainframe playsound( "elev_run_start" ); + mainframe playloopsound( "elev_run_loop" ); + } + + if ( msg == "interrupted" ) + mainframe playsound( "elev_door_interupt" ); + + if ( msg == "elevator_moved" ) + { + mainframe stoploopsound( "elev_run_loop" ); + mainframe playsound( "elev_run_end" ); + mainframe playsound( "elev_bell_ding" ); + } + + //if ( isdefined( level.players[0] ) && level.elevator_debug ) + // level.players[0] iprintln( "(e" + self.e[ "id" ] + ") " + msg ); + } +} + +//==========================================================================// +// === MOVEMENTS === // +//==========================================================================// + +// position elevators +position_elevators() +{ + // closing all outer doors on floors elevator isnt at + foreach ( e, elevator in level._elevators ) + { + elevator.moveto_floor = elevator get_curFloor(); + + foreach ( floor_num, outer_doorset in elevator get_outer_doorsets() ) + { + if ( elevator get_curFloor() != floor_num ) + elevator thread close_outer_doors( floor_num ); + } + } +} + +elevator_move( floor_num ) +{ + // self is elevator, self.e[] + self notify( "elevator_moving" ); + self endon( "elevator_moving" ); + + mainframe = self get_housing_mainframe(); + delta_vec = self.e[ "floor" + floor_num + "_pos" ] - mainframe.origin; + + speed = level._elevator_speed; + dist = abs( distance( self.e[ "floor" + floor_num + "_pos" ], mainframe.origin ) ); + moveTime = dist / speed; + + // move housing: + mainframe moveTo( mainframe.origin + delta_vec, moveTime, moveTime * level._elevator_accel, moveTime * level._elevator_decel ); + + // move doors and triggers and other script models + foreach ( part in self get_housing_children() ) + { + moveto_pos = part.origin + delta_vec; + + if ( !issubstr( part.classname, "trigger_" ) ) + part moveTo( moveto_pos, moveTime, moveTime * level._elevator_accel, moveTime * level._elevator_decel ); + else + part.origin = moveto_pos; + } + + // making sure elevator housing gets to destination floor + self waittill_finish_moving( mainframe, self.e[ "floor" + floor_num + "_pos" ] ); + + self notify( "elevator_moved" ); +} + +close_inner_doors() +{ + // self is elevator set + self notify( "closing_inner_doors" ); + self endon( "closing_inner_doors" ); // when interrupted + self endon( "opening_inner_doors" ); // when interrupted + + left_door = self get_housing_leftdoor(); // ent + right_door = self get_housing_rightdoor(); // ent + + mainframe = self get_housing_mainframe(); // ent + old_closed_pos = self get_housing_closedpos(); // vec + closed_pos = ( old_closed_pos[ 0 ], old_closed_pos[ 1 ], mainframe.origin[ 2 ] ); // adjusted closed position after floor change + + speed = level._elevator_innerdoorspeed; // scaler + dist = abs( distance( left_door.origin, closed_pos ) ); // scaler + moveTime = dist / speed; // scaler + + left_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + right_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + + self waittill_finish_moving( left_door, closed_pos, right_door, closed_pos ); + self notify( "closed_inner_doors" ); +} + +open_inner_doors() +{ + // self is elevator set + self notify( "opening_inner_doors" ); + self endon( "opening_inner_doors" ); // when interrupted + + left_door = self get_housing_leftdoor(); // ent + right_door = self get_housing_rightdoor(); // ent + + mainframe = self get_housing_mainframe(); // ent + old_left_opened_pos = self get_housing_leftdoor_opened_pos(); // vec + old_right_opened_pos = self get_housing_rightdoor_opened_pos(); // vec + + left_opened_pos = ( old_left_opened_pos[ 0 ], old_left_opened_pos[ 1 ], mainframe.origin[ 2 ] ); + right_opened_pos = ( old_right_opened_pos[ 0 ], old_right_opened_pos[ 1 ], mainframe.origin[ 2 ] ); + + speed = level._elevator_innerdoorspeed; // scaler + dist = abs( distance( left_opened_pos, right_opened_pos ) * 0.5 ); // scaler + moveTime = ( dist / speed ) * 0.5; // scaler + + left_door moveTo( left_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + right_door moveTo( right_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + + self waittill_finish_moving( left_door, left_opened_pos, right_door, right_opened_pos ); + self notify( "opened_inner_doors" ); +} + +// close outer elevator doors per floor +close_outer_doors( floor_num ) +{ + // self is elevator set + self notify( "closing_floor_" + floor_num + "_outer_doors" ); + self endon( "closing_floor_" + floor_num + "_outer_doors" ); // when interrupted + self endon( "opening_floor_" + floor_num + "_outer_doors" ); // when interrupted + + left_door = self get_outer_leftdoor( floor_num ); // ent + right_door = self get_outer_rightdoor( floor_num ); // ent + + left_opened_pos = self get_outer_leftdoor_openedpos( floor_num ); // vec + closed_pos = self get_outer_closedpos( floor_num ); // vec + + speed = level._elevator_outterdoorspeed; // scaler + dist = abs( distance( left_opened_pos, closed_pos ) ); // scaler + moveTime = dist / speed; // scaler + + left_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + right_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + + self waittill_finish_moving( left_door, closed_pos, right_door, closed_pos ); + self notify( "closed_floor_" + floor_num + "_outer_doors" ); +} + +// open outer elevator doors per floor +open_outer_doors( floor_num ) +{ + // self is elevator set + level notify( "elevator_doors_opening" ); + self notify( "opening_floor_" + floor_num + "_outer_doors" ); + self endon( "opening_floor_" + floor_num + "_outer_doors" ); // when interrupted + + left_door = self get_outer_leftdoor( floor_num ); // ent + right_door = self get_outer_rightdoor( floor_num ); // ent + + left_opened_pos = self get_outer_leftdoor_openedpos( floor_num ); // vec + right_opened_pos = self get_outer_rightdoor_openedpos( floor_num ); // vec + closed_pos = self get_outer_closedpos( floor_num ); // vec + + speed = level._elevator_outterdoorspeed; // scaler + dist = abs( distance( left_opened_pos, closed_pos ) ); // scaler + moveTime = ( dist / speed ) * 0.5; // scaler + + left_door moveTo( left_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + right_door moveTo( right_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 ); + + self waittill_finish_moving( left_door, left_opened_pos, right_door, right_opened_pos ); + self notify( "opened_floor_" + floor_num + "_outer_doors" ); +} + +//==========================================================================// +// === BUILD ELEVATORS === // +//==========================================================================// + +// builds elevators into 'level.elevators' struct array containing parts list +build_elevators() +{ + // triggers that enclose elevator, to distinguish between elevators + elevator_groups = getentarray( "elevator_group", "targetname" ); + assertex( isdefined( elevator_groups ) && ( elevator_groups.size ), "Radiant: Missing elevator bounding origins" ); + + elevator_housings = getentarray( "elevator_housing", "targetname" ); + assertex( isdefined( elevator_housings ) && ( elevator_housings.size >= elevator_groups.size ), "Fail! Missing the whole elevator, script_brushmodel with [targetname = elevator_housing] must be correctly placed" ); + + // sets of elevator outter door prefabs placed + elevator_doorsets = getentarray( "elevator_doorset", "targetname" ); + assertex( isdefined( elevator_doorsets ) && ( elevator_doorsets.size >= elevator_groups.size ), "Radiant: Missing elevator door(s)" ); + + // build found elevators + foreach ( elevator_bound in elevator_groups ) + { + elevator_bound_end = getent( elevator_bound.target, "targetname" ); + + min_max_xy = []; + min_max_xy[ 0 ] = min( elevator_bound.origin[ 0 ], elevator_bound_end.origin[ 0 ] );// min_x + min_max_xy[ 1 ] = max( elevator_bound.origin[ 0 ], elevator_bound_end.origin[ 0 ] );// max_x + min_max_xy[ 2 ] = min( elevator_bound.origin[ 1 ], elevator_bound_end.origin[ 1 ] );// min_y + min_max_xy[ 3 ] = max( elevator_bound.origin[ 1 ], elevator_bound_end.origin[ 1 ] );// max_y + + parts = spawnstruct(); + parts.e[ "id" ] = level._elevators.size; + + // === build elevator housing === + /* + Elevator's mainframe brushmodel + + script_brushmodel targeting: + "elevator_housing" -> left door -> right door -> door trigger -> inside trigger + + Housing is the body that moves between floors + */ + parts.e[ "housing" ] = []; + parts.e[ "housing" ][ "mainframe" ] = []; + + foreach ( elevator_housing in elevator_housings ) + { + if ( elevator_housing isInbound( min_max_xy ) ) + { + parts.e[ "housing" ][ "mainframe" ][ parts.e[ "housing" ][ "mainframe" ].size ] = elevator_housing; + + if ( elevator_housing.classname == "script_model" ) + continue; + + if ( elevator_housing.code_classname == "light" ) + continue; + + inner_leftdoor = getent( elevator_housing.target, "targetname" ); + parts.e[ "housing" ][ "left_door" ] = inner_leftdoor; + parts.e[ "housing" ][ "left_door_opened_pos" ] = inner_leftdoor.origin; + + inner_rightdoor = getent( inner_leftdoor.target, "targetname" ); + parts.e[ "housing" ][ "right_door" ] = inner_rightdoor; + parts.e[ "housing" ][ "right_door_opened_pos" ] = inner_rightdoor.origin; + + inner_door_closed_pos = ( inner_leftdoor.origin - inner_rightdoor.origin ) * ( 0.5, 0.5, 0.5 ) + inner_rightdoor.origin; + parts.e[ "housing" ][ "door_closed_pos" ] = inner_door_closed_pos; + + door_trigger = getent( inner_rightdoor.target, "targetname" ); + parts.e[ "housing" ][ "door_trigger" ] = door_trigger; + + inside_trigger = getent( door_trigger.target, "targetname" ); + parts.e[ "housing" ][ "inside_trigger" ] = inside_trigger; + inside_trigger make_discrete_trigger(); + + // for motion triggers + inside_trigger.motion_trigger = spawn( "trigger_radius", elevator_housing.origin, 0, 64, 128 ); + assert( isdefined( inside_trigger.motion_trigger ) ); + } + } + assert( isdefined( parts.e[ "housing" ] ) ); + + // === build elevator outer doorsets === + /* + Elevator's outer door sets ( per floor ) are chained together from a script_origin + targeting to the left door, then left door targets to right door + + Outer door sets are bodies that only moves to open/close + */ + parts.e[ "outer_doorset" ] = []; + foreach ( elevator_doorset in elevator_doorsets ) + { + if ( elevator_doorset isInbound( min_max_xy ) ) + { + + // closed for lighting is for compiling lighting in the closed position rather than the open position. + door_starts_closed = isdefined( elevator_doorset.script_noteworthy ) && elevator_doorset.script_noteworthy == "closed_for_lighting"; + + door_set_id = parts.e[ "outer_doorset" ].size; + + parts.e[ "outer_doorset" ][ door_set_id ] = []; + parts.e[ "outer_doorset" ][ door_set_id ][ "door_closed_pos" ] = elevator_doorset.origin; + + leftdoor = getent( elevator_doorset.target, "targetname" ); + parts.e[ "outer_doorset" ][ door_set_id ][ "left_door" ] = leftdoor; + parts.e[ "outer_doorset" ][ door_set_id ][ "left_door_opened_pos" ] = leftdoor.origin; + + rightdoor = getent( leftdoor.target, "targetname" ); + parts.e[ "outer_doorset" ][ door_set_id ][ "right_door" ] = rightdoor; + parts.e[ "outer_doorset" ][ door_set_id ][ "right_door_opened_pos" ] = rightdoor.origin; + + //put them back into the would be positions + if( door_starts_closed ) + { + left_door_vec = elevator_doorset.origin - leftdoor.origin; + elevator_doorset.origin = leftdoor.origin; + leftdoor.origin += left_door_vec; + rightdoor.origin -= left_door_vec; + parts.e[ "outer_doorset" ][ door_set_id ][ "door_closed_pos" ] = elevator_doorset.origin; + parts.e[ "outer_doorset" ][ door_set_id ][ "left_door_opened_pos" ] = leftdoor.origin; + parts.e[ "outer_doorset" ][ door_set_id ][ "right_door_opened_pos" ] = rightdoor.origin; + } + } + } + assert( isdefined( parts.e[ "outer_doorset" ] ) ); + + // bubble sort floors + for ( i = 0; i < parts.e[ "outer_doorset" ].size - 1; i++ ) + { + for ( j = 0; j < parts.e[ "outer_doorset" ].size - 1 - i; j++ ) + { + if ( parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ][ 2 ] < parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ][ 2 ] ) + { + //swap j-1 with j + temp_left_door = parts.e[ "outer_doorset" ][ j ][ "left_door" ]; + temp_left_door_opened_pos = parts.e[ "outer_doorset" ][ j ][ "left_door_opened_pos" ]; + temp_right_door = parts.e[ "outer_doorset" ][ j ][ "right_door" ]; + temp_right_door_opened_pos = parts.e[ "outer_doorset" ][ j ][ "right_door_opened_pos" ]; + temp_closed_pos = parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ]; + + parts.e[ "outer_doorset" ][ j ][ "left_door" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "left_door" ]; + parts.e[ "outer_doorset" ][ j ][ "left_door_opened_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "left_door_opened_pos" ]; + parts.e[ "outer_doorset" ][ j ][ "right_door" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "right_door" ]; + parts.e[ "outer_doorset" ][ j ][ "right_door_opened_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "right_door_opened_pos" ]; + parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ]; + + parts.e[ "outer_doorset" ][ j + 1 ][ "left_door" ] = temp_left_door; + parts.e[ "outer_doorset" ][ j + 1 ][ "left_door_opened_pos" ] = temp_left_door_opened_pos; + parts.e[ "outer_doorset" ][ j + 1 ][ "right_door" ] = temp_right_door; + parts.e[ "outer_doorset" ][ j + 1 ][ "right_door_opened_pos" ] = temp_right_door_opened_pos; + parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ] = temp_closed_pos; + } + } + } + + // === build elevator floor pos === + floor_pos = []; + foreach ( i, doorset in parts.e[ "outer_doorset" ] ) + { + mainframe = parts get_housing_mainframe(); + + floor_pos = ( mainframe.origin[ 0 ], mainframe.origin[ 1 ], doorset[ "door_closed_pos" ][ 2 ] ); + parts.e[ "floor" + i + "_pos" ] = floor_pos; + + if ( mainframe.origin == floor_pos ) + { + parts.e[ "initial_floor" ] = i; + parts.e[ "current_floor" ] = i; + } + } + + // === save build info === + level._elevators[ level._elevators.size ] = parts; + + // trash all script origins no longer needed + elevator_bound delete(); + elevator_bound_end delete(); + } + foreach ( elevator_doorset in elevator_doorsets ) + elevator_doorset delete(); + + build_call_buttons(); + + if ( !level._elevator_motion_detection ) + setup_hints(); + + // turn on all primary lights for elevators if they have em + foreach ( elevator in level._elevators ) + { + pLights = elevator get_housing_primarylight(); + if ( isdefined( pLights ) && pLights.size ) + { + foreach ( pLight in pLights ) + pLight setlightintensity( 0.75 ); + } + } +} + +build_call_buttons() +{ + level._elevator_callbuttons = getentarray( "elevator_call", "targetname" ); + assertex( isdefined( level._elevator_callbuttons ) && ( level._elevator_callbuttons.size > 1 ), "Missing or not enough elevator call buttons" ); + + // per call button + foreach ( callbutton in level._elevator_callbuttons ) + { + callbutton.e = []; + callbutton_v_vec = ( 0, 0, callbutton.origin[ 2 ] ); + callbutton_h_vec = ( callbutton.origin[ 0 ], callbutton.origin[ 1 ], 0 ); + + temp_elevator_list = []; + // per elevator + foreach ( e_idx, elevator in level._elevators ) + { + // per floor + foreach ( f_idx, eFloor in elevator get_outer_doorsets() ) + { + v_vec = ( 0, 0, elevator.e[ "floor" + f_idx + "_pos" ][ 2 ] ); + h_vec = ( elevator.e[ "floor" + f_idx + "_pos" ][ 0 ], elevator.e[ "floor" + f_idx + "_pos" ][ 1 ], 0 ); + + if ( abs( distance( callbutton_v_vec, v_vec ) ) <= level._elevator_callbutton_link_v ) + { + if ( abs( distance( callbutton_h_vec, h_vec ) ) <= level._elevator_callbutton_link_h ) + { + temp_elevator_list[ temp_elevator_list.size ] = elevator; // build list of elevators linked on floor f_idx + callbutton.e[ f_idx ] = temp_elevator_list; + } + } + } + } + callbutton make_discrete_trigger(); + assertex( isdefined( callbutton.e ) && callbutton.e.size, "Elevator call button at " + callbutton.origin + " failed to grab near by elevators, placed too far?" ); + + // build motion detection triggers for motion triggered calls + callbutton.motion_trigger = spawn( "trigger_radius", callbutton.origin + ( 0, 0, -32 ), 0, 32, 64 ); + } +} + +setup_hints() +{ + // elevator inside use trigger hint + foreach ( elevator in level._elevators ) + { + use_trig = elevator get_housing_inside_trigger(); + floors = elevator get_outer_doorsets(); + num_of_floors = floors.size; + + use_trig SetCursorHint( "HINT_NOICON" ); + if ( num_of_floors > 2 ) + // Press and hold &&1 to select floor. + use_trig setHintString( &"ELEVATOR_FLOOR_SELECT_HINT" ); + else + // Press and hold &&1 to use elevator. + use_trig setHintString( &"ELEVATOR_USE_HINT" ); + } + + // elevator call button hint + foreach ( callbutton in level._elevator_callbuttons ) + { + callbutton SetCursorHint( "HINT_NOICON" ); + // Press and hold &&1 to call elevator. + callbutton setHintString( &"ELEVATOR_CALL_HINT" ); + } +} + +//==========================================================================// +// === HELPERS === // +//==========================================================================// + +// setup discrete trigger for discrete waittill +make_discrete_trigger() +{ + self.enabled = 1; // enable now for disabling trigger + self disable_trigger(); // disable trigger, enable again only when waittill on +} + +// trigger only exist when waittill upon +discrete_waittill( msg ) +{ + assert( isdefined( self.motion_trigger ) ); + + self enable_trigger(); // this is for disabling trigger immediately after triggering + + if ( level._elevator_motion_detection ) + self.motion_trigger waittill( msg, param ); + else + self waittill( msg, param ); + + self disable_trigger(); + return param; +} + + +enable_trigger() +{ + if ( !self.enabled ) + { + self.enabled = 1; + self.origin += ( 0, 0, 10000 ); + + if ( isdefined( self.motion_trigger ) ) + self.motion_trigger.origin += ( 0, 0, 10000 ); + } +} + +disable_trigger() +{ + self notify( "disable_trigger" ); + if ( self.enabled ) + self thread disable_trigger_helper(); +} + +disable_trigger_helper() +{ + self endon( "disable_trigger" ); + self.enabled = 0; + wait 1.5; + self.origin += ( 0, 0, -10000 ); + + if ( isdefined( self.motion_trigger ) ) + self.motion_trigger.origin += ( 0, 0, -10000 ); +} + +// ========== OUTER DOOR SETS =========== +// returns array of outer doorsets for this floor - ent[] +get_outer_doorset( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ]; +} + +// returns array of floors of doorsets - int[] +get_outer_doorsets() +{ + return self.e[ "outer_doorset" ]; +} + +// returns outer door closed position for this floor - vec +get_outer_closedpos( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ][ "door_closed_pos" ]; +} + +// returns left door entity for this floor - ent +get_outer_leftdoor( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ][ "left_door" ]; +} + +// returns right door entity for this floor - ent +get_outer_rightdoor( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ][ "right_door" ]; +} + +// returns left door opened position for this floor - vec +get_outer_leftdoor_openedpos( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ][ "left_door_opened_pos" ]; +} + +// returns right door opened position for this floor - vec +get_outer_rightdoor_openedpos( floor_num ) +{ + return self.e[ "outer_doorset" ][ floor_num ][ "right_door_opened_pos" ]; +} + +// ========= HOUSING ========= +// returns all the entities that will move when the elevator moves between floors - ent[] +get_housing_children() +{ + children = []; + + door_trig = self get_housing_door_trigger(); + use_trig = self get_housing_inside_trigger(); + motion_trig = use_trig.motion_trigger; + left_door = self get_housing_leftdoor(); + right_door = self get_housing_rightdoor(); + + children[ children.size ] = door_trig; + children[ children.size ] = use_trig; + children[ children.size ] = left_door; + children[ children.size ] = right_door; + + if ( isdefined( motion_trig ) ) + children[ children.size ] = motion_trig; + + // append script models as children of elevator moving body + script_models = self get_housing_models(); + foreach ( eModel in script_models ) + children[ children.size ] = eModel; + + // append primary light(s) as children of elevator moving body + primarylights = get_housing_primarylight(); + foreach ( pLight in primarylights ) + children[ children.size ] = pLight; + + return children; +} + +// returns only the mainframe script_brushmodel, there can only be one per elevator! - ent +get_housing_mainframe() +{ + parts = self.e[ "housing" ][ "mainframe" ]; + + housing_model = undefined; + foreach ( part in parts ) + { + if ( part.classname != "script_model" && part.code_classname != "light" ) + { + assertex( !isdefined( housing_model ), "Fail! Found more than one elevator housing script_brushmodels per elevator" ); + housing_model = part; + } + } + assertex( isdefined( housing_model ), "Epic fail! No elevator housing script_brushmodel found" ); + return housing_model; +} + +// returns an array of script_models used as part of the elevator prefab - ent[] +get_housing_models() +{ + parts = self.e[ "housing" ][ "mainframe" ]; + temp_model_array = []; + + foreach ( part in parts ) + { + if ( part.classname == "script_model" ) + temp_model_array[ temp_model_array.size ] = part; + } + return temp_model_array; +} + +// returns an array of lights - ent[] +get_housing_primarylight() +{ + parts = self.e[ "housing" ][ "mainframe" ]; + temp_primarylights = []; + + foreach ( part in parts ) + { + if ( part.code_classname == "light" ) + temp_primarylights[ temp_primarylights.size ] = part; + } + return temp_primarylights; +} + +// returns a single model to play elevator music on, this must exist and only one! - ent +get_housing_musak_model() +{ + models = self get_housing_models(); + musak_model = undefined; + + foreach ( eModel in models ) + { + if ( isdefined( eModel.script_noteworthy ) && eModel.script_noteworthy == "play_musak" ) + musak_model = eModel; + } + //assertex( isdefined( musak_model ), "Fail! Missing script_model to play elevator music on, [script_noteworthy = play_musak]" ); + + return musak_model; +} + +// returns interrupt trigger for elevator doors - ent trig +get_housing_door_trigger() +{ + return self.e[ "housing" ][ "door_trigger" ]; +} + +// returns trigger for floor selection inside the elevator - ent trig +get_housing_inside_trigger() +{ + return self.e[ "housing" ][ "inside_trigger" ]; +} + +// returns inner door's closing position - vec +get_housing_closedpos() +{ + return self.e[ "housing" ][ "door_closed_pos" ]; +} + +// returns inner left door entity - ent +get_housing_leftdoor() +{ + return self.e[ "housing" ][ "left_door" ]; +} + +// returns inner right door entity - ent +get_housing_rightdoor() +{ + return self.e[ "housing" ][ "right_door" ]; +} + +// returns inner left door opened position - vec +get_housing_leftdoor_opened_pos() +{ + return self.e[ "housing" ][ "left_door_opened_pos" ]; +} + +// returns inner right door opened position - vec +get_housing_rightdoor_opened_pos() +{ + return self.e[ "housing" ][ "right_door_opened_pos" ]; +} + +// floor currently the elevator is on - int +get_curFloor() +{ + moving = self elevator_floor_update(); + return self.e[ "current_floor" ]; +} + +// floor elevator initially at on level load - int +get_initFloor() +{ + return self.e[ "initial_floor" ]; +} + +waittill_finish_moving( ent1, ent1_moveto_pos, ent2, ent2_moveto_pos ) +{ + if ( !isdefined( ent2 ) && !isdefined( ent2_moveto_pos ) ) + { + ent2 = ent1; + ent2_moveto_pos = ent1_moveto_pos; + } + + while ( 1 ) + { + ent1_current_pos = ent1.origin; + etn2_current_pos = ent2.origin; + + if ( ent1_current_pos == ent1_moveto_pos && etn2_current_pos == ent2_moveto_pos ) + break; + + wait 0.05; + } +} + +// return test of min max bound on xy plane, self = entity being tested - bool +isInbound( bounding_box ) +{ + + assertex( isdefined( self ) && isdefined( self.origin ), "Fail! Can not test bounds with the entity called on" ); + + // the box isn't working on the angle that I have so I'm going to do it by a sphere shape.. -Nate + //special case cause I don't know if a sphere will break other levels. + if( level._script == "plaza" || level._script == "highrise_test" ) + return isInBoundingSpere( bounding_box ); + + v_x = self.origin[ 0 ]; + v_y = self.origin[ 1 ]; + + min_x = bounding_box[ 0 ]; + max_x = bounding_box[ 1 ]; + min_y = bounding_box[ 2 ]; + max_y = bounding_box[ 3 ]; + + return ( v_x >= min_x && v_x <= max_x && v_y >= min_y && v_y <= max_y ); +} + +isInBoundingSpere( bounding_box ) +{ + v_x = self.origin[ 0 ]; + v_y = self.origin[ 1 ]; + min_x = bounding_box[ 0 ]; + max_x = bounding_box[ 1 ]; + min_y = bounding_box[ 2 ]; + max_y = bounding_box[ 3 ]; + + mid_x = (min_x + max_x )/2; + mid_y = (min_y + max_y )/2; + radius = abs( Distance( (min_x,min_y,0 ), (mid_x,mid_y,0)) ); + return( abs( distance( (v_x,v_y,0), (mid_x,mid_y,0) ) ) < radius ); +} + +waittill_or_timeout( msg, timer ) +{ + self endon( msg ); + wait( timer ); +} + +elevator_get_dvar_int( dvar, def ) +{ + return int( elevator_get_dvar( dvar, def ) ); +} + +elevator_get_dvar( dvar, def ) +{ + if ( getdvar( dvar ) != "" ) + return getdvarfloat( dvar ); + else + { + setdvar( dvar, def ); + return def; + } +} + +elevator_debug() +{ + if ( !level._elevator_debug ) + return; + + //print3d(, , , , , ) + + while ( 1 ) + { + // simple debug info: + + if ( level._elevator_debug != 2 ) + continue; + + // full debug info: + + // print all parts for all elevators + foreach ( i, elevator in level._elevators ) + { + mainframe = elevator get_housing_mainframe(); + musak_model = elevator get_housing_musak_model(); + + print3d( musak_model.origin, "[e" + i + "]musak_origin", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + print3d( mainframe.origin, "[e" + i + "]mainframe", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + print3d( elevator.e[ "housing" ][ "left_door" ].origin, "[e" + i + "]left door", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + print3d( elevator.e[ "housing" ][ "right_door" ].origin, "[e" + i + "]right door", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + print3d( elevator.e[ "housing" ][ "door_closed_pos" ], "[e" + i + "]->|<-", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + print3d( elevator.e[ "housing" ][ "inside_trigger" ].origin, "[e" + i + "]USE", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + + foreach ( j, eFloor in elevator.e[ "outer_doorset" ] ) + { + print3d( eFloor[ "left_door" ].origin + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]left door", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 ); + print3d( eFloor[ "right_door" ].origin + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]right door", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 ); + print3d( eFloor[ "door_closed_pos" ] + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]->|<-", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 ); + print3d( elevator.e[ "floor" + j + "_pos" ] + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]stop", ( 1.0, 0.75, 0.75 ), 1, 0.25, 20 ); + } + } + + // per button + foreach ( callbutton in level._elevator_callbuttons ) + { + print3d( callbutton.origin, "linked to:", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + + // per floor + foreach ( f_idx, eFloor in callbutton.e ) + { + // per elevator linked + printoffset = 0; + foreach ( e_idx, eLinked in eFloor ) + { + printoffset++ ; + // e_idx is used to offset print + print_pos = callbutton.origin + ( 0, 0, ( printoffset ) * ( -4 ) ); + print3d( print_pos, "[f" + f_idx + "][e" + eLinked.e[ "id" ] + "]", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 ); + } + } + } + + wait 0.05; + } +} \ No newline at end of file diff --git a/common_scripts/_fx.gsc b/common_scripts/_fx.gsc new file mode 100644 index 0000000..9c0869b --- /dev/null +++ b/common_scripts/_fx.gsc @@ -0,0 +1,518 @@ +#include common_scripts\utility; +#include common_scripts\_createfx; + +initFX() +{ + if ( !isdefined( level._func ) ) + { + // this array will be filled with code commands that SP or MP may use but doesn't exist in the other. + level._func = []; + } + if( !isdefined( level._func[ "create_triggerfx" ] ) ) + level._func[ "create_triggerfx" ] = ::create_triggerfx; + + // wrapper for the exploder function so we dont have to use flags and do ifs/waittills on every exploder call + level._exploderFunction = ::exploder_before_load; + waittillframeend;// Wait one frame so the effects get setup by the maps fx thread + waittillframeend;// Wait another frame so effects can be loaded based on start functions. Without this FX are initialiazed before they are defined by start functions. + level._exploderFunction = ::exploder_after_load; + + /# setDevDvarIfUninitialized( "scr_map_exploder_dump", 0 ); #/ + + for ( i = 0; i < level._createFXent.size; i++ ) + { + ent = level._createFXent[ i ]; + ent set_forward_and_up_vectors(); + + if ( ent.v[ "type" ] == "loopfx" ) + ent thread loopfxthread(); + if ( ent.v[ "type" ] == "oneshotfx" ) + ent thread oneshotfxthread(); + if ( ent.v[ "type" ] == "soundfx" ) + ent thread create_loopsound(); + } +} + +print_org( fxcommand, fxId, fxPos, waittime ) +{ + if ( GetDvar( "debug" ) == "1" ) + { + println( "{" ); + println( "\"origin\" \"" + fxPos[ 0 ] + " " + fxPos[ 1 ] + " " + fxPos[ 2 ] + "\"" ); + println( "\"classname\" \"script_model\"" ); + println( "\"model\" \"fx\"" ); + println( "\"script_fxcommand\" \"" + fxcommand + "\"" ); + println( "\"script_fxid\" \"" + fxId + "\"" ); + println( "\"script_delay\" \"" + waittime + "\"" ); + println( "}" ); + } +} + +OneShotfx( fxId, fxPos, waittime, fxPos2 ) +{ +// level thread print_org ("OneShotfx", fxId, fxPos, waittime); +// level thread OneShotfxthread (fxId, fxPos, waittime, fxPos2); +} + +exploderfx( num, fxId, fxPos, waittime, fxPos2, fireFx, fireFxDelay, fireFxSound, fxSound, fxQuake, fxDamage, soundalias, repeat, delay_min, delay_max, damage_radius, fireFxTimeout, exploder_group ) +{ + if ( 1 ) + { + ent = createExploder( fxId ); + ent.v[ "origin" ] = fxPos; + ent.v[ "angles" ] = ( 0, 0, 0 ); + if ( isdefined( fxPos2 ) ) + ent.v[ "angles" ] = vectortoangles( fxPos2 - fxPos ); + ent.v[ "delay" ] = waittime; + ent.v[ "exploder" ] = num; + // deprecated + return; + } + fx = spawn( "script_origin", ( 0, 0, 0 ) ); +// println ("total ", getentarray ("script_origin","classname").size); + fx.origin = fxPos; + fx.angles = vectortoangles( fxPos2 - fxPos ); +// fx.targetname = "exploder"; + fx.script_exploder = num; + fx.script_fxid = fxId; + fx.script_delay = waittime; + + fx.script_firefx = fireFx; + fx.script_firefxdelay = ( fireFxDelay );// for awhile the script exported strings for this value so we cast it to float + fx.script_firefxsound = fireFxSound; + + fx.script_sound = fxSound; + fx.script_earthquake = fxQuake; + fx.script_damage = ( fxDamage ); + fx.script_radius = ( damage_radius ); + fx.script_soundalias = soundalias; + fx.script_firefxtimeout = ( fireFxTimeout ); + fx.script_repeat = ( repeat ); + fx.script_delay_min = ( delay_min ); + fx.script_delay_max = ( delay_max ); + fx.script_exploder_group = exploder_group; + + forward = anglestoforward( fx.angles ); + forward = vector_multiply( forward, 150 ); + fx.targetPos = fxPos + forward; + + if ( !isdefined( level._script_exploders ) ) + level._script_exploders = []; + level._script_exploders[ level._script_exploders.size ] = fx; + + createfx_showOrigin( fxid, fxPos, waittime, fxpos2, "exploderfx", fx, undefined, fireFx, fireFxDelay, + fireFxSound, fxSound, fxQuake, fxDamage, soundalias, repeat, delay_min, delay_max, damage_radius, fireFxTimeout ); +} + + +/* +loopfxRotate(fxId, fxPos, waittime, angle, fxStart, fxStop, timeout) +{ + level thread print_org ("loopfx", fxId, fxPos, waittime); + level thread loopfxthread (fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout); +} +*/ + + +loopfx( fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout ) +{ + println( "Loopfx is deprecated!" ); + ent = createLoopEffect( fxId ); + ent.v[ "origin" ] = fxPos; + ent.v[ "angles" ] = ( 0, 0, 0 ); + if ( isdefined( fxPos2 ) ) + ent.v[ "angles" ] = vectortoangles( fxPos2 - fxPos ); + ent.v[ "delay" ] = waittime; +} + +/* +loopfx(fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout) +{ + level thread print_org ("loopfx", fxId, fxPos, waittime); + level thread loopfxthread (fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout); +} +*/ + +create_looper() +{ + //assert (isdefined(self.looper)); + self.looper = playLoopedFx( level._effect[ self.v[ "fxid" ] ], self.v[ "delay" ], self.v[ "origin" ], 0, self.v[ "forward" ], self.v[ "up" ] ); + create_loopsound(); +} + +create_loopsound() +{ + self notify( "stop_loop" ); + if ( isdefined( self.v[ "soundalias" ] ) && ( self.v[ "soundalias" ] != "nil" ) ) + { + // tagTP - The createfx scripts don't appear to set the "stoppable" flag correctly after a node + // tagTP - is created, so when the entity was moved, there would be a leftover entity that continued + // tagTP - to play a copy of the looping sound. So, if createfx is enabled, allow it to be stopped. + if (( isdefined( self.v[ "stoppable" ] ) && self.v[ "stoppable" ] ) || level._createFX_enabled ) + { + if ( isdefined( self.looper ) ) + self.looper thread loop_fx_sound( self.v[ "soundalias" ], self.v[ "origin" ], "death" ); + else + thread loop_fx_sound( self.v[ "soundalias" ], self.v[ "origin" ], "stop_loop" ); + } + else + { + if ( isdefined( self.looper ) ) + self.looper thread loop_fx_sound( self.v[ "soundalias" ], self.v[ "origin" ] ); + else + thread loop_fx_sound( self.v[ "soundalias" ], self.v[ "origin" ] ); + } + } +} + +loopfxthread() +{ + waitframe(); +// println ( "fx testing running Id: ", fxId ); +// if ((isdefined (level.scr_sound)) && (isdefined (level.scr_sound[fxId]))) +// loopSound(level.scr_sound[fxId], fxPos); + + if ( isdefined( self.fxStart ) ) + level waittill( "start fx" + self.fxStart ); + + while ( 1 ) + { + /* + if (isdefined (ent.org2)) + { + fxAngle = vectorNormalize (ent.org2 - ent.org); + looper = playLoopedFx( level._effect[fxId], ent.delay, ent.org, 0, fxAngle ); + } + else + looper = playLoopedFx( level._effect[fxId], ent.delay, ent.org, 0 ); + */ + create_looper(); + + if ( isdefined( self.timeout ) ) + thread loopfxStop( self.timeout ); + + if ( isdefined( self.fxStop ) ) + level waittill( "stop fx" + self.fxStop ); + else + return; + + if ( isdefined( self.looper ) ) + self.looper delete(); + + if ( isdefined( self.fxStart ) ) + level waittill( "start fx" + self.fxStart ); + else + return; + } +} + +loopfxChangeID( ent ) +{ + self endon( "death" ); + ent waittill( "effect id changed", change ); +} + +loopfxChangeOrg( ent ) +{ + self endon( "death" ); + for ( ;; ) + { + ent waittill( "effect org changed", change ); + self.origin = change; + } +} + +loopfxChangeDelay( ent ) +{ + self endon( "death" ); + ent waittill( "effect delay changed", change ); +} + +loopfxDeletion( ent ) +{ + self endon( "death" ); + ent waittill( "effect deleted" ); + self delete(); +} + +loopfxStop( timeout ) +{ + self endon( "death" ); + wait( timeout ); + self.looper delete(); +} + +loopSound( sound, Pos, waittime ) +{ +// level thread print_org ("loopSound", sound, Pos, waittime); + level thread loopSoundthread( sound, Pos, waittime ); +} + +loopSoundthread( sound, pos, waittime ) +{ + org = spawn( "sound_emitter", ( pos ) ); + + org.origin = pos; +// println ("hello1 ", org.origin, sound); + org playLoopSound( sound ); +} + +gunfireloopfx( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ) +{ + thread gunfireloopfxthread( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ); +} + +gunfireloopfxthread( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ) +{ + level endon( "stop all gunfireloopfx" ); + waitframe(); + + if ( betweenSetsMax < betweenSetsMin ) + { + temp = betweenSetsMax; + betweenSetsMax = betweenSetsMin; + betweenSetsMin = temp; + } + + betweenSetsBase = betweenSetsMin; + betweenSetsRange = betweenSetsMax - betweenSetsMin; + + if ( shotdelayMax < shotdelayMin ) + { + temp = shotdelayMax; + shotdelayMax = shotdelayMin; + shotdelayMin = temp; + } + + shotdelayBase = shotdelayMin; + shotdelayRange = shotdelayMax - shotdelayMin; + + if ( shotsMax < shotsMin ) + { + temp = shotsMax; + shotsMax = shotsMin; + shotsMin = temp; + } + + shotsBase = shotsMin; + shotsRange = shotsMax - shotsMin; + + fxEnt = spawnFx( level._effect[ fxId ], fxPos ); + + if ( !level._createFX_enabled ) + fxEnt willNeverChange(); + + for ( ;; ) + { + shotnum = shotsBase + randomint( shotsRange ); + for ( i = 0;i < shotnum;i++ ) + { + triggerFx( fxEnt ); + + wait( shotdelayBase + randomfloat( shotdelayRange ) ); + } + wait( betweenSetsBase + randomfloat( betweenSetsRange ) ); + } +} + +gunfireloopfxVec( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ) +{ + thread gunfireloopfxVecthread( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ); +} + +gunfireloopfxVecthread( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax ) +{ + level endon( "stop all gunfireloopfx" ); + waitframe(); + + if ( betweenSetsMax < betweenSetsMin ) + { + temp = betweenSetsMax; + betweenSetsMax = betweenSetsMin; + betweenSetsMin = temp; + } + + betweenSetsBase = betweenSetsMin; + betweenSetsRange = betweenSetsMax - betweenSetsMin; + + if ( shotdelayMax < shotdelayMin ) + { + temp = shotdelayMax; + shotdelayMax = shotdelayMin; + shotdelayMin = temp; + } + + shotdelayBase = shotdelayMin; + shotdelayRange = shotdelayMax - shotdelayMin; + + if ( shotsMax < shotsMin ) + { + temp = shotsMax; + shotsMax = shotsMin; + shotsMin = temp; + } + + shotsBase = shotsMin; + shotsRange = shotsMax - shotsMin; + + fxPos2 = vectornormalize( fxPos2 - fxPos ); + + fxEnt = spawnFx( level._effect[ fxId ], fxPos, fxPos2 ); + + if ( !level._createFX_enabled ) + fxEnt willNeverChange(); + + for ( ;; ) + { + shotnum = shotsBase + randomint( shotsRange ); + for ( i = 0;i < int( shotnum / level._fxfireloopmod );i++ ) + { + triggerFx( fxEnt ); + delay = ( ( shotdelayBase + randomfloat( shotdelayRange ) ) * level._fxfireloopmod ); + if ( delay < .05 ) + delay = .05; + wait delay; + } + wait( shotdelayBase + randomfloat( shotdelayRange ) ); + wait( betweenSetsBase + randomfloat( betweenSetsRange ) ); + } +} + +setfireloopmod( value ) +{ + level._fxfireloopmod = 1 / value; +} + +setup_fx() +{ + if ( ( !isdefined( self.script_fxid ) ) || ( !isdefined( self.script_fxcommand ) ) || ( !isdefined( self.script_delay ) ) ) + { +// println (self.script_fxid); +// println (self.script_fxcommand); +// println (self.script_delay); +// println ("Effect at origin ", self.origin," doesn't have script_fxid/script_fxcommand/script_delay"); +// self delete(); + return; + } + +// println ("^a Command:", self.script_fxcommand, " Effect:", self.script_fxID, " Delay:", self.script_delay, " ", self.origin); + if ( isdefined( self.model ) ) + if ( self.model == "toilet" ) + { + self thread burnville_paratrooper_hack(); + return; + } + + org = undefined; + if ( isdefined( self.target ) ) + { + ent = getent( self.target, "targetname" ); + if ( isdefined( ent ) ) + org = ent.origin; + } + + fxStart = undefined; + if ( isdefined( self.script_fxstart ) ) + fxStart = self.script_fxstart; + + fxStop = undefined; + if ( isdefined( self.script_fxstop ) ) + fxStop = self.script_fxstop; + + if ( self.script_fxcommand == "OneShotfx" ) + OneShotfx( self.script_fxId, self.origin, self.script_delay, org ); + if ( self.script_fxcommand == "loopfx" ) + loopfx( self.script_fxId, self.origin, self.script_delay, org, fxStart, fxStop ); + if ( self.script_fxcommand == "loopsound" ) + loopsound( self.script_fxId, self.origin, self.script_delay ); + + self delete(); +} + +burnville_paratrooper_hack() +{ + normal = ( 0, 0, self.angles[ 1 ] ); +// println ("z: paratrooper fx hack: ", normal); + id = level._effect[ self.script_fxId ]; + origin = self.origin; + +// if (isdefined (self.script_delay)) +// wait (self.script_delay); + + wait 1; + level thread burnville_paratrooper_hack_loop( normal, origin, id ); + self delete(); +} + +burnville_paratrooper_hack_loop( normal, origin, id ) +{ + while ( 1 ) + { + // iprintln ("z: playing paratrooper fx", origin); + + playfx( id, origin ); + wait( 30 + randomfloat( 40 ) ); + } +} + +create_triggerfx() +{ + //assert (isdefined(self.looper)); + if( ! verify_effects_assignment( self.v[ "fxid" ] ) ) + return; + + self.looper = spawnFx( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] ); + triggerFx( self.looper, self.v[ "delay" ] ); + + if ( !level._createFX_enabled ) + self.looper willNeverChange(); + + create_loopsound(); +} + +verify_effects_assignment( effectID ) +{ + if( isdefined ( level._effect[ effectID ] ) ) + return true; + if( ! isdefined( level._missing_FX ) ) + level._missing_FX = []; + level._missing_FX[ self.v[ "fxid" ] ] = effectID; + verify_effects_assignment_print( effectID ); + return false; +} + +verify_effects_assignment_print( effectID ) +{ + + level notify ( "verify_effects_assignment_print" ); + level endon ( "verify_effects_assignment_print" ); + wait .05; //allow errors on the same frame to que up before printing + + println("Error:"); + println("Error:**********MISSING EFFECTS IDS**********"); + keys = getarraykeys( level._missing_FX ); + foreach( key in keys ) + { + println( "Error: Missing Effects ID assignment for: "+ key ); + } + println("Error:"); + + assertmsg( "Missing Effects ID assignments ( see console )" ); +} + +OneShotfxthread() +{ + waitframe(); + + if ( self.v[ "delay" ] > 0 ) + wait self.v[ "delay" ]; + + /* + if ( isdefined( self.v[ "fire_range" ] ) ) + { + thread fire_radius( self.v[ "origin" ], self.v[ "fire_range" ] ); + } + */ + + [[ level._func[ "create_triggerfx" ] ]](); +}> \ No newline at end of file diff --git a/common_scripts/_moon.gsc b/common_scripts/_moon.gsc new file mode 100644 index 0000000..69739bb --- /dev/null +++ b/common_scripts/_moon.gsc @@ -0,0 +1,24 @@ +MOON_GLOBAL_GRAVITY_SCALE = 0.17; +MOON_AIM_SCALE_TURN_RATE = 1.0; +MOON_AIM_ADS_PITCH = 85;//1.5 x 55 +MOON_AIM_ADS_YAW = 135;//1.5 x 90 + +getMoonGlobalGravityScale() +{ + return MOON_GLOBAL_GRAVITY_SCALE; +} + +getMoonGlobalTurnRateScale() +{ + return MOON_AIM_SCALE_TURN_RATE; +} + +getMoonGlobalADSYaw() +{ + return MOON_AIM_ADS_YAW; +} + +getMoonGlobalADSPitch() +{ + return MOON_AIM_ADS_PITCH; +} \ No newline at end of file diff --git a/common_scripts/_painter.gsc b/common_scripts/_painter.gsc new file mode 100644 index 0000000..340f489 --- /dev/null +++ b/common_scripts/_painter.gsc @@ -0,0 +1,1106 @@ +#include common_scripts\utility; + +main( painter_spmp ) +{ + + painter_setup_array = getentarray( "painter_setup", "targetname" ); + + if ( !painter_setup_array.size ) + return; + + if ( !getdvarint( "painter" ) ) + { + array_thread( painter_setup_array, ::painter_clean_me ); + return; + } + + painter_initvars( painter_spmp ); + + painter_groups = []; + + groups = get_painter_groups( painter_setup_array ); + + foreach ( group in groups ) + setup_painter_group( group ); + + thread painter_init(); + + array_thread( level._spam_model_group, ::default_undefined ); + level._stop_load = true; + level waittill( "forever" ); +} + +painter_clean_me() +{ + if( isdefined( self.target ) ) + { + ent = getent(self.target,"targetname"); + ent delete(); + } + self delete(); +} + +default_undefined() +{ + if ( !isdefined( self.bPosedstyle ) ) + self.bPosedstyle = false; + if ( !isdefined( self.bOrienttoplayeryrot ) ) + self.bOrienttoplayeryrot = false; + if ( !isdefined( self.bTreeOrient ) ) + self.bTreeOrient = false; + if ( !isdefined( self.bFacade ) ) + self.bFacade = false; + if ( !isdefined( self.density ) ) + self.density = 32; + if ( !isdefined( self.radius ) ) + self.radius = 84; + if ( !isdefined( self.maxdist ) ) + self.maxdist = 1000; + if ( !isdefined( self.angleoffset ) ) + self.angleoffset = []; + +} + +setup_painter_group( group ) +{ + density = 100000001; + group_copy = group; + // figure out default radius and density for the group + bTreeOrient = undefined; + bFacade = undefined; + radius = undefined; + maxdist = undefined; + offsetheight = undefined; + bPosedstyle = undefined; + bOrienttoplayeryrot = undefined; + angleoffset = undefined; + + + foreach ( obj in group ) + { + angleoffset = get_angle_offset( obj ); + offsetheight = get_height_offset( obj ); + modeluseprefab = ( isdefined( obj.script_parameters ) && obj.script_parameters == "use_prefab_model" ); + + + if ( isdefined( obj.radius ) ) + radius = obj.radius; + if ( isdefined( obj.script_painter_treeorient ) && obj.script_painter_treeorient ) + bTreeOrient = true; + if ( isdefined( obj.script_painter_maxdist ) && obj.script_painter_maxdist ) + maxdist = obj.script_painter_maxdist; + if ( isdefined( obj.script_painter_facade ) && obj.script_painter_facade ) + bFacade = true; + foreach ( other_obj in group_copy ) + { + if ( obj == other_obj ) + continue; + dist = distance( obj.origin, other_obj.origin ); + assert( dist > 0 ); + if ( dist < density ) + density = dist; + } + if ( density == 100000001 ) + density = undefined; + add_spammodel( obj.script_paintergroup, obj.model, bTreeOrient, bFacade, density, radius, maxdist, offsetheight, bPosedstyle, bOrienttoplayeryrot, angleoffset, modeluseprefab ); + } +} + +get_angle_offset( obj ) +{ + if( !isdefined( obj.target ) ) + return undefined; + + targent = getent( obj.target, "targetname" ); + assert( isdefined ( targent ) ); + return targent.angles - obj.angles; +} + +get_height_offset( obj ) +{ + if( !isdefined( obj.target ) ) + return undefined; + + targent = getent( obj.target, "targetname" ); + assert( isdefined ( targent ) ); + origin = targent.origin[2] - obj.origin[2]; + targent delete(); + return origin; +} + + + + +get_painter_groups( painter_setup_array ) +{ + groups = []; + script_paintergroup = ""; + foreach ( paint_obj in painter_setup_array ) + { + if ( !isdefined( paint_obj.script_paintergroup ) ) + { + paint_obj.script_paintergroup = paint_obj.model; + } + script_paintergroup = paint_obj.script_paintergroup; + + level._painter_startgroup = script_paintergroup; + + if ( !isdefined( groups[ script_paintergroup ] ) || ! groups[ script_paintergroup ].size ) + groups[ script_paintergroup ] = []; + groups[ script_paintergroup ][ groups[ script_paintergroup ].size ] = paint_obj; + } + return groups; +} + +painter_initvars( painter_spmp ) +{ + level._clearalltextafterhudelem = false; + level._bPosedstyle = false; + level._bOrienttoplayeryrot = false; + level._spam_density_scale = 16; + level._spaming_models = false; + level._spam_model_group = []; + level._spamed_models = []; + level._spam_models_flowrate = .1; + level._spam_model_radius = 31; + level._spam_maxdist = 1000; + level._previewmodels = []; + level._spam_models_isCustomrotation = false; + level._spam_models_isCustomheight = false; + level._spam_models_customheight = 0; + level._spam_model_circlescale_lasttime = 0; + level._spam_model_circlescale_accumtime = 0; + level._paintadd = ::add_spammodel; +// level.geteyeoffset = (0,0,24); + level._timeLimitOverride = true; + thread hack_start( painter_spmp ); + thread hud_init(); +} + +hack_start( painter_spmp ) +{ + if ( !isdefined( painter_spmp ) ) + painter_spmp = "painter"; + + precachemenu( painter_spmp ); + + //who knows what the mp scripts are doing I took a dive deep into them and discovered many hud elements being controled through code and not through a menu that can be easily disabled + // here I simply automate some things to get the user up and running. + // get the player going. I don't handle people dieing in this tool since they are in ufo mode anyway. + + flag_init( "user_alive" ); + while ( !isdefined( get_player() ) ) + wait .05; + level._painter_player = get_player(); + wait .05; + menu = "team_marinesopfor"; + + if( level._multiTeamBased ) + { + menu = "team_mtdm_options"; + } + + response = "autoassign"; + level._painter_player notify( "menuresponse", menu, response ); + wait .05; + menu = "changeclass_offline"; + response = "offline_class1_mp, 0"; + level._painter_player notify( "menuresponse", menu, response ); + level._painter_player openpopupmenu( painter_spmp );// painter.menu execs some console commands( ufo mode ).. sneaky hacks. + wait .05; + level._painter_player closepopupmenu(); + flag_set( "user_alive" ); +} + +painter_init() +{ + array_call( getentarray( "script_model", "classname" ), ::delete ); + setcurrentgroup( level._painter_startgroup ); + level._painter_startgroup = undefined; + playerInit(); +} + +hud_update_placed_model_count() +{ + level._hud_controler[ "helppm" ].description setvalue( level._spamed_models.size ); + whitecap = 256; + if ( level._spamed_models.size < whitecap ) + { + level._hud_controler[ "helppm" ].description.color = ( 1, 1, 1 ); + return; + } + + r = 1; + g = 1 - ( ( level._spamed_models.size - whitecap ) / whitecap ); + b = g; + + level._hud_controler[ "helppm" ].description.color = ( r, g, b ); + +} + +hud_init() +{ + flag_init( "user_hud_active" ); + flag_wait( "user_alive" ); + + //shorter list for mp cause it's got too many g_configstring somesuch. There is probably better check than substr on the mapname. I don't think this will bite me though, knock on wood. + listsize = 7; + if ( is_mp() ) + listsize = 7; + + hudelems = []; + spacer = 15; + div = int( listsize / 2 ); + org = 240 + div * spacer; + alphainc = .5 / div; + alpha = alphainc; + + for ( i = 0;i < listsize;i++ ) + { + hudelems[ i ] = _newhudelem(); + hudelems[ i ].location = 0; + hudelems[ i ].alignX = "left"; + hudelems[ i ].alignY = "middle"; + hudelems[ i ].foreground = 1; + hudelems[ i ].fontScale = 2; + hudelems[ i ].sort = 20; + if ( i == div ) + hudelems[ i ].alpha = 1; + else + hudelems[ i ].alpha = alpha; + + hudelems[ i ].x = 20; + hudelems[ i ].y = org; + hudelems[ i ] _settext( "." ); + + if ( i == div ) + alphainc *= -1; + + alpha += alphainc; + + org -= spacer; + } + + level._spam_group_hudelems = hudelems; + + crossHair = _newhudelem(); + crossHair.location = 0; + crossHair.alignX = "center"; + crossHair.alignY = "bottom"; + crossHair.foreground = 1; + crossHair.fontScale = 2; + crossHair.sort = 20; + crossHair.alpha = 1; + crossHair.x = 320; + crossHair.y = 244; + crossHair _settext( "." ); + level._crosshair = crossHair; + + // setup "crosshair" + crossHair = _newhudelem(); + crossHair.location = 0; + crossHair.alignX = "center"; + crossHair.alignY = "bottom"; + crossHair.foreground = 1; + crossHair.fontScale = 2; + crossHair.sort = 20; + crossHair.alpha = 0; + crossHair.x = 320; + crossHair.y = 244; + crossHair setvalue( 0 ); + level._crosshair_value = crossHair; + + controler_hud_add( "helppm", 1, "^5Placed Models: ", undefined, level._spamed_models.size ); + controler_hud_add( "helpdensity", 2, "^5Spacing: ", undefined, level._spam_density_scale ); + controler_hud_add( "helpradius", 3, "^5Radius: ", undefined, level._spam_model_radius ); + controler_hud_add( "helpxy", 6, "^4X / ^3Y: ", undefined, level._spam_model_radius ); + controler_hud_add( "helpab", 7, "^2A / ^1B^7: ", " - " ); + controler_hud_add( "helplsrs", 8, "^8L^7 / R Stick: ", " - " ); + controler_hud_add( "helplbrb", 9, "^8L^7 / R Shoulder: ", " - " ); + controler_hud_add( "helpdpu", 10, "^8DPad U / ^7D: ", " - " ); + controler_hud_add( "helpdpl", 11, "^8DPad L / ^7R: ", " - " ); + controler_hud_add( "helpF", 17, "^8F: ^7( dump ) ^3map_source/" + level._script + "_modeldump.map", "" ); + + hint_buttons_main(); + + flag_set( "user_hud_active" ); +} + +hint_buttons_main() +{ + controler_hud_update_text( "helpxy", "^4Select Set Up ^7 / ^3Down" ); + controler_hud_update_text( "helpab", "^2Spacing Down ^7 / ^1up " ); + controler_hud_update_text( "helplsrs", "^8Radius Down ^7 / Up" ); + controler_hud_update_text( "helplbrb", "^8Remove ^7 / Place" ); + controler_hud_update_text( "helpdpl", "^8zOffset Clear ^7 / Set" ); + controler_hud_update_text( "helpdpu", "^8Rotation Clear ^7 / Set" ); +// controler_hud_update_text( "helpF", text ); + +} + +hint_buttons_zoffset() +{ + controler_hud_update_text( "helpxy", "^4 - ^7 / ^3 - " ); + controler_hud_update_text( "helpab", "^2Height Down ^7 / ^1Up " ); + controler_hud_update_text( "helplsrs", "^8 - ^7 / - " ); + controler_hud_update_text( "helplbrb", "^8 - ^7 / - " ); + controler_hud_update_text( "helpdpl", "^8 - ^7 / Set" ); + controler_hud_update_text( "helpdpu", "^8 - ^7 / - " ); + controler_hud_update_text( "helpF", " - " ); +} + +hint_buttons_rotation() +{ + controler_hud_update_text( "helpxy", "^4 - ^7 / ^3 - " ); + controler_hud_update_text( "helpab", "^2RotateOther Up ^7 / ^1Down " ); + controler_hud_update_text( "helplsrs", "^8 - ^7 / - " ); + controler_hud_update_text( "helplbrb", "^8 - ^7 / - " ); + controler_hud_update_text( "helpdpl", "^8 - ^7 / - " ); + controler_hud_update_text( "helpdpu", "^8Set ^7 / - " ); + controler_hud_update_text( "helpF", " - " ); +} + +setcurrentgroup( group ) +{ + flag_wait( "user_hud_active" ); + level._spam_model_current_group = group; + keys = getarraykeys( level._spam_model_group ); + index = 0; + div = int( level._spam_group_hudelems.size / 2 ); + for ( i = 0;i < keys.size;i++ ) + if ( keys[ i ] == group ) + { + index = i; + break; + } + + level._spam_group_hudelems[ div ] _settext( keys[ index ] ); + + for ( i = 1;i < level._spam_group_hudelems.size - div;i++ ) + { + if ( index - i < 0 ) + { + level._spam_group_hudelems[ div + i ] _settext( "." ); + continue; + } + level._spam_group_hudelems[ div + i ] _settext( keys[ index - i ] ); + } + + for ( i = 1;i < level._spam_group_hudelems.size - div;i++ ) + { + if ( index + i > keys.size - 1 ) + { + // -- -- + level._spam_group_hudelems[ div - i ] _settext( "." ); + continue; + } + level._spam_group_hudelems[ div - i ] _settext( keys[ index + i ] ); + } + + group = getcurrent_groupstruct(); + + level._bOrienttoplayeryrot = group.bOrienttoplayeryrot; + level._bPosedstyle = group.bPosedstyle; + level._spam_maxdist = group.maxdist; + level._spam_model_radius = group.radius; + level._hud_controler[ "helpradius" ].description setvalue( level._spam_model_radius ); + + level._spam_density_scale = group.density; + level._hud_controler[ "helpdensity" ].description setvalue( level._spam_density_scale ); +} + + +setgroup_up() +{ + index = undefined; + keys = getarraykeys( level._spam_model_group ); + for ( i = 0;i < keys.size;i++ ) + if ( keys[ i ] == level._spam_model_current_group ) + { + index = i + 1; + break; + } + if ( index == keys.size ) + return; + setcurrentgroup( keys[ index ] ); + while ( level._painter_player buttonpressed( "BUTTON_Y" ) ) + wait .05; +} + +setgroup_down() +{ + index = undefined; + keys = getarraykeys( level._spam_model_group ); + for ( i = 0;i < keys.size;i++ ) + if ( keys[ i ] == level._spam_model_current_group ) + { + index = i - 1; + break; + } + if ( index < 0 ) + return; + setcurrentgroup( keys[ index ] ); + while ( level._painter_player buttonpressed( "BUTTON_X" ) ) + wait .05; +} + +Add_Spammodel( group, model, bTreeOrient, bFacade, density, radius, maxdist, offsetheight, bPosedstyle, bOrienttoplayeryrot, angleoffset, modelusesprefab ) +{ + if ( !isdefined( level._spam_model_group[ group ] ) ) + { + struct = spawnstruct(); + level._spam_model_group[ group ] = struct; + level._spam_model_group[ group ].models = []; + } + + if( !isdefined( angleoffset ) ) + angleoffset = (0,0,0); + + level._spam_model_group[ group ].bFacade = bFacade; + level._spam_model_group[ group ].bTreeOrient = bTreeOrient; + level._spam_model_group[ group ].density = density; + level._spam_model_group[ group ].radius = radius; + level._spam_model_group[ group ].maxdist = maxdist; + level._spam_model_group[ group ].bPosedstyle = bPosedstyle; + level._spam_model_group[ group ].bOrienttoplayeryrot = bOrienttoplayeryrot; + + if( !isdefined( level._spam_model_group[ group ].angleoffset ) ) + level._spam_model_group[ group ].angleoffset = []; + level._spam_model_group[ group ].angleoffset[ model ] = angleoffset; + + if( !isdefined( level._spam_model_group[ group ].heightoffset ) ) + level._spam_model_group[ group ].heightoffset = []; + level._spam_model_group[ group ].heightoffset[ model ] = offsetheight; + + if( !isdefined( level._spam_model_group[ group ].modelusesprefab ) ) + level._spam_model_group[ group ].modelusesprefab = []; + level._spam_model_group[ group ].modelusesprefab[ model ] = modelusesprefab; + + level._spam_model_group[ group ].models[ level._spam_model_group[ group ].models.size ] = model; +} + + +playerInit() +{ + level._painter_max = 700; + level._painter_player takeAllWeapons(); + + flag_wait( "user_hud_active" ); + while ( 1 ) + { + trace = player_view_trace(); + draw_placement_circle( trace ); + if ( level._painter_player buttonpressed( "f" ) ) + dump_models(); + if ( level._painter_player buttonpressed( "DPAD_UP" ) ) + customrotation_mode( trace, "DPAD_UP" ); + else if ( level._painter_player buttonpressed( "DPAD_DOWN" ) ) + customrotation_mode_off(); + else if ( level._painter_player buttonpressed( "DPAD_RIGHT" ) ) + customheight_mode( trace, "DPAD_RIGHT" ); + else if ( level._painter_player buttonpressed( "DPAD_LEFT" ) ) + customheight_mode_off(); + else if ( level._painter_player buttonpressed( "BUTTON_X" ) ) + setgroup_down(); + else if ( level._painter_player buttonpressed( "BUTTON_Y" ) ) + setgroup_up(); + else if ( level._painter_player buttonpressed( "BUTTON_LSTICK" ) ) + spam_model_circlescale( trace, -1 ); + else if ( level._painter_player buttonpressed( "BUTTON_RSTICK" ) ) + spam_model_circlescale( trace, 1 ); + else if ( level._painter_player buttonpressed( "BUTTON_A" ) ) + spam_model_densityscale( trace, -1 ); + else if ( level._painter_player buttonpressed( "BUTTON_B" ) ) + spam_model_densityscale( trace, 1 ); + else + { + if ( level._painter_player buttonpressed( "BUTTON_LSHLDR" ) ) + spam_model_erase( trace ); + if ( level._painter_player buttonpressed( "BUTTON_RSHLDR" ) ) + thread spam_model_place( trace );// threaded for delay + } + level notify( "clear_previews" ); + wait .05; + hud_update_placed_model_count(); + } +} + +customheight_mode_off() +{ + level._spam_models_isCustomheight = false; + hint_buttons_main(); +} + +customheight_mode( trace, button ) +{ + if ( trace[ "fraction" ] == 1 ) + return; + + while ( level._painter_player buttonpressed( button ) ) + wait .05; + + level._spam_models_isCustomheight = true; + hint_buttons_zoffset(); + models = []; + models = spam_models_atcircle( trace, false, true ); + + inc = 2; + dir = 1; + + origin = trace[ "position" ]; + while ( !level._painter_player buttonpressed( button ) ) + { + height = level._spam_models_customheight; + if ( level._painter_player buttonpressed( "BUTTON_A" ) ) + dir = -1; + else if ( level._painter_player buttonpressed( "BUTTON_B" ) ) + dir = 1; + else + dir = 0; + height += dir * inc; + if ( height == 0 ) + height += dir * inc; + level._spam_models_customheight = height; + + array_thread( models, ::customheight_mode_offsetmodels, trace ); + draw_placement_circle( trace, ( 1, 1, 1 ) ); + + wait .05; + } + array_thread( models, ::deleteme ); + hint_buttons_main(); + while ( level._painter_player buttonpressed( button ) ) + wait .05; +} + +customheight_mode_offsetmodels( trace ) +{ + self.origin = self.orgorg + ( trace[ "normal" ] * level._spam_models_customheight ); +} + +customrotation_mode_off() +{ + level._spam_models_isCustomrotation = false; + hint_buttons_main(); +} + +customrotation_mode( trace, button ) +{ + if ( trace[ "fraction" ] == 1 ) + return; + + while ( level._painter_player buttonpressed( button ) ) + wait .05; + + hint_buttons_rotation(); + + level._spam_models_isCustomrotation = true; + level._spam_models_customrotation = level._painter_player getplayerangles(); + models = []; + models = spam_models_atcircle( trace, true, true ); + + otherangle = 0; + otherangleinc = 1; + dir = 0; + + while ( !level._painter_player buttonpressed( button ) ) + { + dir = 0; + if ( level._painter_player buttonpressed( "BUTTON_A" ) ) + dir = -1; + else if ( level._painter_player buttonpressed( "BUTTON_B" ) ) + dir = 1; + otherangle += dir * otherangleinc; + if ( otherangle > 360 ) + otherangle = 1; + if ( otherangle < 0 ) + otherangle = 359; + draw_placement_circle( trace, ( 0, 0, 1 ) ); + level._spam_models_customrotation = level._painter_player getplayerangles(); + level._spam_models_customrotation += ( 0, 0, otherangle ); + for ( i = 0;i < models.size;i++ ) + models[ i ].angles = level._spam_models_customrotation; + wait .05; + } + + hint_buttons_main(); + + while ( level._painter_player buttonpressed( button ) ) + wait .05; + + for ( i = 0;i < models.size;i++ ) + models[ i ] thread deleteme(); + +} + +deleteme() +{ + self delete(); +} + +spam_model_clearcondition() +{ + self endon( "death" ); + level waittill( "clear_previews" ); + level._previewmodels = array_remove( level._previewmodels, self ); + self delete(); +} + +crosshair_fadetopoint() +{ + level notify( "crosshair_fadetopoint" ); + level endon( "crosshair_fadetopoint" ); + wait 2; + level._crosshair_value.alpha = 0; + level._crosshair.alpha = 1; +} + +spam_model_circlescale( trace, dir ) +{ + if ( gettime() - level._spam_model_circlescale_lasttime > 60 ) + level._spam_model_circlescale_accumtime = 0; + + level._spam_model_circlescale_accumtime += .05; + + if ( level._spam_model_circlescale_accumtime < .5 ) + inc = 2; + else + inc = level._spam_model_circlescale_accumtime / .3; + + radius = level._spam_model_radius; + radius += dir * inc; + if ( radius > 0 ) + level._spam_model_radius = radius; + + level._hud_controler[ "helpradius" ].description setvalue( level._spam_model_radius ); + + level._spam_model_circlescale_lasttime = gettime(); +} + +spam_model_densityscale( trace, dir ) +{ + // ghetto hack here. density scale used for distance on floating model types + inc = 2; + scale = level._spam_density_scale; + scale += dir * inc; + if ( scale > 0 ) + level._spam_density_scale = scale; + + + level._crosshair_value.alpha = 1; + level._crosshair.alpha = 0; + + level._crosshair_value setvalue( level._spam_density_scale ); + level._hud_controler[ "helpdensity" ].description setvalue( level._spam_density_scale ); + + thread crosshair_fadetopoint(); +} + +draw_placement_circle( trace, coloroverride ) +{ + if ( !isdefined( coloroverride ) ) + coloroverride = ( 0, 1, 0 ); + if ( trace[ "fraction" ] == 1 ) + return; + // angles = vectortoangles( anglestoup( vectortoangles( trace[ "normal" ] ) ) ); + angles = vectortoangles( trace[ "normal" ] ); + origin = trace[ "position" ]; + radius = level._spam_model_radius; + // plot_circle( origin, radius, angles, color, circleres ); + plot_circle( origin, radius, angles, coloroverride, 40, level._spam_model_radius ); + + if ( level._spam_models_isCustomrotation ) + draw_axis( origin, level._spam_models_customrotation ); + if ( level._spam_models_isCustomheight ) + draw_arrow( origin, origin + ( trace[ "normal" ] * level._spam_models_customheight ), ( 1, 1, 1 ) ); +} + +player_view_trace() +{ + maxdist = level._spam_maxdist; + traceorg = level._painter_player geteye(); + return bullettrace( traceorg, traceorg + ( anglestoforward( level._painter_player getplayerangles() ) * maxdist ), 0, self ); +} + +Orienttoplayeryrot() +{ + self addyaw( level._painter_player getplayerangles()[ 1 ] - flat_angle( self.angles )[ 1 ] ); + // self.angles = ( x, y, z ); +} + +getcurrent_groupstruct() +{ + return level._spam_model_group[ level._spam_model_current_group ]; +} + +orient_model() +{ + group = getcurrent_groupstruct(); + + if ( level._spam_models_isCustomrotation ) + { + self.angles = level._spam_models_customrotation; + return; + } + + if ( level._bPosedstyle ) + self.angles = level._painter_player getplayerangles(); + + if ( level._bOrienttoplayeryrot ) + self Orienttoplayeryrot(); + + if ( group.bTreeOrient ) + self.angles = flat_angle( self.angles ); + + if ( ! level._bOrienttoplayeryrot && !level._bPosedstyle ) + self addyaw( randomint( 360 ) ); + + if ( group.bFacade ) + { + self.angles = flat_angle( vectortoangles( self.origin - level._painter_player geteye() ) ); + self addyaw( 90 ); + + } + + assert( isdefined( group.angleoffset ) && isdefined( group.angleoffset[ self.model] ) ); + + self addroll( group.angleoffset[self.model][ 0 ] ); + self addpitch( group.angleoffset[self.model][ 1 ] ); + self addyaw( group.angleoffset[self.model][ 2 ] ); + + + +} + +spam_model_place( trace ) +{ + if ( level._spaming_models ) + return; + if ( trace[ "fraction" ] == 1 && !level._bPosedstyle ) + return; + level._spaming_models = true; + models = spam_models_atcircle( trace, true ); + level._spamed_models = array_combine( level._spamed_models, models ); + level._spaming_models = false; +} + +getrandom_spammodel() +{ + models = level._spam_model_group[ level._spam_model_current_group ].models; + return models[ randomint( models.size ) ]; +} + +spam_models_atcircle( trace, bRandomrotation, bForcedSpam ) +{ + if ( !isdefined( bForcedSpam ) ) + bForcedSpam = false; + models = []; + incdistance = level._spam_density_scale; + radius = level._spam_model_radius; + incs = int( radius / incdistance ) * 2; + startpoint = 0; + traceorg = trace[ "position" ]; + angles = vectortoangles( trace[ "normal" ] ); + if ( bRandomrotation ) + angles += ( 0, randomfloat( 360 ), 0 ); + xvect = vectornormalize( anglestoright( angles ) ); + yvect = vectornormalize( anglestoup( angles ) ); + startpos = traceorg; + startpos -= ( xvect * radius ); + startpos -= ( yvect * radius ); + startpos += ( xvect * incdistance ); + startpos += ( yvect * incdistance ); + + modelpos = startpos; + // special for when circle is too small for current density to place anything. Just place one in the center.. + if ( incs == 0 || level._bPosedstyle ) + { + if ( !bForcedSpam ) + if ( is_too_dense( traceorg ) ) + return models; + if ( !bForcedSpam ) + if ( level._spamed_models.size + models.size > level._painter_max ) + return models; + + getmodel = getrandom_spammodel(); + models[ 0 ] = spam_modelattrace( trace, getmodel ); + models[ 0 ] orient_model(); + + return models; + } + + countourtrace = []; + for ( x = startpoint;x < incs;x++ ) + for ( y = startpoint;y < incs;y++ ) + { + if ( !bForcedSpam ) + if ( level._spamed_models.size + models.size > level._painter_max ) + return models;; + modelpos = startpos; + modelpos += ( xvect * x * incdistance ); + modelpos += ( yvect * y * incdistance ); + if ( distance( modelpos, traceorg ) > radius ) + continue; +// if ( !bForcedSpam ) + countourtrace = contour_point( modelpos, angles, level._spam_model_radius ); + + if ( countourtrace[ "fraction" ] == 1 ) + continue; + if ( is_too_dense( countourtrace[ "position" ] ) ) + continue; + getmodel = getrandom_spammodel(); + + model = spam_modelattrace( countourtrace, getmodel ); + model orient_model(); + models[ models.size ] = model; + + } + return models; +} + +is_too_dense( testorg ) +{ + // going backwards will be faster + for ( i = level._spamed_models.size - 1; i >= 0; i -- ) + if ( distance( level._spamed_models[ i ].orgorg, testorg ) < ( level._spam_density_scale - 1 ) ) + return true; + return false; +} + +get_player() +{ + return getentarray( "player", "classname" )[ 0 ]; +} + +spam_modelattrace( trace, getmodel ) +{ + model = spawn( "script_model", level._painter_player.origin ); + model setmodel( getmodel ); + model notsolid(); + model.origin = trace[ "position" ]; + model.angles = vectortoangles( trace[ "normal" ] ); + model addpitch( 90 ); + model.orgorg = model.origin; + group = getcurrent_groupstruct(); + if ( level._spam_models_isCustomheight ) + model.origin += ( trace[ "normal" ] * level._spam_models_Customheight ); + + group = getcurrent_groupstruct(); + if( isdefined( group.heightoffset[ getmodel ] ) ) + model.origin += ( trace[ "normal" ] * group.heightoffset[ getmodel ] ); + if( isdefined( group.modelusesprefab[ getmodel ] ) ) + model.modelusesprefab = group.modelusesprefab[ getmodel ]; + + return model; +} + +contour_point( origin, angles, height ) +{ + offset = height; + vect = anglestoforward( angles ); + destorg = origin + ( vect * offset ); + targetorg = origin + ( vect * - 1 * offset ); + return bullettrace( destorg, targetorg, 0, level._painter_player ); +} + +plot_circle( origin, radius, angles, color, circleres, contourdepth ) +{ + if ( !isdefined( color ) ) + color = ( 0, 1, 0 ); + if ( !isdefined( circleres ) ) + circleres = 16; + hemires = circleres / 2; + circleinc = 360 / circleres; + circleres++ ; + plotpoints = []; + rad = 0; + plotpoints = []; + rad = 0.000; + for ( i = 0;i < circleres;i++ ) + { + baseorg = origin + ( anglestoup( ( angles + ( 0, 0, rad ) ) ) * radius ); + point = contour_point( baseorg, angles, level._spam_model_radius ); + if ( point[ "fraction" ] != 1 ) + plotpoints[ plotpoints.size ] = point[ "position" ]; + rad += circleinc; + } + plot_points( plotpoints, color[ 0 ], color[ 1 ], color[ 2 ] ); + plotpoints = []; +} + +spam_model_erase( trace ) +{ + traceorg = trace[ "position" ]; + keepmodels = []; + deletemodels = []; + for ( i = 0;i < level._spamed_models.size;i++ ) + { + if ( distance( level._spamed_models[ i ].orgorg, traceorg ) > level._spam_model_radius ) + keepmodels[ keepmodels.size ] = level._spamed_models[ i ]; + else + deletemodels[ deletemodels.size ] = level._spamed_models[ i ]; + } + level._spamed_models = keepmodels; + + for ( i = 0;i < deletemodels.size;i++ ) + deletemodels[ i ] delete(); +} + +dump_models() +{ + /# + if ( ! level._spamed_models.size ) + return; + fileprint_launcher_start_file(); + fileprint_map_start(); + for ( i = 0;i < level._spamed_models.size;i++ ) + { + origin = fileprint_radiant_vec( level._spamed_models[ i ].origin );// convert these vectors to mapfile keypair format + angles = fileprint_radiant_vec( level._spamed_models[ i ].angles ); + + fileprint_map_entity_start(); + if( isdefined ( level._spamed_models[ i ].modelusesprefab ) && level._spamed_models[ i ].modelusesprefab ) + { + fileprint_map_keypairprint( "classname", "misc_prefab" ); + fileprint_map_keypairprint( "model", "prefabs/misc_models/" + level._spamed_models[ i ].model + ".map" ); + } + else + { + fileprint_map_keypairprint( "classname", "misc_model" ); + fileprint_map_keypairprint( "model", level._spamed_models[ i ].model ); + } + fileprint_map_keypairprint( "origin", origin ); + fileprint_map_keypairprint( "angles", angles ); + fileprint_map_keypairprint( "spammed_model", level._spam_model_current_group ); + fileprint_map_entity_end(); + } + map_path = level._script+"_modeldump.map"; + if( !fileprint_launcher_end_file( "/map_source/"+map_path,false ) ) + return; + launcher_write_clipboard( map_path ); + array_thread( level._spamed_models, ::deleteme ); + level._spamed_models = []; +#/ +} + +draw_axis( org, angles ) +{ + range = 32; + forward = range * anglestoforward( angles ); + right = range * anglestoright( angles ); + up = range * anglestoup( angles ); + line( org, org + forward, ( 1, 0, 0 ), 1 ); + line( org, org + up, ( 0, 1, 0 ), 1 ); + line( org, org + right, ( 0, 0, 1 ), 1 ); +} + +_newhudelem() +{ + if ( !isdefined( level._scripted_elems ) ) + level._scripted_elems = []; + elem = newhudelem(); + level._scripted_elems[ level._scripted_elems.size ] = elem; + return elem; +} + +_settext( text ) +{ + self.realtext = text; + self settext( "_" ); + self thread _clearalltextafterhudelem(); + sizeofelems = 0; + foreach ( elem in level._scripted_elems ) + { + if ( isdefined( elem.realtext ) ) + { + sizeofelems += elem.realtext.size; + elem settext( elem.realtext ); + } + } + println( "SIze of elems: " + sizeofelems ); +} + +controler_hud_add( identifier, inc, initial_text, initial_description_text, initial_value ) +{ + startx = 520; + if ( is_mp() ) + startx = 630; + starty = 120; + space = 18; + basealpha = .8; + denradoffset = 20; + descriptionscale = 1.4; + if ( !isdefined( initial_text ) ) + initial_text = ""; + + if ( !isdefined( level._hud_controler ) || !isdefined( level._hud_controler[ identifier ] ) ) + { + level._hud_controler[ identifier ] = _newhudelem(); + description = _newhudelem(); + } + else + description = level._hud_controler[ identifier ].description; + + level._hud_controler[ identifier ].location = 0; + level._hud_controler[ identifier ].alignX = "right"; + level._hud_controler[ identifier ].alignY = "middle"; + level._hud_controler[ identifier ].foreground = 1; + level._hud_controler[ identifier ].fontscale = 1.5; + level._hud_controler[ identifier ].sort = 20; + level._hud_controler[ identifier ].alpha = basealpha; + level._hud_controler[ identifier ].x = startx + denradoffset; + level._hud_controler[ identifier ].y = starty + ( inc * space ); + level._hud_controler[ identifier ] _settext( initial_text ); + level._hud_controler[ identifier ].base_button_text = initial_text; + + description.location = 0; + description.alignX = "left"; + description.alignY = "middle"; + description.foreground = 1; + description.fontscale = descriptionscale; + description.sort = 20; + description.alpha = basealpha; + description.x = startx + denradoffset; + description.y = starty + ( inc * space ); + if ( isdefined( initial_value ) ) + description setvalue( initial_value ); + if ( isdefined( initial_description_text ) ) + description _settext( initial_description_text ); + level._hud_controler[ identifier ].description = description; +} + +controler_hud_update_text( hudid, text ) +{ + if ( is_mp() ) + { + level._hud_controler[ hudid ] _settext( level._hud_controler[ hudid ].base_button_text + text ); + level._hud_controler[ hudid ].description _settext( "" ); + } + else + level._hud_controler[ hudid ].description _settext( text ); + + + +} + +controler_hud_update_button( hudid, text ) +{ + level._hud_controler[ hudid ] _settext( text ); +} + + +_clearalltextafterhudelem() +{ + if ( level._clearalltextafterhudelem ) + return; + level._clearalltextafterhudelem = true; + self clearalltextafterhudelem(); + wait .05; + level._clearalltextafterhudelem = false; + +} + +is_mp() +{ + return issubstr( level._script, "mp_" ); +} \ No newline at end of file diff --git a/common_scripts/_pipes.gsc b/common_scripts/_pipes.gsc new file mode 100644 index 0000000..5a78eec --- /dev/null +++ b/common_scripts/_pipes.gsc @@ -0,0 +1,323 @@ +#include common_scripts\utility; + +////////////////////////////////////////////////////////////////////////////// +// CONSTANTS // +////////////////////////////////////////////////////////////////////////////// +level_limit_pipe_fx = 8; +max_fires_from_entity = 4; +level_pipe_fx_chance = 33; + + +////////////////////////////////////////////////////////////////////////////// +// LOGIC // +////////////////////////////////////////////////////////////////////////////// +main() +{ + level._pipe_fx_time = 25; + pipes = GetEntArray( "pipe_shootable", "targetname" ); + if ( !pipes.size ) + return; + level._pipes = SpawnStruct(); + level._pipes.num_pipe_fx = 0; + + pipes thread precacheFX(); + pipes thread methodsInit(); + + waittillframeend;// insure that structs are initialized + array_thread( pipes, ::pipesetup ); +} + +pipesetup() +{ + self SetCanDamage( true ); + self SetCanRadiusDamage( false ); // optimization + self.pipe_fx_array = []; + + node = undefined; + + if ( IsDefined( self.target ) ) + { + node = getstruct( self.target, "targetname" ); + self.A = node.origin; + vec = AnglesToForward( node.angles ); + vec = vector_multiply( vec, 128 ); + self.B = self.A + vec; + } + else + { + vec = AnglesToForward( self.angles ); + vec1 = vector_multiply( vec, 64 ); + self.A = self.origin + vec1; + vec1 = vector_multiply( vec, -64 ); + self.B = self.origin + vec1; + } + + self thread pipe_wait_loop(); +} + +pipe_wait_loop() +{ + P = ( 0, 0, 0 );// just to initialize P as a vector + + hasTakenDamage = false; + remaining = max_fires_from_entity; + + while ( 1 ) + { + self waittill( "damage", damage, other, direction_vec, P, type ); + + // random so we don't get so many fx, but the very first time is guarenteed + if ( hasTakenDamage ) + { + if ( randomint( 100 ) <= level_pipe_fx_chance ) + continue; + } + hasTakenDamage = true; + + result = self pipe_logic( direction_vec, P, type, other ); + if ( result ) + remaining--; + + if ( remaining <= 0 ) + break; + } + + self SetCanDamage( false ); +} + +pipe_logic( direction_vec, P, type, damageOwner ) +{ + if ( level._pipes.num_pipe_fx > level_limit_pipe_fx ) + return false; + + if ( !isDefined( level._pipes._pipe_methods[ type ] ) ) + P = self pipe_calc_nofx( P, type ); + else + P = self [[ level._pipes._pipe_methods[ type ] ]]( P, type ); + + if ( !isdefined( P ) ) + return false; + + if ( IsDefined( damageOwner.classname ) && damageOwner.classname == "worldspawn" ) + return false; + + foreach ( value in self.pipe_fx_array ) + { + if ( DistanceSquared( P, value.origin ) < 25 ) + return false; + } + + //calculate the vector derived from the center line of our pipe and the point of damage + vec = VectorFromLineToPoint( self.A, self.B, P ); + self thread pipefx( P, vec, damageOwner ); + return true; +} + +pipefx( P, vec, damageOwner ) +{ + time = level._pipes.fx_time[ self.script_noteworthy ] ; + intervals = Int( level._pipe_fx_time / time );// loops for 25 seconds + hitsnd = level._pipes._sound[ self.script_noteworthy + "_hit" ]; + loopsnd = level._pipes._sound[ self.script_noteworthy + "_loop" ]; + endsnd = level._pipes._sound[ self.script_noteworthy + "_end" ]; + + snd = Spawn( "sound_emitter", P ); + snd Hide(); + snd PlaySound( hitsnd ); + snd PlayLoopSound( loopsnd ); + self.pipe_fx_array[ self.pipe_fx_array.size ] = snd; + + level._pipes.num_pipe_fx++; + + if ( isSP() || self.script_noteworthy != "steam" ) + self thread pipe_damage( P, vec, damageOwner, snd ); + + //do it once without checking for newer fx being played ( we're the newest ) + PlayFX( level._pipes._effect[ self.script_noteworthy ], P, vec ); + wait time; + intervals--; + + //now check for other fx and rest of intervals + while ( level._pipes.num_pipe_fx <= level_limit_pipe_fx && intervals > 0 ) + { + PlayFX( level._pipes._effect[ self.script_noteworthy ], P, vec ); + wait time; + intervals--; + } + snd PlaySound( endsnd ); + wait( .5 ); + snd StopLoopSound( loopsnd ); + snd Delete(); + self.pipe_fx_array = array_removeUndefined( self.pipe_fx_array ); + + level._pipes.num_pipe_fx--; +} + +pipe_damage( P, vec, damageOwner, fx ) +{ + if ( !allow_pipe_damage() ) + return; + + fx endon( "death" ); + + origin = fx.origin + vector_multiply( VectorNormalize( vec ), 40 ); + dmg = level._pipes._dmg[ self.script_noteworthy ]; + + while ( 1 ) + { + // do not pass damage owner if they have disconnected before the barrels explode.. the barrels? + if ( !isdefined( self.damageOwner ) ) + { + // MOD_TRIGGER_HURT so they dont do dirt on the player's screen + self RadiusDamage( origin, 36, dmg, dmg * 0.75, undefined, "MOD_TRIGGER_HURT" ); + } + else + { + // MOD_TRIGGER_HURT so they dont do dirt on the player's screen + self RadiusDamage( origin, 36, dmg, dmg * 0.75, damageOwner, "MOD_TRIGGER_HURT" ); + } + + wait( 0.4 ); + } +} + +allow_pipe_damage() +{ + if( !isSP() ) + return false; + + if ( !isDefined( level._pipesDamage ) ) + return true; + + return ( level._pipesDamage ); +} + +////////////////////////////////////////////////////////////////////////////// +// CALCULATIONS / SETUP // +////////////////////////////////////////////////////////////////////////////// + +methodsInit() +{ + level._pipes._pipe_methods = []; + level._pipes._pipe_methods[ "MOD_UNKNOWN" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_PISTOL_BULLET" ] = ::pipe_calc_ballistic; + level._pipes._pipe_methods[ "MOD_RIFLE_BULLET" ] = ::pipe_calc_ballistic; + level._pipes._pipe_methods[ "MOD_GRENADE" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_GRENADE_SPLASH" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_PROJECTILE" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_PROJECTILE_SPLASH" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_TRIGGER_HURT" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_EXPLOSIVE" ] = ::pipe_calc_splash; + level._pipes._pipe_methods[ "MOD_EXPLOSIVE_BULLET" ] = ::pipe_calc_splash; +} + +pipe_calc_ballistic( P, type ) +{ + return P; +} + +pipe_calc_splash( P, type ) +{ + vec = VectorNormalize( VectorFromLineToPoint( self.A, self.B, P ) ); + P = PointOnSegmentNearestToPoint( self.A, self.B, P ); + return( P + vector_multiply( vec, 4 ) ); +} + +pipe_calc_nofx( P, type ) +{ + return undefined; +} + +precacheFX() +{ + steam = false; + fire = false; + fire_short = false; + steam_moon = false; + fire_moon = false; + foreach ( value in self ) + { + if ( value.script_noteworthy == "water" ) + value.script_noteworthy = "steam"; + + if ( value.script_noteworthy == "steam" ) + { + value willNeverChange(); + steam = true; + } + else if ( value.script_noteworthy == "fire" ) + { + value willNeverChange(); + fire = true; + } + else if ( value.script_noteworthy == "fire_short" ) + { + value willNeverChange(); + fire_short = true; + } + else if ( value.script_noteworthy == "steam_moon" ) + { + value willNeverChange(); + steam_moon = true; + } + else if ( value.script_noteworthy == "fire_moon" ) + { + value willNeverChange(); + fire_moon = true; + } + else + { + println( "Unknown 'pipe_shootable' script_noteworthy type '%s'\n", value.script_noteworthy ); + } + } + + if ( steam ) + { + level._pipes._effect[ "steam" ] = LoadFX( "impacts/pipe_steam" ); + level._pipes._sound[ "steam_hit" ] = "mtl_steam_pipe_hit"; + level._pipes._sound[ "steam_loop" ] = "mtl_steam_pipe_hiss_loop"; + level._pipes._sound[ "steam_end" ] = "mtl_steam_pipe_hiss_loop_end"; + level._pipes.fx_time[ "steam" ] = 3; + level._pipes._dmg[ "steam" ] = 5; + } + + if ( fire ) + { + level._pipes._effect[ "fire" ] = LoadFX( "impacts/pipe_fire" ); + level._pipes._sound[ "fire_hit" ] = "mtl_gas_pipe_hit"; + level._pipes._sound[ "fire_loop" ] = "mtl_gas_pipe_flame_loop"; + level._pipes._sound[ "fire_end" ] = "mtl_gas_pipe_flame_end"; + level._pipes.fx_time[ "fire" ] = 3; + level._pipes._dmg[ "fire" ] = 5; + } + + if ( fire_short ) + { + level._pipes._effect[ "fire_short" ] = LoadFX( "nx/impacts/nx_pipe_fire" ); + level._pipes._sound[ "fire_short_hit" ] = "mtl_gas_pipe_hit"; + level._pipes._sound[ "fire_short_loop" ] = "mtl_gas_pipe_flame_loop"; + level._pipes._sound[ "fire_short_end" ] = "mtl_gas_pipe_flame_end"; + level._pipes.fx_time[ "fire_short" ] = 16; + level._pipes._dmg[ "fire_short" ] = 5; + } + + if ( steam_moon ) + { + level._pipes._effect[ "steam_moon" ] = LoadFX( "nx/lunar/impacts/nx_lunar_pipe_steam" ); + level._pipes._sound[ "steam_moon_hit" ] = "mtl_steam_pipe_hit"; + level._pipes._sound[ "steam_moon_loop" ] = "mtl_steam_pipe_hiss_loop"; + level._pipes._sound[ "steam_moon_end" ] = "mtl_steam_pipe_hiss_loop_end"; + level._pipes.fx_time[ "steam_moon" ] = 5; + level._pipes._dmg[ "steam_moon" ] = 10; + } + + if ( fire_moon ) + { + level._pipes._effect[ "fire_moon" ] = LoadFX( "nx/lunar/impacts/nx_lunar_pipe_fire" ); + level._pipes._sound[ "fire_moon_hit" ] = "mtl_gas_pipe_hit"; + level._pipes._sound[ "fire_moon_loop" ] = "mtl_gas_pipe_flame_loop"; + level._pipes._sound[ "fire_moon_end" ] = "mtl_gas_pipe_flame_end"; + level._pipes.fx_time[ "fire_moon" ] = 5; + level._pipes._dmg[ "fire_moon" ] = 10; + } +} \ No newline at end of file diff --git a/common_scripts/_portable_radar.gsc b/common_scripts/_portable_radar.gsc new file mode 100644 index 0000000..cb963eb --- /dev/null +++ b/common_scripts/_portable_radar.gsc @@ -0,0 +1,175 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +setPortableRadar() +{ + println( "called setPortableRadar" ); + + self _giveWeapon( "portable_radar_mp", 0 ); + self giveStartAmmo( "portable_radar_mp" ); + + self thread monitorPortableRadarUse(); +} + +unsetPortableRadar() +{ + self notify( "end_monitorPortableRadarUse" ); +} + +deletePortableRadar( portable_radar ) +{ + if ( !isDefined( portable_radar ) ) + return; + + portable_radar notify( "death" ); + portable_radar Delete(); + + self.deployedPortableRadar = undefined; +} + +monitorPortableRadarUse() +{ + self endon ( "death" ); + self endon ( "disconnect" ); + level endon ( "game_ended" ); + + for ( ;; ) + { + // grenade is the entity spawned by the G_FireGrenade() since we want this to be + // script controlled, we won't actually use this entity + self waittill( "grenade_fire", grenade, weapName ); + + if ( weapName != "portable_radar_mp" ) + continue; + + println( "A portable radar has been fired" ); + + if( isDefined( self.deployedPortableRadar ) ) + { + println( "Deleting the other portable radar you have deployed" ); + deletePortableRadar( self.deployedPortableRadar ); + } + + grenade waittill( "missile_stuck" ); + println( "Portable radar is has missile_stuck" ); + + GroundPosition = grenade.origin; + + grenade Delete(); + + portable_radar = spawn( "script_model", GroundPosition ); + portable_radar.health = 100; + portable_radar.team = self.team; + portable_radar.owner = self; + + portable_radar setCanDamage( true ); + + portable_radar makePortableRadar( self ); + portable_radar portableRadarSetup( self ); + portable_radar thread maps\mp\gametypes\_weapons::createBombSquadModel( "weapon_c4_bombsquad", "tag_origin", self ); + + self.deployedPortableRadar = portable_radar; + return; + } +} + +portableRadarSetup( owner ) +{ + // JCC temp until we get our model + self setModel( "weapon_c4" ); + + // setup icons for item so friendlies see it + if ( level._teamBased ) + self maps\mp\_entityheadIcons::setTeamHeadIcon( self.team , (0,0,20) ); + else + self maps\mp\_entityheadicons::setPlayerHeadIcon( owner, (0,0,20) ); + + self thread portableRadarDamageListener( owner ); + self thread portableRadarUseListener( owner ); + owner thread portableRadarWatchOwner( self ); + self thread portableRadarBeepSounds(); +} + +portableRadarWatchOwner( portable_radar ) +{ + portable_radar endon( "death" ); + level endon ( "game_ended" ); + + self waittill_any( "disconnect", "joined_team", "joined_spectators", "death" ); + + level thread deletePortableRadar( portable_radar ); +} + +portableRadarBeepSounds() +{ + self endon( "death" ); + level endon ( "game_ended" ); + + for ( ;; ) + { + wait ( 2.0 ); + self playSound( "sentry_gun_beep" ); + } +} + +portableRadarDamageListener( owner ) +{ + self endon ( "death" ); + + // use a health buffer to prevent dying to friendly fire + healthBuffer = 20000; + self.health += healthbuffer; + + for ( ;; ) + { + self waittill ( "damage", amount, attacker ); + + if ( level._teambased && isDefined( attacker.team ) && attacker.team == self.team ) + { + self.health += amount; + continue; + } + + if ( self.health - healthbuffer < 0 ) + { + if ( isDefined( owner ) && attacker != owner ) + { + // JCC commented out + //attacker notify ( "destroyed_insertion", owner ); + attacker notify( "destroyed_explosive" ); // count towards SitRep Pro challenge + + // JCC commented out + //owner thread leaderDialogOnPlayer( "ti_destroyed" ); + } + + // JCC temp playing sounds and effects from other weapons until we have the right ones + self playsound( "sentry_explode" ); + self.c4DeathEffect = playFX( level.c4Death, self.origin ); + attacker thread deletePortableRadar( self ); + } + } +} + +portableRadarUseListener( owner ) +{ + self endon ( "death" ); + level endon ( "game_ended" ); + owner endon ( "disconnect" ); + + self setCursorHint( "HINT_NOICON" ); + self setHintString( &"MP_PICKUP_PORTABLE_RADAR" ); + self setSelfUsable( owner ); + + for ( ;; ) + { + self waittill ( "trigger", player ); + + player playLocalSound( "scavenger_pack_pickup" ); + + // give item to user (only if they haven't restocked from scavenger pickup since dropping) + if ( player getAmmoCount( "portable_radar_mp" ) == 0 ) + player setPortableRadar(); + + player thread deletePortableRadar( self ); + } +} \ No newline at end of file diff --git a/common_scripts/testscripts.gsc b/common_scripts/testscripts.gsc new file mode 100644 index 0000000..b009dbf --- /dev/null +++ b/common_scripts/testscripts.gsc @@ -0,0 +1,93 @@ +// note: Test code added to this file should not be checked in! + +//******************************************************************* +// * +// * +//******************************************************************* +testscript0() +{ + /# + IPrintLn( "testscript0 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript1() +{ + /# + IPrintLn( "testscript1 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript2() +{ + /# + IPrintLn( "testscript2 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript3() +{ + /# + IPrintLn( "testscript3 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript4() +{ + /# + IPrintLn( "testscript4 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript5() +{ + /# + IPrintLn( "testscript5 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript6() +{ + /# + IPrintLn( "testscript6 executed on gentity " + self GetEntNum() ); + #/ +} + +//******************************************************************* +// * +// * +//******************************************************************* +testscript7() +{ + /# + IPrintLn( "testscript7 executed on gentity " + self GetEntNum() ); + #/ +} + + + + \ No newline at end of file diff --git a/common_scripts/utility.gsc b/common_scripts/utility.gsc new file mode 100644 index 0000000..b2aeb50 --- /dev/null +++ b/common_scripts/utility.gsc @@ -0,0 +1,4111 @@ +scriptPrintln( channel, msg ) +{ + setprintchannel( channel ); + println( msg ); + setprintchannel( "script" ); +} + +debugPrintln( channel, msg ) +{ + setprintchannel( "script_debug" ); + println( msg ); + setprintchannel( "script" ); +} + +draw_debug_line( start, end, timer ) +{ + for ( i = 0;i < timer * 20;i++ ) + { + line( start, end, ( 1, 1, 0.5 ) ); + wait( 0.05 ); + } +} + +waittillend( msg ) +{ + self waittillmatch( msg, "end" ); +} + +/* +============= +///ScriptDocBegin +"Name: noself_func( , , , , )" +"Summary: Runs a function from level.func, if it exists. Stand alone, doesn't run on anything. Useful for common scripts where a code function may not exist in one codebase or the other." +"Module: Utility" +"CallOn: An entity" +"MandatoryArg: : String reference to level.func array." +"OptionalArg: : " +"OptionalArg: : " +"OptionalArg: : " +"OptionalArg: : " +"Example: noself_func( "setsaveddvar", "r_spotlightbrightness", maxVal );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +noself_func( func, parm1, parm2, parm3, parm4 ) +{ + if ( !isdefined( level._func ) ) + return; + if ( !isdefined( level._func[ func ] ) ) + return; + + if ( !isdefined( parm1 ) ) + { + call [[ level._func[ func ] ]](); + return; + } + + if ( !isdefined( parm2 ) ) + { + call [[ level._func[ func ] ]]( parm1 ); + return; + } + if ( !isdefined( parm3 ) ) + { + call [[ level._func[ func ] ]]( parm1, parm2 ); + return; + } + if ( !isdefined( parm4 ) ) + { + call [[ level._func[ func ] ]]( parm1, parm2, parm3 ); + return; + } + + call [[ level._func[ func ] ]]( parm1, parm2, parm3, parm4 ); +} + +/* +============= +///ScriptDocBegin +"Name: self_func( , , , , )" +"Summary: Runs a function from level.func, if it exists. Runs on whatever calls it. Useful for common scripts where a code function may not exist in one codebase or the other." +"Module: Utility" +"CallOn: An entity" +"MandatoryArg: : String reference to level.func array." +"OptionalArg: : " +"OptionalArg: : " +"OptionalArg: : " +"OptionalArg: : " +"Example: level.player self_func( "some_player_function", 1, 2 );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +self_func( func, parm1, parm2, parm3, parm4 ) +{ + if ( !isdefined( level._func[ func ] ) ) + return; + + if ( !isdefined( parm1 ) ) + { + self call [[ level._func[ func ] ]](); + return; + } + + if ( !isdefined( parm2 ) ) + { + self call [[ level._func[ func ] ]]( parm1 ); + return; + } + if ( !isdefined( parm3 ) ) + { + self call [[ level._func[ func ] ]]( parm1, parm2 ); + return; + } + if ( !isdefined( parm4 ) ) + { + self call [[ level._func[ func ] ]]( parm1, parm2, parm3 ); + return; + } + + self call [[ level._func[ func ] ]]( parm1, parm2, parm3, parm4 ); +} + +/* +============= +///ScriptDocBegin +"Name: random_vector( )" +"Summary: Returns a random unit vector, with optional scale." +"Module: Vector" +"CallOn: Level" +"OptionalArg: : The magnitude by which to scale the random vector." +"Example: my_new_vector = random_vector( 500 );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +random_vector( scale ) +{ + if( !IsDefined( scale ) ) + scale = 1; + + return( RandomFloatRange( -1, 1 ) * scale, RandomFloatRange( -1, 1 ) * scale, RandomFloatRange( -1, 1 ) * scale ); +} + +/* +============= +///ScriptDocBegin +"Name: randomvector( )" +"Summary: returns a random vector centered on " +"Module: Vector" +"CallOn: Level" +"MandatoryArg: : " +"Example: direction = randomvector( 1 )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +randomvector( num ) +{ + return( randomfloat( num ) - num * 0.5, randomfloat( num ) - num * 0.5, randomfloat( num ) - num * 0.5 ); +} + +/* +============= +///ScriptDocBegin +"Name: randomvectorrange( , )" +"Summary: returns a random vector centered between and " +"Module: Vector" +"CallOn: Level" +"MandatoryArg: : " +"MandatoryArg: : " +"Example: direction = randomvectorrange( 5, 10 )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +randomvectorrange( num_min, num_max ) +{ + assert( isdefined( num_min ) ); + assert( isdefined( num_max ) ); + + x = randomfloatrange( num_min, num_max ); + if ( randomint( 2 ) == 0 ) + x *= -1; + + y = randomfloatrange( num_min, num_max ); + if ( randomint( 2 ) == 0 ) + y *= -1; + + z = randomfloatrange( num_min, num_max ); + if ( randomint( 2 ) == 0 ) + z *= -1; + + return( x, y, z ); +} + +angle_dif ( oldangle, newangle ) +{ + // returns the difference between two yaws + if ( oldangle == newangle ) + return 0; + + while ( newangle > 360 ) + newangle -= 360; + + while ( newangle < 0 ) + newangle += 360; + + while ( oldangle > 360 ) + oldangle -= 360; + + while ( oldangle < 0 ) + oldangle += 360; + + olddif = undefined; + newdif = undefined; + + if ( newangle > 180 ) + newdif = 360 - newangle; + else + newdif = newangle; + + if ( oldangle > 180 ) + olddif = 360 - oldangle; + else + olddif = oldangle; + + outerdif = newdif + olddif; + innerdif = 0; + + if ( newangle > oldangle ) + innerdif = newangle - oldangle; + else + innerdif = oldangle - newangle; + + if ( innerdif < outerdif ) + return innerdif; + else + return outerdif; +} + + +sign( x ) +{ + if ( x >= 0 ) + return 1; + return - 1; +} + + +track( spot_to_track ) +{ + if ( isdefined( self.current_target ) ) + { + if ( spot_to_track == self.current_target ) + return; + } + self.current_target = spot_to_track; +} + +get_enemy_team( team ) +{ + assertEx( team != "neutral", "Team must be allies or axis" ); + + teams = []; + teams[ "axis" ] = "allies"; + teams[ "allies" ] = "axis"; + + return teams[ team ]; +} + + +clear_exception( type ) +{ + assert( isdefined( self.exception[ type ] ) ); + self.exception[ type ] = anim.defaultException; +} + +set_exception( type, func ) +{ + assert( isdefined( self.exception[ type ] ) ); + self.exception[ type ] = func; +} + +set_all_exceptions( exceptionFunc ) +{ + keys = getArrayKeys( self.exception ); + for ( i = 0; i < keys.size; i++ ) + { + self.exception[ keys[ i ] ] = exceptionFunc; + } +} + +/* +============= +///ScriptDocBegin +"Name: cointoss()" +"Summary: 50/50 returns true" +"Module: Utility" +"CallOn: Level" +"Example: if(cointoss())" +"SPMP: both" +///ScriptDocEnd +============= +*/ +cointoss() +{ + return randomint( 100 ) >= 50 ; +} + + +choose_from_weighted_array( values, weights ) +{ + assert( values.size == weights.size ); + + randomval = randomint( weights[ weights.size - 1 ] + 1 ); + + for ( i = 0; i < weights.size; i++ ) + { + if ( randomval <= weights[i] ) + return values[i]; + } +} + +get_cumulative_weights( weights ) +{ + cumulative_weights = []; + + sum = 0; + for ( i = 0; i < weights.size; i++ ) + { + sum += weights[i]; + cumulative_weights[i] = sum; + } + + return cumulative_weights; +} + + +waittill_string( msg, ent ) +{ + if ( msg != "death" ) + self endon( "death" ); + + ent endon( "die" ); + self waittill( msg ); + ent notify( "returned", msg ); +} + + +waittill_multiple( string1, string2, string3, string4, string5 ) +{ + self endon( "death" ); + ent = spawnstruct(); + ent.threads = 0; + + if ( isdefined( string1 ) ) + { + self thread waittill_string( string1, ent ); + ent.threads++; + } + if ( isdefined( string2 ) ) + { + self thread waittill_string( string2, ent ); + ent.threads++; + } + if ( isdefined( string3 ) ) + { + self thread waittill_string( string3, ent ); + ent.threads++; + } + if ( isdefined( string4 ) ) + { + self thread waittill_string( string4, ent ); + ent.threads++; + } + if ( isdefined( string5 ) ) + { + self thread waittill_string( string5, ent ); + ent.threads++; + } + + while ( ent.threads ) + { + ent waittill( "returned" ); + ent.threads--; + } + + ent notify( "die" ); +} + +waittill_multiple_ents( ent1, string1, ent2, string2, ent3, string3, ent4, string4 ) +{ + self endon( "death" ); + ent = spawnstruct(); + ent.threads = 0; + + if ( isdefined( ent1 ) ) + { + assert( isdefined( string1 ) ); + ent1 thread waittill_string( string1, ent ); + ent.threads++; + } + if ( isdefined( ent2 ) ) + { + assert( isdefined( string2 ) ); + ent2 thread waittill_string( string2, ent ); + ent.threads++; + } + if ( isdefined( ent3 ) ) + { + assert( isdefined( string3 ) ); + ent3 thread waittill_string( string3, ent ); + ent.threads++; + } + if ( isdefined( ent4 ) ) + { + assert( isdefined( string4 ) ); + ent4 thread waittill_string( string4, ent ); + ent.threads++; + } + + while ( ent.threads ) + { + ent waittill( "returned" ); + ent.threads--; + } + + ent notify( "die" ); +} + +/* +============= +///ScriptDocBegin +"Name: waittill_any_return( , , , , )" +"Summary: Waits for any of several messages then returns what it was." +"Module: Utility" +"MandatoryArg: : A string to wait on" +"MandatoryArg: : A string to wait on" +"OptionalArg: : A string to wait on" +"OptionalArg: : A string to wait on" +"OptionalArg: : A string to wait on" +"Example: msg = level.player waittill_any_return( "weapon_fired", "player_flash", "player_frag" );" +"SPMP: singleplayer" +///ScriptDocEnd +============= +*/ +waittill_any_return( string1, string2, string3, string4, string5 ) +{ + if ( ( !isdefined( string1 ) || string1 != "death" ) && + ( !isdefined( string2 ) || string2 != "death" ) && + ( !isdefined( string3 ) || string3 != "death" ) && + ( !isdefined( string4 ) || string4 != "death" ) && + ( !isdefined( string5 ) || string5 != "death" ) ) + self endon( "death" ); + + ent = spawnstruct(); + + if ( isdefined( string1 ) ) + self thread waittill_string( string1, ent ); + + if ( isdefined( string2 ) ) + self thread waittill_string( string2, ent ); + + if ( isdefined( string3 ) ) + self thread waittill_string( string3, ent ); + + if ( isdefined( string4 ) ) + self thread waittill_string( string4, ent ); + + if ( isdefined( string5 ) ) + self thread waittill_string( string5, ent ); + + ent waittill( "returned", msg ); + ent notify( "die" ); + return msg; +} + +/* +============= +///ScriptDocBegin +"Name: waittill_any_timeout( , , , , , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +waittill_any_timeout( timeOut, string1, string2, string3, string4, string5 ) +{ + if ( ( !isdefined( string1 ) || string1 != "death" ) && + ( !isdefined( string2 ) || string2 != "death" ) && + ( !isdefined( string3 ) || string3 != "death" ) && + ( !isdefined( string4 ) || string4 != "death" ) && + ( !isdefined( string5 ) || string5 != "death" ) ) + self endon( "death" ); + + ent = spawnstruct(); + + if ( isdefined( string1 ) ) + self thread waittill_string( string1, ent ); + + if ( isdefined( string2 ) ) + self thread waittill_string( string2, ent ); + + if ( isdefined( string3 ) ) + self thread waittill_string( string3, ent ); + + if ( isdefined( string4 ) ) + self thread waittill_string( string4, ent ); + + if ( isdefined( string5 ) ) + self thread waittill_string( string5, ent ); + + ent thread _timeout( timeOut ); + + ent waittill( "returned", msg ); + ent notify( "die" ); + return msg; +} + + +_timeout( delay ) +{ + self endon( "die" ); + + wait( delay ); + self notify( "returned", "timeout" ); +} + + +/* +============= +///ScriptDocBegin +"Name: waittill_any( , , , , , , , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : a notify on which the entity should wait" +"OptionalArg: - : optional other notifies to wait for" +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +waittill_any( string1, string2, string3, string4, string5, string6, string7, string8 ) +{ + assert( isdefined( string1 ) ); + + if ( isdefined( string2 ) ) + self endon( string2 ); + + if ( isdefined( string3 ) ) + self endon( string3 ); + + if ( isdefined( string4 ) ) + self endon( string4 ); + + if ( isdefined( string5 ) ) + self endon( string5 ); + + if ( isdefined( string6 ) ) + self endon( string6 ); + + if ( isdefined( string7 ) ) + self endon( string7 ); + + if ( isdefined( string8 ) ) + self endon( string8 ); + + self waittill( string1 ); +} + +waittill_any_ents( ent1, string1, ent2, string2, ent3, string3, ent4, string4, ent5, string5, ent6, string6, ent7, string7 ) +{ + assert( isdefined( ent1 ) ); + assert( isdefined( string1 ) ); + + if ( ( isdefined( ent2 ) ) && ( isdefined( string2 ) ) ) + ent2 endon( string2 ); + + if ( ( isdefined( ent3 ) ) && ( isdefined( string3 ) ) ) + ent3 endon( string3 ); + + if ( ( isdefined( ent4 ) ) && ( isdefined( string4 ) ) ) + ent4 endon( string4 ); + + if ( ( isdefined( ent5 ) ) && ( isdefined( string5 ) ) ) + ent5 endon( string5 ); + + if ( ( isdefined( ent6 ) ) && ( isdefined( string6 ) ) ) + ent6 endon( string6 ); + + if ( ( isdefined( ent7 ) ) && ( isdefined( string7 ) ) ) + ent7 endon( string7 ); + + ent1 waittill( string1 ); +} + +/* +============= +///ScriptDocBegin +"Name: isFlashed()" +"Summary: Returns true if the player or an AI is flashed" +"Module: Utility" +"CallOn: An AI" +"Example: flashed = level.price isflashed();" +"SPMP: both" +///ScriptDocEnd +============= +*/ +isFlashed() +{ + if ( !isdefined( self.flashEndTime ) ) + return false; + + return gettime() < self.flashEndTime; +} + + /* + ============= +///ScriptDocBegin +"Name: flag_exist( )" +"Summary: checks to see if a flag exists" +"Module: Flag" +"MandatoryArg: : name of the flag to check" +"Example: if( flag_exist( "hq_cleared" ) );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_exist( message ) +{ + return isdefined( level._flag[ message ] ); +} + + /* + ============= +///ScriptDocBegin +"Name: flag( , )" +"Summary: Checks if the flag is set. Returns true or false." +"Module: Flag" +"MandatoryArg: : name of the flag to check" +"OptionalArg: : You can check the flag settings for a specific entity by passing the entity" +"Example: if ( flag( "hq_cleared" ) )" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +flag( message ) +{ + assertEx( isdefined( message ), "Tried to check flag but the flag was not defined." ); + assertEx( isdefined( level._flag[ message ] ), "Tried to check flag " + message + " but the flag was not initialized." ); + + return level._flag[ message ]; +} + + +init_flags() +{ + level._flag = []; + level._flags_lock = []; + level._generic_index = 0; + + if ( !isdefined( level._sp_stat_tracking_func ) ) + level._sp_stat_tracking_func = ::empty_init_func; + + level._flag_struct = spawnstruct(); + level._flag_struct assign_unique_id(); +} + + /* + ============= +///ScriptDocBegin +"Name: flag_init( )" +"Summary: Initialize a flag to be used. All flags must be initialized before using flag_set or flag_wait" +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of the flag to create" +"Example: flag_init( "hq_cleared" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_init( message ) +{ + if ( !isDefined( level._flag ) ) + { + init_flags(); + } + + /# + if ( isdefined( level._first_frame ) && level._first_frame == -1 ) + assertEx( !isDefined( level._flag[ message ] ), "Attempt to reinitialize existing message: " + message ); + #/ + + level._flag[ message ] = false; +/# + // lock check +#/ + if ( !isdefined( level._trigger_flags ) ) + { + init_trigger_flags(); + level._trigger_flags[ message ] = []; + } + else + if ( !isdefined( level._trigger_flags[ message ] ) ) + { + level._trigger_flags[ message ] = []; + } + + if ( issuffix( message, "aa_" ) ) + { + thread [[ level._sp_stat_tracking_func ]]( message ); + } +} + +empty_init_func( empty ) +{ +} + +issuffix( msg, suffix ) +{ + if ( suffix.size > msg.size ) + return false; + + for ( i = 0; i < suffix.size; i++ ) + { + if ( msg[ i ] != suffix[ i ] ) + return false; + } + return true; +} + /* + ============= +///ScriptDocBegin +"Name: flag_set( , )" +"Summary: Sets the specified flag, all scripts using flag_wait will now continue." +"Module: Flag" +"MandatoryArg: : name of the flag to set" +"OptionalArg: : Pass an entity with the flag_set" +"Example: flag_set( "hq_broiled" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_set( message, setter ) +{ +/# + assertEx( isDefined( level._flag[ message ] ), "Attempt to set a flag before calling flag_init: " + message ); + //lock check +#/ + + level._flag[ message ] = true; + set_trigger_flag_permissions( message ); + if ( isdefined( setter ) ) + { + level notify( message, setter );// notify needs to be very last thing called + } + else + { + level notify( message );// notify needs to be very last thing called + } +} + +assign_unique_id() +{ + self.unique_id = "generic" + level._generic_index; + level._generic_index++; +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait( , )" +"Summary: Waits until the specified flag is set." +"Module: Flag" +"MandatoryArg: : name of the flag to wait on" +"OptionalArg: : You can wait until a flag is set for a specific entity" +"Example: flag_wait( "hq_cleared" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait( msg, entity ) +{ + other = undefined; + while ( !flag( msg ) ) + { + other = undefined; + level waittill( msg, other ); + + // if we're waiting for the flag on a specific entity then we have to check + // to see if the flag is set on that specific entity + if ( isdefined( entity ) && flag( msg, entity ) ) + break; + } + if ( isdefined( other ) ) + return other; +} + + /* + ============= +///ScriptDocBegin +"Name: flag_clear( , )" +"Summary: Clears the specified flag." +"Module: Flag" +"MandatoryArg: : name of the flag to clear" +"Example: flag_clear( "hq_cleared" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_clear( message ) +{ +/# + assertEx( isDefined( level._flag[ message ] ), "Attempt to set a flag before calling flag_init: " + message ); + // lock implementation tbd +#/ + //do this check so we don't unneccessarily send a notify + if ( !flag( message ) ) + return; + + level._flag[ message ] = false; + + set_trigger_flag_permissions( message ); + level notify( message );// the notify needs to be the very last thing called in this function +} + +/* +============= +///ScriptDocBegin +"Name: flag_waitopen( )" +"Summary: Waits for the flag to open" +"Module: Flag" +"MandatoryArg: : The flag" +"Example: flag_waitopen( "get_me_bagels" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +flag_waitopen( msg ) +{ + while ( flag( msg ) ) + level waittill( msg ); +} + +/* +============= +///ScriptDocBegin +"Name: waittill_either( , )" +"Summary: Waits until either message, on self" +"Module: Utility" +"CallOn: An entity or the level" +"MandatoryArg: : First msg to wait on" +"MandatoryArg: : Second msg to wait on" +"Example: level waittill_either( "yo", "no" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +waittill_either( msg1, msg2 ) +{ + self endon( msg1 ); + self waittill( msg2 ); +} + +/* +============= +///ScriptDocBegin +"Name: waittill_both( , )" +"Summary: Waits until both message, on self" +"Module: Utility" +"CallOn: An entity or the level" +"MandatoryArg: : First msg to wait on" +"MandatoryArg: : Second msg to wait on" +"Example: level waittill_either( "yo", "no" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +waittill_both( msg1, msg2 ) +{ + self.msg1_complete = false; + self.msg2_complete = false; + self thread waittill_both_watch_msg1(msg1); + self thread waittill_both_watch_msg2(msg2); + while( true ) + { + if( self.msg1_complete && self.msg2_complete ) + { + return; + } + wait 0.05; + } + +} +waittill_both_watch_msg1( msg1 ) +{ + self waittill( msg1 ); + self.msg1_complete = true; +} +waittill_both_watch_msg2( msg2 ) +{ + self waittill( msg2 ); + self.msg2_complete = true; +} + + +/* + ============= +///ScriptDocBegin +"Name: array_thread( , , , , )" +"Summary: Threads the < process > function on every entity in the < entities > array. The entity will become "self" in the specified function." +"Module: Array" +"CallOn: " +"MandatoryArg: : array of entities to thread the process" +"MandatoryArg: : pointer to a script function" +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"Example: array_thread( array_of_guys, ::set_ignoreme, false );" +"SPMP: both" +///ScriptDocEnd + ============= +*/ +array_thread( entities, process, var1, var2, var3, var4, var5, var6, var7, var8, var9 ) +{ + if ( !isdefined( var1 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]](); + return; + } + + if ( !isdefined( var2 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1 ); + return; + } + + if ( !isdefined( var3 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2 ); + return; + } + + if ( !isdefined( var4 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3 ); + return; + } + + if ( !isdefined( var5 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4 ); + return; + } + + if ( !isdefined( var6 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4, var5 ); + return; + } + + if ( !isdefined( var7 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4, var5, var6 ); + return; + } + + if ( !isdefined( var8 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4, var5, var6, var7 ); + return; + } + + if ( !isdefined( var9 ) ) + { + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4, var5, var6, var7, var8 ); + return; + } + + foreach ( ent in entities ) + ent thread [[ process ]]( var1, var2, var3, var4, var5, var6, var7, var8, var9 ); + return; +} + +/* + ============= +///ScriptDocBegin +"Name: array_call( , , , , )" +"Summary: Runs the code < process > function on every entity in the < entities > array. The entity will become "self" in the specified function." +"Module: Array" +"CallOn: " +"MandatoryArg: : array of entities to thread the process" +"MandatoryArg: : pointer to a code function" +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"Example: array_call( array_of_guys, ::set_ignoreme, false );" +"SPMP: both" +///ScriptDocEnd + ============= +*/ +array_call( entities, process, var1, var2, var3 ) +{ + if ( isdefined( var3 ) ) + { + foreach ( ent in entities ) + ent call [[ process ]]( var1, var2, var3 ); + + return; + } + + if ( isdefined( var2 ) ) + { + foreach ( ent in entities ) + ent call [[ process ]]( var1, var2 ); + + return; + } + + if ( isdefined( var1 ) ) + { + foreach ( ent in entities ) + ent call [[ process ]]( var1 ); + + return; + } + + foreach ( ent in entities ) + ent call [[ process ]](); +} + +/* +============= +///ScriptDocBegin +"Name: array_thread4( , , , , , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +array_thread4( entities, process, var1, var2, var3, var4 ) +{ + array_thread( entities, process, var1, var2, var3, var4 ); +} + +/* +============= +///ScriptDocBegin +"Name: array_thread5( , , , , , , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +array_thread5( entities, process, var1, var2, var3, var4, var5 ) +{ + array_thread( entities, process, var1, var2, var3, var4, var5 ); +} + +/* +============= +///ScriptDocBegin +"Name: remove_undefined_from_array()" +"Summary: remove elements from an array that are undefined" +"Module: Array" +"CallOn: " +"MandatoryArg: : array to clear out" +"Example: level.trigger_flags[ msg ] = remove_undefined_from_array( level.trigger_flags[ msg ] );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +remove_undefined_from_array( array ) +{ + newarray = []; + for ( i = 0; i < array.size; i++ ) + { + if ( !isdefined( array[ i ] ) ) + continue; + newarray[ newarray.size ] = array[ i ]; + } + return newarray; +} + +/* + ============= +///ScriptDocBegin +"Name: trigger_on( , )" +"Summary: Turns a trigger on. This only needs to be called if it was previously turned off" +"Module: Trigger" +"CallOn: A trigger" +"OptionalArg: : the name corrisponding to a targetname or script_noteworthy to grab the trigger internally" +"OptionalArg: : the type( targetname, or script_noteworthy ) corrisponding to a name to grab the trigger internally" +"Example: trigger trigger_on(); -or- trigger_on( "base_trigger", "targetname" )" +"SPMP: both" +///ScriptDocEnd + ============= + */ +trigger_on( name, type ) +{ + if ( isdefined( name ) && isdefined( type ) ) + { + ents = getentarray( name, type ); + array_thread( ents, ::trigger_on_proc ); + } + else + self trigger_on_proc(); +} + +trigger_on_proc() +{ + if ( isDefined( self.realOrigin ) ) + self.origin = self.realOrigin; + self.trigger_off = undefined; +} + + + /* + ============= +///ScriptDocBegin +"Name: trigger_off( , )" +"Summary: Turns a trigger off so it can no longer be triggered." +"Module: Trigger" +"CallOn: A trigger" +"OptionalArg: : the name corrisponding to a targetname or script_noteworthy to grab the trigger internally" +"OptionalArg: : the type( targetname, or script_noteworthy ) corrisponding to a name to grab the trigger internally" +"Example: trigger trigger_off();" +"SPMP: both" +///ScriptDocEnd + ============= + */ +trigger_off( name, type ) +{ + if ( isdefined( name ) && isdefined( type ) ) + { + ents = getentarray( name, type ); + array_thread( ents, ::trigger_off_proc ); + } + else + self trigger_off_proc(); +} + +trigger_off_proc() +{ + if ( !isDefined( self.realOrigin ) ) + self.realOrigin = self.origin; + + if ( self.origin == self.realorigin ) + self.origin += ( 0, 0, -10000 ); + self.trigger_off = true; +} + +set_trigger_flag_permissions( msg ) +{ + // turns triggers on or off depending on if they have the proper flags set, based on their shift-g menu settings + + // this can be init before _load has run, thanks to AI. + if ( !isdefined( level._trigger_flags ) ) + return; + + // cheaper to do the upkeep at this time rather than with endons and waittills on the individual triggers + level._trigger_flags[ msg ] = remove_undefined_from_array( level._trigger_flags[ msg ] ); + array_thread( level._trigger_flags[ msg ], ::update_trigger_based_on_flags ); +} + +update_trigger_based_on_flags() +{ + true_on = true; + if ( isdefined( self.script_flag_true ) ) + { + true_on = false; + tokens = create_flags_and_return_tokens( self.script_flag_true ); + + // stay off unless all the flags are false + foreach ( token in tokens ) + { + if ( flag( token ) ) + { + true_on = true; + break; + } + } + } + + false_on = true; + if ( isdefined( self.script_flag_false ) ) + { + tokens = create_flags_and_return_tokens( self.script_flag_false ); + + // stay off unless all the flags are false + foreach ( token in tokens ) + { + if ( flag( token ) ) + { + false_on = false; + break; + } + } + } + + [[ level._trigger_func[ true_on && false_on ] ]](); +} + +create_flags_and_return_tokens( flags ) +{ + tokens = strtok( flags, " " ); + + // create the flag if level script does not + for ( i = 0; i < tokens.size; i++ ) + { + if ( !isdefined( level._flag[ tokens[ i ] ] ) ) + { + flag_init( tokens[ i ] ); + } + } + + return tokens; +} + +init_trigger_flags() +{ + level._trigger_flags = []; + level._trigger_func[ true ] = ::trigger_on; + level._trigger_func[ false ] = ::trigger_off; +} + +/* +============= +///ScriptDocBegin +"Name: getstruct( , )" +"Summary: get a struct by target, targetname,script_noteworthy, or script_linkname types, must be called after maps\_load::main();" +"Module: Struct" +"CallOn: Level" +"MandatoryArg: : name of key" +"MandatoryArg: : key type" +"Example: position = getstruct("waypoint1","targetname"); +"SPMP: both" +///ScriptDocEnd +============= +*/ + +getstruct( name, type ) +{ + assertex( isdefined( name ) && isdefined( type ), "Did not fill in name and type" ); + assertEx( isdefined( level._struct_class_names ), "Tried to getstruct before the structs were init" ); + + array = level._struct_class_names[ type ][ name ]; + if ( !isdefined( array ) ) + { + return undefined; + } + + if ( array.size > 1 ) + { + assertMsg( "getstruct used for more than one struct of type " + type + " called " + name + "." ); + return undefined; + } + return array[ 0 ]; +} + + /* + ============= +///ScriptDocBegin +"Name: getstructarray( , : " +"MandatoryArg: : " +"Example: fxemitters = getstructarray( "streetlights", "targetname" )" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +getstructarray( name, type ) +{ + assertEx( isdefined( level._struct_class_names ), "Tried to getstruct before the structs were init" ); + + array = level._struct_class_names[ type ][ name ]; + if ( !isdefined( array ) ) + return []; + return array; +} + +struct_class_init() +{ + assertEx( !isdefined( level._struct_class_names ), "level.struct_class_names is being initialized in the wrong place! It shouldn't be initialized yet." ); + + level._struct_class_names = []; + level._struct_class_names[ "target" ] = []; + level._struct_class_names[ "targetname" ] = []; + level._struct_class_names[ "script_noteworthy" ] = []; + level._struct_class_names[ "script_linkname" ] = []; + level._struct_class_names[ "script_aresgroup" ] = []; + level._struct_class_names[ "script_aresarea" ] = []; + + foreach ( struct in level._struct ) + { + if ( isdefined( struct.targetname ) ) + { + if ( !isdefined( level._struct_class_names[ "targetname" ][ struct.targetname ] ) ) + level._struct_class_names[ "targetname" ][ struct.targetname ] = []; + + size = level._struct_class_names[ "targetname" ][ struct.targetname ].size; + level._struct_class_names[ "targetname" ][ struct.targetname ][ size ] = struct; + } + if ( isdefined( struct.target ) ) + { + if ( !isdefined( level._struct_class_names[ "target" ][ struct.target ] ) ) + level._struct_class_names[ "target" ][ struct.target ] = []; + + size = level._struct_class_names[ "target" ][ struct.target ].size; + level._struct_class_names[ "target" ][ struct.target ][ size ] = struct; + } + if ( isdefined( struct.script_noteworthy ) ) + { + if ( !isdefined( level._struct_class_names[ "script_noteworthy" ][ struct.script_noteworthy ] ) ) + level._struct_class_names[ "script_noteworthy" ][ struct.script_noteworthy ] = []; + + size = level._struct_class_names[ "script_noteworthy" ][ struct.script_noteworthy ].size; + level._struct_class_names[ "script_noteworthy" ][ struct.script_noteworthy ][ size ] = struct; + } + if ( isdefined( struct.script_linkname ) ) + { + assertex( !isdefined( level._struct_class_names[ "script_linkname" ][ struct.script_linkname ] ), "Two structs have the same linkname" ); + level._struct_class_names[ "script_linkname" ][ struct.script_linkname ][ 0 ] = struct; + } + if ( isdefined( struct.script_aresgroup ) ) + { + if ( !isdefined( level._struct_class_names[ "script_aresgroup" ][ struct.script_aresgroup ] ) ) + level._struct_class_names[ "script_aresgroup" ][ struct.script_aresgroup ] = []; + + size = level._struct_class_names[ "script_aresgroup" ][ struct.script_aresgroup ].size; + level._struct_class_names[ "script_aresgroup" ][ struct.script_aresgroup ][ size ] = struct; + } + if ( isdefined( struct.script_aresarea ) ) + { + if ( !isdefined( level._struct_class_names[ "script_aresarea" ][ struct.script_aresarea ] ) ) + level._struct_class_names[ "script_aresarea" ][ struct.script_aresarea ] = []; + + size = level._struct_class_names[ "script_aresarea" ][ struct.script_aresarea ].size; + level._struct_class_names[ "script_aresarea" ][ struct.script_aresarea ][ size ] = struct; + } + } +} + +fileprint_start( file ) +{ + /# + filename = file; + level._fileprint = 1; + level._fileprintlinecount = 0; + level._fileprint_filename = filename; + #/ +} + + /* + ============= +///ScriptDocBegin +"Name: fileprint_map_start( )" +"Summary: starts map export with the file trees\cod3\cod3\map_source\xenon_export\ < filename > .map adds header / worldspawn entity to the map. Use this if you want to start a .map export." +"Module: Fileprint" +"CallOn: Level" +"MandatoryArg: : " +"OptionalArg: : " +"Example: fileprint_map_start( filename );" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +fileprint_map_start() +{ + /# + // for the entity count + level._fileprint_mapentcount = 0; + fileprint_map_header( true ); + #/ + +} + +fileprint_map_header( bInclude_blank_worldspawn ) +{ + if ( !isdefined( bInclude_blank_worldspawn ) ) + bInclude_blank_worldspawn = false; + + /# + fileprint_launcher( "iwmap 6" ); + fileprint_launcher( "\"000_Global\" flags active" ); + fileprint_launcher( "\"The Map\" flags" ); + + if ( !bInclude_blank_worldspawn ) + return; + + fileprint_map_entity_start(); + fileprint_map_keypairprint( "classname", "worldspawn" ); + fileprint_map_entity_end(); + + #/ +} + + /* + ============= +///ScriptDocBegin +"Name: fileprint_map_keypairprint( , )" +"Summary: prints a pair of keys to the current open map( by fileprint_map_start() )" +"Module: Fileprint" +"CallOn: Level" +"MandatoryArg: : " +"MandatoryArg: : " +"Example: fileprint_map_keypairprint( "classname", "script_model" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +fileprint_map_keypairprint( key1, key2 ) +{ + /# + fileprint_launcher( "\"" + key1 + "\" \"" + key2 + "\"" ); + #/ +} + + /* + ============= +///ScriptDocBegin +"Name: fileprint_map_entity_start()" +"Summary: prints entity number and opening bracket to currently opened file" +"Module: Fileprint" +"CallOn: Level" +"Example: fileprint_map_entity_start();" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +fileprint_map_entity_start() +{ + /# + assert( isdefined( level._fileprint_mapentcount ), "need to start a map with fileprint_map_start() first" ); + assert( !isdefined( level._fileprint_entitystart ) ); + level._fileprint_entitystart = true; + fileprint_launcher( "entity " + level._fileprint_mapentcount ); + fileprint_launcher( "{" ); + level._fileprint_mapentcount++; + #/ +} + + /* + ============= +///ScriptDocBegin +"Name: fileprint_map_entity_end()" +"Summary: close brackets an entity, required for the next entity to begin" +"Module: Fileprint" +"CallOn: Level" +"Example: fileprint_map_entity_end();" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +fileprint_map_entity_end() +{ + /# + fileprint_launcher( "}" ); + level._fileprint_entitystart = undefined; + #/ +} + + + /* + ============= +///ScriptDocBegin +"Name: fileprint_radiant_vec( )" +"Summary: this converts a vector to a .map file readable format" +"Module: Fileprint" +"CallOn: An entity" +"MandatoryArg: : " +"Example: origin_string = fileprint_radiant_vec( vehicle.angles )" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +fileprint_radiant_vec( vector ) +{ + /# + string = "" + vector[ 0 ] + " " + vector[ 1 ] + " " + vector[ 2 ] + ""; + return string; + #/ +} + +/* +============= +///ScriptDocBegin +"Name: vector_multiply( , )" +"Summary: multiply a vector" +"Module: Vector" +"CallOn: Level" +"MandatoryArg: : vector to multiply" +"MandatoryArg: : scale" +"Example: vec = vector_multiply( vec, magnitude );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +vector_multiply( vec, dif ) +{ + vec = ( vec[ 0 ] * dif, vec[ 1 ] * dif, vec[ 2 ] * dif ); + return vec; +} + +/* +============= +///ScriptDocBegin +"Name: vector_string( )" +"Summary: format a string based on a vector." +"Module: Vector" +"CallOn: Level" +"MandatoryArg: : vector to format into a string." +"Example: string = vector_string( vec );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +vector_string( vec ) +{ + string = "( " + vec[0] + ", " + vec[1] + ", " + vec[2] + " )"; + + return string; +} + +/* +============= +///ScriptDocBegin +"Name: f3D_vectors_equal( , )" +"Summary: Determines whether or not 2 floating-point 3D vectors are 'equal'" +"Module: Vector" +"MandatoryArg: " +"MandatoryArg: " +"Example: if ( f3D_vectors_equal( vec0, vec1 ) ) {...}" +"SPMP: both" +///ScriptDocEnd +============= +*/ +f3D_vectors_equal( vec0, vec1 ) +{ + EPSILON = 0.01; + + return abs( vec0[0] - vec1[0] ) < EPSILON && + abs( vec0[1] - vec1[1] ) < EPSILON && + abs( vec0[2] - vec1[2] ) < EPSILON; +} + + /* + ============= +///ScriptDocBegin +"Name: array_remove( , )" +"Summary: Returns < ents > array minus < remover > " +"Module: Array" +"CallOn: " +"MandatoryArg: : array to remove < remover > from" +"MandatoryArg: : entity to remove from the array" +"Example: ents = array_remove( ents, guy );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +array_remove( ents, remover ) +{ + newents = []; + foreach( index in ents ) + { + if ( index != remover ) + newents[ newents.size ] = index; + } + + return newents; +} + +/* +============= +///ScriptDocBegin +"Name: array_remove_array( , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +array_remove_array( ents, remover_array ) +{ + foreach( remover in remover_array ) + ents = array_remove( ents, remover ); + + return ents; +} + + /* + ============= +///ScriptDocBegin +"Name: array_removeUndefined( )" +"Summary: Returns a new array of < array > minus the undefined indicies" +"Module: Array" +"CallOn: " +"MandatoryArg: : The array to search for undefined indicies in." +"Example: ents = array_removeUndefined( ents );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +array_removeUndefined( array ) +{ + newArray = []; + for ( i = 0; i < array.size; i++ ) + { + if ( !isdefined( array[ i ] ) ) + continue; + newArray[ newArray.size ] = array[ i ]; + } + + return newArray; +} + + /* + ============= +///ScriptDocBegin +"Name: array_levelthread( , , , , )" +"Summary: Threads the < process > function for every entity in the < entities > array. The level calls the function and each entity of the array is passed as the first parameter to the process." +"Module: Array" +"CallOn: " +"MandatoryArg: : array of entities to thread the process" +"MandatoryArg: : pointer to a script function" +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"Example: array_levelthread( getentarray( "palm", "targetname" ), ::palmTrees );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +array_levelthread( array, process, var1, var2, var3 ) +{ + if ( isdefined( var3 ) ) + { + foreach ( ent in array ) + thread [[ process ]]( ent, var1, var2, var3 ); + + return; + } + + if ( isdefined( var2 ) ) + { + foreach ( ent in array ) + thread [[ process ]]( ent, var1, var2 ); + + return; + } + + if ( isdefined( var1 ) ) + { + foreach ( ent in array ) + thread [[ process ]]( ent, var1 ); + + return; + } + + foreach ( ent in array ) + thread [[ process ]]( ent ); +} + + /* + ============= +///ScriptDocBegin +"Name: array_levelcall( , , , , )" +"Summary: Calls the < process > function for every entity in the < entities > array. The level calls the function and each entity of the array is passed as the first parameter to the process." +"Module: Array" +"CallOn: " +"MandatoryArg: : array of entities to thread the process" +"MandatoryArg: : pointer to a code function" +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"Example: array_levelthread( array_of_trees, ::palmTrees );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +array_levelcall( array, process, var1, var2, var3 ) +{ + if ( isdefined( var3 ) ) + { + foreach ( ent in array ) + call [[ process ]]( ent, var1, var2, var3 ); + + return; + } + + if ( isdefined( var2 ) ) + { + foreach ( ent in array ) + call [[ process ]]( ent, var1, var2 ); + + return; + } + + if ( isdefined( var1 ) ) + { + foreach ( ent in array ) + call [[ process ]]( ent, var1 ); + + return; + } + + foreach ( ent in array ) + call [[ process ]]( ent ); +} + +/* +============= +///ScriptDocBegin +"Name: add_to_array( , )" +"Summary: Adds < ent > to < array > and returns the new array." +"Module: Array" +"CallOn: " +"MandatoryArg: : The array to add < ent > to." +"MandatoryArg: : The entity to be added." +"Example: nodes = add_to_array( nodes, new_node );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +add_to_array( array, ent ) +{ + if ( !isdefined( ent ) ) + return array; + + if ( !isdefined( array ) ) + array[ 0 ] = ent; + else + array[ array.size ] = ent; + + return array; +} + + + +/* +============= +///ScriptDocBegin +"Name: flag_assert( )" +"Summary: Asserts that a flag is clear. Useful for proving an assumption of a flag's state" +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : flag name" +"Example: flag_assert( "fairground_begins" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +flag_assert( msg ) +{ + assertEx( !flag( msg ), "Flag " + msg + " set too soon!" ); +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_either( , )" +"Summary: Waits until either of the the specified flags are set." +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of one flag to wait on" +"MandatoryArg: : name of the other flag to wait on" +"Example: flag_wait( "hq_cleared", "hq_destroyed" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_either( flag1, flag2 ) +{ + for ( ;; ) + { + if ( flag( flag1 ) ) + return; + if ( flag( flag2 ) ) + return; + + level waittill_either( flag1, flag2 ); + } +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_either_return( , )" +"Summary: Waits until either of the the specified flags are set, and returns the first one it found." +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of one flag to wait on" +"MandatoryArg: : name of the other flag to wait on" +"Example: flag_wait( "hq_cleared", "hq_destroyed" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_either_return( flag1, flag2 ) +{ + for ( ;; ) + { + if ( flag( flag1 ) ) + return flag1; + if ( flag( flag2 ) ) + return flag2; + + msg = level waittill_any_return( flag1, flag2 ); + return msg; + } +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_any( , , , , , )" +"Summary: Waits until any of the the specified flags are set." +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of a flag to wait on" +"MandatoryArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"Example: flag_wait_any( "hq_cleared", "hq_destroyed", "hq_overrun", "hq_skipped" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_any( flag1, flag2, flag3, flag4, flag5, flag6 ) +{ + array = []; + if ( isdefined( flag6 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + array[ array.size ] = flag5; + array[ array.size ] = flag6; + } + else if ( isdefined( flag5 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + array[ array.size ] = flag5; + } + else if ( isdefined( flag4 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + } + else if ( isdefined( flag3 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + } + else if ( isdefined( flag2 ) ) + { + flag_wait_either( flag1, flag2 ); + return; + } + else + { + assertmsg( "flag_wait_any() needs at least 2 flags passed to it" ); + return; + } + + for ( ;; ) + { + for ( i = 0; i < array.size; i++ ) + { + if ( flag( array[ i ] ) ) + return; + } + + level waittill_any( flag1, flag2, flag3, flag4, flag5, flag6 ); + } +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_any_return( , , , , , )" +"Summary: Waits until any of the the specified flags are set, and returns the first set flag that was found." +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of a flag to wait on" +"MandatoryArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"Example: returned = flag_wait_any_return( "hq_cleared", "hq_destroyed", "hq_overrun", "hq_skipped" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_any_return( flag1, flag2, flag3, flag4, flag5, flag6 ) +{ + array = []; + if ( isdefined( flag6 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + array[ array.size ] = flag5; + array[ array.size ] = flag6; + } + else if ( isdefined( flag5 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + array[ array.size ] = flag5; + } + else if ( isdefined( flag4 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + array[ array.size ] = flag4; + } + else if ( isdefined( flag3 ) ) + { + array[ array.size ] = flag1; + array[ array.size ] = flag2; + array[ array.size ] = flag3; + } + else if ( isdefined( flag2 ) ) + { + msg = flag_wait_either_return( flag1, flag2 ); + return msg; + } + else + { + assertmsg( "flag_wait_any_return() needs at least 2 flags passed to it" ); + return; + } + + for ( ;; ) + { + for ( i = 0; i < array.size; i++ ) + { + if ( flag( array[ i ] ) ) + return array[ i ]; + } + + msg = level waittill_any_return( flag1, flag2, flag3, flag4, flag5, flag6 ); + return msg; + } +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_all( , , , )" +"Summary: Waits until all of the the specified flags are set." +"Module: Flag" +"CallOn: " +"MandatoryArg: : name of a flag to wait on" +"MandatoryArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"OptionalArg: : name of a flag to wait on" +"Example: flag_wait_any( "hq_cleared", "hq_destroyed", "hq_overrun", "hq_skipped" );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_all( flag1, flag2, flag3, flag4 ) +{ + if ( isdefined( flag1 ) ) + flag_wait( flag1 ); + + if ( isdefined( flag2 ) ) + flag_wait( flag2 ); + + if ( isdefined( flag3 ) ) + flag_wait( flag3 ); + + if ( isdefined( flag4 ) ) + flag_wait( flag4 ); +} + + /* + ============= +///ScriptDocBegin +"Name: flag_wait_or_timeout( , )" +"Summary: Waits until either the flag gets set or the timer elapses." +"Module: Flag" +"CallOn: " +"MandatoryArg: : Amount of time to wait before continuing regardless of flag." +"Example: flag_wait_or_timeout( "time_to_go", 3 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flag_wait_or_timeout( flagname, timer ) +{ + timerMS = timer * 1000; + start_time = GetTime(); + + for ( ;; ) + { + if ( flag( flagname ) ) + { + break; + } + + if ( GetTime() >= start_time + timerMS ) + { + break; + } + + timeRemaining = timerMS - ( GetTime() - start_time ); // figure out how long we waited already, if at all + timeRemainingSecs = timeRemaining / 1000; + wait_for_flag_or_time_elapses( flagname, timeRemainingSecs ); + } +} + +/* +============= +///ScriptDocBegin +"Name: flag_waitopen_or_timeout( , )" +"Summary: Waits until either the flag gets cleared or the timer elapses." +"Module: Flag" +"CallOn: " +"MandatoryArg: : Amount of time to wait before continuing regardless of flag." +"Example: flag_waitopen_or_timeout( "time_to_go", 3 );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +flag_waitopen_or_timeout( flagname, timer ) +{ + start_time = gettime(); + for ( ;; ) + { + if ( !flag( flagname ) ) + break; + + if ( gettime() >= start_time + timer * 1000 ) + break; + + wait_for_flag_or_time_elapses( flagname, timer ); + } +} + +wait_for_flag_or_time_elapses( flagname, timer ) +{ + level endon( flagname ); + wait( timer ); +} + + + /* + ============= +///ScriptDocBegin +"Name: delayCall( , , , , )" +"Summary: delayCall is cool! It saves you from having to write extra script for once off commands. Note you don�t have to thread it off. delaycall is that smart!" +"Module: Utility" +"MandatoryArg: : The delay before the function occurs" +"MandatoryArg: : The function to run." +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"OptionalArg: : parameter 4 to pass to the process" +"Example: delayCall( ::flag_set, "player_can_rappel", 3 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +delayCall( timer, func, param1, param2, param3, param4 ) +{ + // to thread it off + thread delayCall_proc( func, timer, param1, param2, param3, param4 ); +} + +delayCall_proc( func, timer, param1, param2, param3, param4 ) +{ + if ( isSP() ) + self endon( "death" ); + + wait( timer ); + if ( isdefined( param4 ) ) + self call [[ func ]]( param1, param2, param3, param4 ); + else + if ( isdefined( param3 ) ) + self call [[ func ]]( param1, param2, param3 ); + else + if ( isdefined( param2 ) ) + self call [[ func ]]( param1, param2 ); + else + if ( isdefined( param1 ) ) + self call [[ func ]]( param1 ); + else + self call [[ func ]](); +} + + /* + ============= +///ScriptDocBegin +"Name: noself_delayCall( , , , , , )" +"Summary: Calls a command with no self (some commands don't support having self)." +"Module: Utility" +"MandatoryArg: : The delay before the function occurs" +"MandatoryArg: : The function to run." +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"OptionalArg: : parameter 4 to pass to the process" +"Example: noself_delayCall( ::setsaveddvar, "player_can_rappel", 1 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +noself_delayCall( timer, func, param1, param2, param3, param4 ) +{ + // to thread it off + thread noself_delayCall_proc( func, timer, param1, param2, param3, param4 ); +} + +noself_delayCall_proc( func, timer, param1, param2, param3, param4 ) +{ + wait( timer ); + if ( isdefined( param4 ) ) + call [[ func ]]( param1, param2, param3, param4 ); + else + if ( isdefined( param3 ) ) + call [[ func ]]( param1, param2, param3 ); + else + if ( isdefined( param2 ) ) + call [[ func ]]( param1, param2 ); + else + if ( isdefined( param1 ) ) + call [[ func ]]( param1 ); + else + call [[ func ]](); +} + + /* + ============= +///ScriptDocBegin +"Name: isSP()" +"Summary: Returns false if the level name begins with mp_" +"Module: Utility" +"Example: if ( isSP() );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +isSP() +{ + if ( !isdefined( level._isSP ) ) + level._isSP = !( string_starts_with( getdvar( "mapname" ), "mp_" ) ); + + return level._isSP; +} + + +/* +============= +///ScriptDocBegin +"Name: string_starts_with( , )" +"Summary: Returns true if the first string begins with the first string" +"Module: Utility" +"CallOn:" +"MandatoryArg: String to check" +"MandatoryArg: Beginning of string to check" +"Example: if ( string_starts_with( "somestring", "somest" ) )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +string_starts_with( string, start ) +{ + assert( isdefined( string ) ); + assert( isdefined( start ) ); + if ( string.size < start.size ) + return false; + + for ( i = 0 ; i < start.size ; i++ ) + { + if ( tolower( string[ i ] ) != tolower( start[ i ] ) ) + return false; + } + + return true; +} + +plot_points( plotpoints, r, g, b, timer ) +{ + lastpoint = plotpoints[ 0 ]; + if ( !isdefined( r ) ) + r = 1; + if ( !isdefined( g ) ) + g = 1; + if ( !isdefined( b ) ) + b = 1; + if ( !isdefined( timer ) ) + timer = 0.05; + for ( i = 1;i < plotpoints.size;i++ ) + { + thread draw_line_for_time( lastpoint, plotpoints[ i ], r, g, b, timer ); + lastpoint = plotpoints[ i ]; + } +} + + + /* + ============= +///ScriptDocBegin +"Name: draw_line_for_time( , , , , , )" +"Summary: Draws a line from < org1 > to < org2 > in the specified color for the specified duration" +"Module: Debug" +"CallOn: " +"MandatoryArg: : starting origin for the line" +"MandatoryArg: : ending origin for the line" +"MandatoryArg: : red color value( 0 to 1 )" +"MandatoryArg: : green color value( 0 to 1 )" +"MandatoryArg: : blue color value( 0 to 1 )" +"MandatoryArg: : time in seconds the line should last" +"Example: thread draw_line_for_time( level.player.origin, vehicle.origin, 1, 0, 0, 10.0 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +draw_line_for_time( org1, org2, r, g, b, timer ) +{ + timer = gettime() + ( timer * 1000 ); + while ( gettime() < timer ) + { + line( org1, org2, ( r, g, b ), 1 ); + wait .05; + } + +} + + + /* + ============= +///ScriptDocBegin +"Name: array_combine( , )" +"Summary: Combines the two arrays and returns the resulting array. This function doesn't care if it produces duplicates in the array." +"Module: Array" +"CallOn: " +"MandatoryArg: : first array" +"MandatoryArg: : second array" +"Example: combinedArray = array_combine( array1, array2 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +array_combine( array1, array2 ) +{ + array3 = []; + foreach ( item in array1 ) + { + array3[ array3.size ] = item; + } + foreach ( item in array2 ) + { + array3[ array3.size ] = item; + } + return array3; +} + + + /* + ============= +///ScriptDocBegin +"Name: flat_angle( )" +"Summary: Returns the specified angle as a flat angle.( 45, 90, 30 ) becomes( 0, 90, 30 ). Useful if you just need an angle around Y - axis." +"Module: Vector" +"CallOn: " +"MandatoryArg: : angles to flatten" +"Example: yaw = flat_angle( node.angles );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flat_angle( angle ) +{ + rangle = ( 0, angle[ 1 ], 0 ); + return rangle; +} + + /* + ============= +///ScriptDocBegin +"Name: flat_origin( )" +"Summary: Returns a flat origin of the specified origin. Moves Z corrdinate to 0.( x, y, z ) becomes( x, y, 0 )" +"Module: Vector" +"CallOn: " +"MandatoryArg: : origin to flatten" +"Example: org = flat_origin( self.origin );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +flat_origin( org ) +{ + rorg = ( org[ 0 ], org[ 1 ], 0 ); + return rorg; + +} + + /* + ============= +///ScriptDocBegin +"Name: draw_arrow_time( , , , )" +"Summary: Draws an arrow pointing at < end > in the specified color for < duration > seconds." +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : starting coordinate for the arrow" +"MandatoryArg: : ending coordinate for the arrow" +"MandatoryArg: :( r, g, b ) color array for the arrow" +"MandatoryArg: : time in seconds to draw the arrow" +"Example: thread draw_arrow_time( lasttarg.origin, targ.origin, ( 0, 0, 1 ), 5.0 );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +draw_arrow_time( start, end, color, duration ) +{ + level endon( "newpath" ); + pts = []; + angles = vectortoangles( start - end ); + right = anglestoright( angles ); + forward = anglestoforward( angles ); + up = anglestoup( angles ); + + dist = distance( start, end ); + arrow = []; + range = 0.1; + + arrow[ 0 ] = start; + arrow[ 1 ] = start + vector_multiply( right, dist * ( range ) ) + vector_multiply( forward, dist * - 0.1 ); + arrow[ 2 ] = end; + arrow[ 3 ] = start + vector_multiply( right, dist * ( -1 * range ) ) + vector_multiply( forward, dist * - 0.1 ); + + arrow[ 4 ] = start; + arrow[ 5 ] = start + vector_multiply( up, dist * ( range ) ) + vector_multiply( forward, dist * - 0.1 ); + arrow[ 6 ] = end; + arrow[ 7 ] = start + vector_multiply( up, dist * ( -1 * range ) ) + vector_multiply( forward, dist * - 0.1 ); + arrow[ 8 ] = start; + + r = color[ 0 ]; + g = color[ 1 ]; + b = color[ 2 ]; + + plot_points( arrow, r, g, b, duration ); +} + + +/* +============= +///ScriptDocBegin +"Name: get_linked_ents()" +"Summary: Returns an array of entities that SELF is linked to" +"Module: Utility" +"CallOn: An entity that links to other entities" +"Example: spawners = heli get_linked_ents()" +"SPMP: both" +///ScriptDocEnd +============= +*/ +get_linked_ents() +{ + array = []; + + if ( isdefined( self.script_linkto ) ) + { + linknames = get_links(); + foreach ( name in linknames ) + { + entities = getentarray( name, "script_linkname" ); + if ( entities.size > 0 ) + array = array_combine( array, entities ); + } + } + + return array; +} + +/* +============= +///ScriptDocBegin +"Name: get_linked_ent()" +"Summary: Returns a single entity that SELF is linked to" +"Module: Utility" +"CallOn: An entity that links to another entity" +"Example: spawner = heli get_linked_ent()" +"SPMP: both" +///ScriptDocEnd +============= +*/ +get_linked_ent() +{ + array = get_linked_ents(); + assert( array.size == 1 ); + assert( isdefined( array[ 0 ] ) ); + return array[ 0 ]; +} + + +/* +============= +///ScriptDocBegin +"Name: get_links( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +get_links() +{ + return strtok( self.script_linkTo, " " ); +} + + + +/* +============= +///ScriptDocBegin +"Name: run_thread_on_targetname( , , , , )" +"Summary: Runs the specified thread on any entity with that targetname" +"Module: Utility" +"MandatoryArg: : The targetname" +"MandatoryArg: : The function" +"OptionalArg: : Optional argument" +"OptionalArg: : Optional argument" +"OptionalArg: : Optional argument" +"Example: run_thread_on_targetname( "chopper_guys", ::add_spawn_function, ::chopper_guys_land );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +run_thread_on_targetname( msg, func, param1, param2, param3 ) +{ + array = getentarray( msg, "targetname" ); + array_thread( array, func, param1, param2, param3 ); + + array = getstructarray( msg, "targetname" ); + array_thread( array, func, param1, param2, param3 ); + + array = call [[ level._getNodeArrayFunction ]]( msg, "targetname" ); + array_thread( array, func, param1, param2, param3 ); + + array = getvehiclenodearray( msg, "targetname" ); + array_thread( array, func, param1, param2, param3 ); +} + + +/* +============= +///ScriptDocBegin +"Name: run_thread_on_noteworthy( , , , , )" +"Summary: Runs the specified thread on any entity with that noteworthy" +"Module: Utility" +"MandatoryArg: : The noteworthy" +"MandatoryArg: : The function" +"OptionalArg: : Optional argument" +"OptionalArg: : Optional argument" +"OptionalArg: : Optional argument" +"Example: run_thread_on_noteworthy( "chopper_guys", ::add_spawn_function, ::chopper_guys_land );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + + +run_thread_on_noteworthy( msg, func, param1, param2, param3 ) +{ + array = getentarray( msg, "script_noteworthy" ); + array_thread( array, func, param1, param2, param3 ); + + array = getstructarray( msg, "script_noteworthy" ); + array_thread( array, func, param1, param2, param3 ); + + array = call [[ level._getNodeArrayFunction ]]( msg, "script_noteworthy" ); + array_thread( array, func, param1, param2, param3 ); + + array = getvehiclenodearray( msg, "script_noteworthy" ); + array_thread( array, func, param1, param2, param3 ); +} + + + /* + ============= +///ScriptDocBegin +"Name: draw_arrow( , , )" +"Summary: Draws an arrow pointing at < end > in the specified color for < duration > seconds." +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : starting coordinate for the arrow" +"MandatoryArg: : ending coordinate for the arrow" +"MandatoryArg: :( r, g, b ) color array for the arrow" +"Example: draw_arrow( lasttarg.origin, targ.origin, ( 0, 0, 1 ));" +"SPMP: both" +///ScriptDocEnd + ============= + */ + +draw_arrow( start, end, color ) +{ + level endon( "newpath" ); + pts = []; + angles = vectortoangles( start - end ); + right = anglestoright( angles ); + forward = anglestoforward( angles ); + + dist = distance( start, end ); + arrow = []; + range = 0.05; + arrow[ 0 ] = start; + arrow[ 1 ] = start + vector_multiply( right, dist * ( range ) ) + vector_multiply( forward, dist * - 0.2 ); + arrow[ 2 ] = end; + arrow[ 3 ] = start + vector_multiply( right, dist * ( -1 * range ) ) + vector_multiply( forward, dist * - 0.2 ); + + for ( p = 0;p < 4;p++ ) + { + nextpoint = p + 1; + if ( nextpoint >= 4 ) + nextpoint = 0; + line( arrow[ p ], arrow[ nextpoint ], color, 1.0 ); + } +} + +/* +============= +///ScriptDocBegin +"Name: cap_value( value, minValue, maxValue )" +"Summary: Caps a number value within a range" +"Module: Utility" +"MandatoryArg: : the int or float to cap" +"OptionalArg: : minimum allowed value" +"OptionalArg: : maximum allowed value" +"Example: number = cap_value( number, 0.1, 2.0 );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +cap_value( value, minValue, maxValue ) +{ + assert( isdefined( value ) ); + + // handle a min value larger than a max value + if ( minValue > maxValue ) + return cap_value( value, maxValue, minValue ); + + assert( minValue <= maxValue ); + + if ( isdefined( minValue ) && ( value < minValue ) ) + return minValue; + + if ( isdefined( maxValue ) && ( value > maxValue ) ) + return maxValue; + + return value; +} + +/* +============= +///ScriptDocBegin +"Name: getfx( )" +"Summary: Gets the associated level._effect" +"Module: Utility" +"MandatoryArg: : The effect" +"Example: playfx ( getfx( "heli_dust_default" ), eOrgFx.origin + offset ); " +"SPMP: both" +///ScriptDocEnd +============= +*/ +getfx( fx ) +{ + assertEx( isdefined( level._effect[ fx ] ), "Fx " + fx + " is not defined in level._effect." ); + return level._effect[ fx ]; +} + +/* +============= +///ScriptDocBegin +"Name: fxExists( )" +"Summary: Returns whether or not an fx exists" +"Module: Utility" +"MandatoryArg: : The effect" +"Example: if ( fxExists( "blah" ) )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +fxExists( fx ) +{ + return isdefined( level._effect[ fx ] ); +} + +print_csv_asset( asset, type ) +{ + fileline = type + "," + asset; + if ( isdefined( level._csv_lines[ fileline ] ) ) + return; + level._csv_lines[ fileline ] = true; +// fileprint_chk( level.fileprint, fileline ); +} + +fileprint_csv_start( file ) +{ + /# + file = "scriptgen/" + file + ".csv"; + level._csv_lines = []; + #/ +} + +_loadfx( effect ) +{ + return loadfx( effect ); +} + + + +/* +============= +///ScriptDocBegin +"Name: getLastWeapon( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +getLastWeapon() +{ + assert( isDefined( self.saved_lastWeapon ) ); + + return self.saved_lastWeapon; +} + + +/* +============= +///ScriptDocBegin +"Name: PlayerUnlimitedAmmoThread()" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +PlayerUnlimitedAmmoThread() +{ + /# + if ( !isdefined( self ) || self == level || self.code_classname != "player" ) + player = level._player; + else + player = self; + + assert( isdefined( player ) ); + + while ( 1 ) + { + wait .5; + + if ( getdvar( "UnlimitedAmmoOff" ) == "1" ) + continue; + + currentWeapon = player getCurrentWeapon(); + if ( currentWeapon != "none" ) + { + currentAmmo = player GetFractionMaxAmmo( currentWeapon ); + if ( currentAmmo < 0.2 ) + player GiveMaxAmmo( currentWeapon ); + } + currentoffhand = player GetCurrentOffhand(); + if ( currentoffhand != "none" ) + { + currentAmmo = player GetFractionMaxAmmo( currentoffhand ); + if ( currentAmmo < 0.4 ) + player GiveMaxAmmo( currentoffhand ); + } + } + #/ +} + + +isUsabilityEnabled() +{ + return ( !self.disabledUsability ); +} + + +_disableUsability() +{ + self.disabledUsability++; + self DisableUsability(); +} + + +_enableUsability() +{ + self.disabledUsability--; + + assert( self.disabledUsability >= 0 ); + + if ( !self.disabledUsability ) + self EnableUsability(); +} + + +resetUsability() +{ + self.disabledUsability = 0; + self EnableUsability(); +} + + +_disableWeapon() +{ + self.disabledWeapon++; + self disableWeapons(); +} + +_enableWeapon() +{ + self.disabledWeapon--; + + assert( self.disabledWeapon >= 0 ); + + if ( !self.disabledWeapon ) + self enableWeapons(); +} + +isWeaponEnabled() +{ + return ( !self.disabledWeapon ); +} + + +_disableWeaponSwitch() +{ + self.disabledWeaponSwitch++; + self disableWeaponSwitch(); +} + +_enableWeaponSwitch() +{ + self.disabledWeaponSwitch--; + + assert( self.disabledWeaponSwitch >= 0 ); + + if ( !self.disabledWeaponSwitch ) + self enableWeaponSwitch(); +} + +isWeaponSwitchEnabled() +{ + return ( !self.disabledWeaponSwitch ); +} + + +_disableOffhandWeapons() +{ + self.disabledOffhandWeapons++; + self DisableOffhandWeapons(); +} + +_enableOffhandWeapons() +{ + self.disabledOffhandWeapons--; + + assert( self.disabledOffhandWeapons >= 0 ); + + if ( !self.disabledOffhandWeapons ) + self EnableOffhandWeapons(); +} + +isOffhandWeaponEnabled() +{ + return ( !self.disabledOffhandWeapons ); +} + + +/* +============= +///ScriptDocBegin +"Name: random( )" +"Summary: chose a random element of an array" +"Module: Array" +"CallOn: Level" +"MandatoryArg: : " +"Example: select_spot = random( array );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +random( array ) +{ + // process the array so it'll work with any string index arrays and arrays with missing entries. + newarray = []; + foreach ( index, value in array ) + { + newarray[ newarray.size ] = value; + } + + if ( !newarray.size ) + return undefined; + + return newarray[ randomint( newarray.size ) ]; +} + + +/* +============= +///ScriptDocBegin +"Name: spawn_tag_origin()" +"Summary: Spawn a script model with tag_origin model" +"Module: Utility" +"Example: ent = spawn_tag_origin();" +"SPMP: both" +///ScriptDocEnd +============= +*/ +spawn_tag_origin() +{ + tag_origin = spawn( "script_model", ( 0, 0, 0 ) ); + tag_origin setmodel( "tag_origin" ); + tag_origin hide(); + if ( isdefined( self.origin ) ) + tag_origin.origin = self.origin; + if ( isdefined( self.angles ) ) + tag_origin.angles = self.angles; + + return tag_origin; +} + +/* +============= +///ScriptDocBegin +"Name: show_level_notes( )" +"Summary: Show or hide the designer notes for this level. To create a note in Radiant, give an entity the KVP ( note_message, YOUR_MESSAGE ). + KVPs that can be used with level notes: + + - note_message: The message to display. + + Optional: + - note_color: The color of the text. Defaults to (1, 1, 1). + - note_offset: Positional offset of where the message will print. Defaults to the entity's origin. + - note_alpha: Opacity (0.0 to 1.0) of the note displayed when show_level_notes is called. Defaults to 1.0 + - note_scale: The size of the text. Defaults to 1.0. + +"Module: Utility" +"MandatoryArg: : True or false." +"Example: show_level_notes( true ); // Show the designer notes in this level. + show_level_notes( false ); // Hide the designer notes in this level." +"SPMP: both" +///ScriptDocEnd +============= +*/ +show_level_notes( enable ) +{ + if( enable ) + { + level thread level_notes_update(); + } + else + { + level notify( "level_notes_stop" ); + } +} + +level_notes_update() +{ + self endon( "level_notes_stop" ); + + interval = 0.033; + + ents = GetEntArray(); + noted_ents = []; + + foreach( ent in ents ) + { + if( IsDefined( ent.note_message ) ) + noted_ents[ noted_ents.size ] = ent; + } + + if( noted_ents.size == 0 ) + return; + + while( 1 ) + { + foreach( ent in noted_ents ) + { + if ( !IsDefined( ent ) ) + { + noted_ents = array_remove( noted_ents, ent ); + continue; + } + + offset = ( 0, 0, 0 ); + message = ent.note_message; + color = ( 1, 1, 1 ); + scale = 1.0; + alpha = 1.0; + + if( IsDefined( ent.note_offset ) ) + offset = ent.note_offset; + + if( IsDefined( ent.note_color ) ) + color = ent.note_color; + + if( IsDefined( ent.note_alpha ) ) + alpha = ent.note_alpha; + + if( IsDefined( ent.note_scale ) ) + scale = ent.note_scale; + + Print3D( ent.origin + offset, message, color, alpha, scale ); + } + + wait interval; + } +} + + +/* +============= +///ScriptDocBegin +"Name: waittill_notify_or_timeout( , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +waittill_notify_or_timeout( msg, timer ) +{ + self endon( msg ); + wait( timer ); +} + +/* +============= +///ScriptDocBegin +"Name: fileprint_launcher_start_file()" +"Summary: Tells Launcher to start storing text to a file. Use in conjunction with fileprint_launcher() and fileprint_launcher_end_file() to append to that file and then instruct launcher to write the file." +"Module: Print" +"CallOn: Level" +"Example: fileprint_launcher_start_file();" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +fileprint_launcher_start_file() +{ + AssertEx( ! isdefined( level._fileprint_launcher ), "Can't open more than one file at a time to print through launcher." ); + level._fileprintlauncher_linecount = 0; + level._fileprint_launcher = true; + fileprint_launcher( "GAMEPRINTSTARTFILE:" ); +} + +/* +============= +///ScriptDocBegin +"Name: fileprint_launcher( )" +"Summary: Tell launcher to append text to current open file created by fileprint_launcher_start_file(), to be closed and written with fileprint_launcher_end_file() " +"Module: Print" +"CallOn: Level" +"MandatoryArg: : " +"Example: fileprint_launcher( "main()" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +fileprint_launcher( string ) +{ + assert( isdefined( level._fileprintlauncher_linecount ) ); + level._fileprintlauncher_linecount++; + if( level._fileprintlauncher_linecount > 200 ) + { + wait .05; + level._fileprintlauncher_linecount = 0; + } + println( "LAUNCHERPRINTLN:" + string ); +} + + +/* +============= +///ScriptDocBegin +"Name: fileprint_launcher_end_file( , )" +"Summary: Tell launcher to write out Text that has been started and appended to using fileprint_launcher_start_file() and fileprint_launcher(). you must end a file before you can start a new one." +"Module: Print" +"CallOn: Level" +"MandatoryArg: : " +"OptionalArg: : " +"Example: fileprint_launcher_end_file( "\\share\\raw\\maps\\createart\\" + level.script + "_art.gsc, true );" +"SPMP: both" +///ScriptDocEnd +============= +*/ + +fileprint_launcher_end_file( file_relative_to_game, bIsPerforceEnabled ) +{ + if( !isdefined( bIsPerforceEnabled ) ) + bIsPerforceEnabled = false; + + setDevDvarIfUninitialized("LAUNCHER_PRINT_FAIL", "0"); + setDevDvarIfUninitialized("LAUNCHER_PRINT_SUCCESS", "0"); + + if( bIsPerforceEnabled ) + fileprint_launcher( "GAMEPRINTENDFILE:GAMEPRINTP4ENABLED:"+file_relative_to_game ); + else + fileprint_launcher( "GAMEPRINTENDFILE:"+file_relative_to_game ); + + // wait for launcher to tell us that it's done writing the file + TimeOut = gettime()+4000; // give launcher 4 seconds to print the file. + while( getdvarint( "LAUNCHER_PRINT_SUCCESS" ) == 0 && getdvar( "LAUNCHER_PRINT_FAIL" ) == "0" && gettime() < TimeOut ) + wait .05; + + if( ! ( gettime() < TimeOut ) ) + { + iprintlnbold("LAUNCHER_PRINT_FAIL:( TIMEOUT ): launcherconflict? restart launcher and try again? " ); + setdevdvar("LAUNCHER_PRINT_FAIL", "0"); + level._fileprint_launcher = undefined; + return false; + } + + failvar = getdvar("LAUNCHER_PRINT_FAIL"); + if( failvar != "0" ) + { + iprintlnbold("LAUNCHER_PRINT_FAIL:( "+ failvar + " ): launcherconflict? restart launcher and try again? " ); + setdevdvar("LAUNCHER_PRINT_FAIL", "0"); + level._fileprint_launcher = undefined; + return false; + } + + successvar = getdvar("LAUNCHER_PRINT_SUCCESS"); + if( successvar != "0" ) + { + iprintlnbold("LAUNCHER_PRINT_SUCCESS: " + file_relative_to_game + " updated! " ); + } + + setdevdvar("LAUNCHER_PRINT_FAIL", "0"); + setdevdvar( "LAUNCHER_PRINT_SUCCESS", "0" ); + + level._fileprint_launcher = undefined; + return true; +} + +/* +============= +///ScriptDocBegin +"Name: launcher_write_clipboard( )" +"Summary: send a string to your Connected PC's clipboard through launcher" +"Module: Print" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: launcher_write_clipboard( Players_origin_string )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +launcher_write_clipboard( str ) +{ + level._fileprintlauncher_linecount = 0; + fileprint_launcher( "LAUNCHER_CLIP:" + str ); +} + +/* +============= +///ScriptDocBegin +"Name: isDestructible()" +"Summary: returns true if self is a destructible" +"Module: Entity" +"CallOn: An entity" +"Example: if ( self isDestructible() )" +"SPMP: both" +///ScriptDocEnd +============= +*/ +isDestructible() +{ + if ( !isdefined( self ) ) + return false; + return isdefined( self.destructible_type ); +} + +/* +============= +///ScriptDocBegin +"Name: pauseEffect( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +pauseEffect() +{ + common_scripts\_createfx::stop_fx_looper(); +} + +/* +============= +///ScriptDocBegin +"Name: activate_individual_exploder()" +"Summary: Activates an individual exploder, rather than all the exploders of a given number" +"Module: Utility" +"CallOn: An exploder" +"Example: exploder activate_individual_exploder();" +"SPMP: both" +///ScriptDocEnd +============= +*/ +activate_individual_exploder() +{ + if ( IsDefined( self.v[ "firefx" ] ) ) + self thread fire_effect(); + + if ( IsDefined( self.v[ "fxid" ] ) && self.v[ "fxid" ] != "No FX" ) + self thread cannon_effect(); + else + if ( IsDefined( self.v[ "soundalias" ] ) && self.v[ "soundalias" ] != "nil" ) + self thread sound_effect(); + + if ( IsDefined( self.v[ "loopsound" ] ) && self.v[ "loopsound" ] != "nil" ) + self thread effect_loopsound(); + + if ( IsDefined( self.v[ "damage" ] ) ) + self thread exploder_damage(); + + if ( IsDefined( self.v[ "earthquake" ] ) ) + self thread exploder_earthquake(); + + if ( IsDefined( self.v[ "rumble" ] ) ) + self thread exploder_rumble(); + + if ( self.v[ "exploder_type" ] == "exploder" ) + self thread brush_show(); + else + if ( ( self.v[ "exploder_type" ] == "exploderchunk" ) || ( self.v[ "exploder_type" ] == "exploderchunk visible" ) ) + self thread brush_throw(); + else + self thread brush_delete(); +} + +waitframe() +{ + wait( 0.05 ); +} + +brush_delete() +{ +// if( ent.v[ "exploder_type" ] != "normal" && !isdefined( ent.v[ "fxid" ] ) && !isdefined( ent.v[ "soundalias" ] ) ) +// if( !isdefined( ent.script_fxid ) ) + + num = self.v[ "exploder" ]; + if ( IsDefined( self.v[ "delay" ] ) ) + wait( self.v[ "delay" ] ); + else + wait( .05 );// so it disappears after the replacement appears + + if ( !isdefined( self.model ) ) + return; + + + Assert( IsDefined( self.model ) ); + + if ( isSP() && ( self.model.spawnflags & 1 ) ) + self.model call [[ level._connectPathsFunction ]](); + + if ( level._createFX_enabled ) + { + if ( IsDefined( self.exploded ) ) + return; + + self.exploded = true; + self.model Hide(); + self.model NotSolid(); + + wait( 3 ); + self.exploded = undefined; + self.model Show(); + self.model Solid(); + return; + } + + if ( !isdefined( self.v[ "fxid" ] ) || self.v[ "fxid" ] == "No FX" ) + self.v[ "exploder" ] = undefined; + + waittillframeend;// so it hides stuff after it shows the new stuff + self.model Delete(); +} + +brush_throw() +{ + if ( IsDefined( self.v[ "delay" ] ) ) + wait( self.v[ "delay" ] ); + + ent = undefined; + if ( IsDefined( self.v[ "target" ] ) ) + ent = get_target_ent( self.v[ "target" ] ); + + if ( !isdefined( ent ) ) + { + self.model Delete(); + return; + } + + self.model Show(); + + if ( IsDefined( self.v[ "delay_post" ] ) ) + wait( self.v[ "delay_post" ] ); + + startorg = self.v[ "origin" ]; + startang = self.v[ "angles" ]; + org = ent.origin; + + temp_vec = ( org - self.v[ "origin" ] ); + x = temp_vec[ 0 ]; + y = temp_vec[ 1 ]; + z = temp_vec[ 2 ]; + + physics = IsDefined( self.v[ "physics" ] ); + if ( physics ) + { + target = undefined; + if ( IsDefined( ent.target ) ) + target = ent get_target_ent(); + + if ( !isdefined( target ) ) + { + contact_point = startorg;// no spin just push it. + throw_vec = ent.origin; + } + else + { + contact_point = ent.origin; + throw_vec = vector_multiply( target.origin - ent.origin, self.v[ "physics" ] ); + + } + +// model = Spawn( "script_model", startorg ); +// model.angles = startang; +// model PhysicsLaunchClient( model.origin, temp_vec ); + self.model PhysicsLaunchClient( contact_point, throw_vec ); + return; + } + else + { + self.model RotateVelocity( ( x, y, z ), 12 ); + self.model MoveGravity( ( x, y, z ), 12 ); + } + + if ( level._createFX_enabled ) + { + if ( IsDefined( self.exploded ) ) + return; + + self.exploded = true; + wait( 3 ); + self.exploded = undefined; + self.v[ "origin" ] = startorg; + self.v[ "angles" ] = startang; + self.model Hide(); + return; + } + + self.v[ "exploder" ] = undefined; + wait( 6 ); + self.model Delete(); +// self Delete(); +} + +/* +============= +///ScriptDocBegin +"Name: get_target_ent( )" +"Summary: Returns whatever SINGLE ent is targetted, be it node, struct, or entity" +"Module: Utility" +"OptionalArg: : Optional target override" +"Example: node = guy get_target_ent();" +"SPMP: both" +///ScriptDocEnd +============= +*/ +get_target_ent( target ) +{ + if ( !isdefined( target ) ) + target = self.target; + + AssertEx( IsDefined( target ), "Self had no target!" ); + + ent = GetEnt( target, "targetname" ); + if ( IsDefined( ent ) ) + return ent; + + if ( isSP() ) + { + ent = call [[ level._getNodeFunction ]]( target, "targetname" ); + if ( IsDefined( ent ) ) + return ent; + } + + ent = getstruct( target, "targetname" ); + if ( IsDefined( ent ) ) + return ent; + + ent = GetVehicleNode( target, "targetname" ); + if ( IsDefined( ent ) ) + return ent; + + AssertEx( "Tried to get ent, but there was no ent." ); +} + +brush_show() +{ + if ( IsDefined( self.v[ "delay" ] ) ) + wait( self.v[ "delay" ] ); + + Assert( IsDefined( self.model ) ); + + self.model Show(); + self.model Solid(); + + self.brush_shown = true; // used for hiding an exploder. + + if ( isSP() && ( self.model.spawnflags & 1 ) ) + { + if ( !isdefined( self.model.disconnect_paths ) ) + self.model call [[ level._connectPathsFunction ]](); + else + self.model call [[ level._disconnectPathsFunction ]](); + } + + if ( level._createFX_enabled ) + { + if ( IsDefined( self.exploded ) ) + return; + + self.exploded = true; + wait( 3 ); + self.exploded = undefined; + self.model Hide(); + self.model NotSolid(); + } +} + +exploder_earthquake() +{ + self exploder_delay(); + eq = level._earthquake[ self.v[ "earthquake" ] ]; + Earthquake( eq[ "magnitude" ], eq[ "duration" ], self.v[ "origin" ], eq[ "radius" ] ); +} + +exploder_rumble() +{ + if ( !isSP() ) + return; + + self exploder_delay(); + level._player PlayRumbleOnEntity( self.v[ "rumble" ] ); +} + +exploder_delay() +{ + if ( !isdefined( self.v[ "delay" ] ) ) + self.v[ "delay" ] = 0; + + min_delay = self.v[ "delay" ]; + max_delay = self.v[ "delay" ] + 0.001;// cant randomfloatrange on the same # + if ( IsDefined( self.v[ "delay_min" ] ) ) + min_delay = self.v[ "delay_min" ]; + + if ( IsDefined( self.v[ "delay_max" ] ) ) + max_delay = self.v[ "delay_max" ]; + + if ( min_delay > 0 ) + wait( RandomFloatRange( min_delay, max_delay ) ); +} + +exploder_damage() +{ + if ( IsDefined( self.v[ "delay" ] ) ) + delay = self.v[ "delay" ]; + else + delay = 0; + + if ( IsDefined( self.v[ "damage_radius" ] ) ) + radius = self.v[ "damage_radius" ]; + else + radius = 128; + + damage = self.v[ "damage" ]; + origin = self.v[ "origin" ]; + + wait( delay ); + // Range, max damage, min damage + RadiusDamage( origin, radius, damage, damage ); +} + +effect_loopsound() +{ + if ( IsDefined( self.loopsound_ent ) ) + { + self.loopsound_ent Delete(); + } + // save off this info in case we delete the effect + origin = self.v[ "origin" ]; + alias = self.v[ "loopsound" ]; + self exploder_delay(); + + self.loopsound_ent = play_loopsound_in_space( alias, origin ); +} + +/* + ============= +///ScriptDocBegin +"Name: play_loopsound_in_space( , , )" +"Summary: Use the PlayLoopSound command at a position in space. Unrelated to caller." +"Module: Sound" +"CallOn: Level" +"MandatoryArg: : Sound alias to play" +"MandatoryArg: : Origin of the sound" +"Example: play_loopsound_in_space( "siren", level.speaker.origin );" +"SPMP: both" +///ScriptDocEnd + ============= + */ +play_loopsound_in_space( alias, origin ) +{ + org = Spawn( "sound_emitter", ( 0, 0, 0 ) ); + if ( !isdefined( origin ) ) + origin = self.origin; + + org.origin = origin; + + org PlayLoopSound( alias, "sounddone" ); + return org; +} + +sound_effect() +{ + self effect_soundalias(); +} + +effect_soundalias() +{ + // save off this info in case we delete the effect + origin = self.v[ "origin" ]; + alias = self.v[ "soundalias" ]; + self exploder_delay(); + play_sound_in_space( alias, origin ); +} + +/* + ============= +///ScriptDocBegin +"Name: play_sound_in_space( , , )" +"Summary: Play a sound at an origin, unrelated to caller" +"Module: Sound" +"CallOn: Level" +"MandatoryArg: : Sound alias to play" +"MandatoryArg: : Origin of the sound" +"OptionalArg: : Play this sound as a master sound. Defaults to false" +"Example: play_sound_in_space( "siren", level.speaker.origin );" +"SPMP: singleplayer" +///ScriptDocEnd + ============= + */ +play_sound_in_space( alias, origin, master ) +{ + org = Spawn( "sound_emitter", ( 0, 0, 1 ) ); + if ( !isdefined( origin ) ) + origin = self.origin; + org.origin = origin; + if ( isSP() ) + { + if ( IsDefined( master ) && master ) + org PlaySoundAsMaster( alias, "sounddone" ); + else + org PlaySound( alias, "sounddone" ); + } + else + { + if ( IsDefined( master ) && master ) + org PlaySoundAsMaster( alias ); + else + org PlaySound( alias ); + } + org waittill( "sounddone" ); + org Delete(); +} + +cannon_effect() +{ + if ( IsDefined( self.v[ "repeat" ] ) ) + { + thread exploder_playSound(); + for ( i = 0; i < self.v[ "repeat" ]; i++ ) + { + PlayFX( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] ); + self exploder_delay(); + } + return; + } + self exploder_delay(); + +// PlayFX( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] ); + if ( IsDefined( self.looper ) ) + self.looper Delete(); + + self.looper = SpawnFx( getfx( self.v[ "fxid" ] ), self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] ); + TriggerFX( self.looper ); + exploder_playSound(); +} + +exploder_playSound() +{ + if ( !isdefined( self.v[ "soundalias" ] ) || self.v[ "soundalias" ] == "nil" ) + return; + + play_sound_in_space( self.v[ "soundalias" ], self.v[ "origin" ] ); +} + +fire_effect() +{ + forward = self.v[ "forward" ]; + up = self.v[ "up" ]; + + org = undefined; + + firefxSound = self.v[ "firefxsound" ]; + origin = self.v[ "origin" ]; + firefx = self.v[ "firefx" ]; + ender = self.v[ "ender" ]; + if ( !isdefined( ender ) ) + ender = "createfx_effectStopper"; + timeout = self.v[ "firefxtimeout" ]; + + fireFxDelay = 0.5; + if ( IsDefined( self.v[ "firefxdelay" ] ) ) + fireFxDelay = self.v[ "firefxdelay" ]; + + self exploder_delay(); + + if ( IsDefined( firefxSound ) ) + level thread loop_fx_sound( firefxSound, origin, ender, timeout ); + + PlayFX( level._effect[ firefx ], self.v[ "origin" ], forward, up ); + +// loopfx( fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout ) +// maps\_fx::loopfx( firefx, origin, delay, org, undefined, ender, timeout ); +} + +/* +============= +///ScriptDocBegin +"Name: loop_fx_sound( , , , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +loop_fx_sound( alias, origin, ender, timeout ) +{ + org = Spawn( "sound_emitter", ( 0, 0, 0 ) ); + if ( IsDefined( ender ) ) + { + thread loop_sound_delete( ender, org ); + self endon( ender ); + } + org.origin = origin; + org PlayLoopSound( alias ); + if ( !isDefined( timeout ) && !level._createFX_enabled ) + { + org willNeverChange(); + return; + } + + if ( isDefined( timeout ) ) + wait( timeout ); +// org Delete(); +} + +/* +============= +///ScriptDocBegin +"Name: loop_sound_delete( , )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +loop_sound_delete( ender, ent ) +{ + ent endon( "death" ); + self waittill( ender ); + ent Delete(); +} + +exploder_before_load( num ) +{ + // gotta wait twice because the createfx_init function waits once then inits all exploders. This guarentees + // that if an exploder is run on the first frame, it happens after the fx are init. + waittillframeend; + waittillframeend; + activate_exploder( num ); +} + +exploder_after_load( num ) +{ + activate_exploder( num ); +} + +/* +============= +///ScriptDocBegin +"Name: activate_exploder( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +activate_exploder( num ) +{ + num += ""; + + prof_begin( "activate_exploder" ); + + //here's a hook so you can know when a certain number of an exploder is going off + level notify( "exploding_" + num ); + + for ( i = 0;i < level._createFXent.size;i++ ) + { + ent = level._createFXent[ i ]; + if ( !isdefined( ent ) ) + continue; + + if ( ent.v[ "type" ] != "exploder" ) + continue; + + // make the exploder actually removed the array instead? + if ( !isdefined( ent.v[ "exploder" ] ) ) + continue; + + if ( ent.v[ "exploder" ] + "" != num ) + continue; + + ent activate_individual_exploder(); + } + prof_end( "activate_exploder" ); +} + +/* +============= +///ScriptDocBegin +"Name: createLoopEffect( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +createLoopEffect( fxid ) +{ + ent = common_scripts\_createfx::createEffect( "loopfx", fxid ); + ent.v[ "delay" ] = 0.5; + return ent; +} + +/* +============= +///ScriptDocBegin +"Name: createOneshotEffect( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +createOneshotEffect( fxid ) +{ + // uses triggerfx + ent = common_scripts\_createfx::createEffect( "oneshotfx", fxid ); + ent.v[ "delay" ] = -15; + return ent; +} + +/* +============= +///ScriptDocBegin +"Name: createExploder( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +createExploder( fxid ) +{ + ent = common_scripts\_createfx::createEffect( "exploder", fxid ); + ent.v[ "delay" ] = 0; + ent.v[ "exploder_type" ] = "normal"; + return ent; +} + +/* +============= +///ScriptDocBegin +"Name: sortString( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +sortString( array ) +{ + if ( array.size <= 1 ) + { + return array; + } + + for ( i=0; i 0 ) + { + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + } + } + + return array; +} + +/* +============= +///ScriptDocBegin +"Name: alphabetize( )" +"Summary: " +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: " +"SPMP: both" +///ScriptDocEnd +============= +*/ +alphabetize( array ) +{ + if ( array.size <= 1 ) + return array; + + addwaits = false; + if ( isSP() ) + addwaits = true; + + count = 0; + for ( ;; ) + { + changed = false; + for ( i = 0; i < array.size - 1; i++ ) + { + if ( is_later_in_alphabet( array[ i ], array[ i + 1 ] ) ) + { + val = array[ i ]; + array[ i ] = array[ i + 1 ]; + array[ i + 1 ] = val; + changed = true; + + if ( addwaits ) + { + count++; + if ( count >= 10 ) + { + count = 0; + waitframe(); + } + } + } + } + + if ( !changed ) + return array; + } + + return array; +} + +is_later_in_alphabet( string1, string2 ) +{ + count = string1.size; + if ( count >= string2.size ) + count = string2.size; + + for ( i = 0; i < count; i++ ) + { + val = alphabet_compare( string1[ i ], string2[ i ] ); + if ( val == "1st" ) + return true; + if ( val == "2nd" ) + return false; + } + + return string1.size > string2.size; +} + +alphabet_compare( a, b ) +{ + list = []; + val = 1; + list[ "0" ] = val; val++; + list[ "1" ] = val; val++; + list[ "2" ] = val; val++; + list[ "3" ] = val; val++; + list[ "4" ] = val; val++; + list[ "5" ] = val; val++; + list[ "6" ] = val; val++; + list[ "7" ] = val; val++; + list[ "8" ] = val; val++; + list[ "9" ] = val; val++; + list[ "_" ] = val; val++; + list[ "a" ] = val; val++; + list[ "b" ] = val; val++; + list[ "c" ] = val; val++; + list[ "d" ] = val; val++; + list[ "e" ] = val; val++; + list[ "f" ] = val; val++; + list[ "g" ] = val; val++; + list[ "h" ] = val; val++; + list[ "i" ] = val; val++; + list[ "j" ] = val; val++; + list[ "k" ] = val; val++; + list[ "l" ] = val; val++; + list[ "m" ] = val; val++; + list[ "n" ] = val; val++; + list[ "o" ] = val; val++; + list[ "p" ] = val; val++; + list[ "q" ] = val; val++; + list[ "r" ] = val; val++; + list[ "s" ] = val; val++; + list[ "t" ] = val; val++; + list[ "u" ] = val; val++; + list[ "v" ] = val; val++; + list[ "w" ] = val; val++; + list[ "x" ] = val; val++; + list[ "y" ] = val; val++; + list[ "z" ] = val; val++; + + a = ToLower( a ); + b = ToLower( b ); + val1 = 0; + if ( IsDefined( list[ a ] ) ) + val1 = list[ a ]; + + val2 = 0; + if ( IsDefined( list[ b ] ) ) + val2 = list[ b ]; + + if ( val1 > val2 ) + return "1st"; + if ( val1 < val2 ) + return "2nd"; + return "same"; +} + +/* +============= +///ScriptDocBegin +"Name: play_loop_sound_on_entity( , )" +"Summary: Play loop sound alias on an entity" +"Module: Sound" +"CallOn: An entity" +"MandatoryArg: : Sound alias to loop" +"OptionalArg: : Offset for sound origin relative to the world from the models origin." +"Example: vehicle thread play_loop_sound_on_entity( "engine_belt_run" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +play_loop_sound_on_entity( alias, offset ) +{ + org = Spawn( "sound_emitter", ( 0, 0, 0 ) ); + org endon( "death" ); + thread delete_on_death( org ); + + if ( IsDefined( offset ) ) + { + org.origin = self.origin + offset; + org.angles = self.angles; + org LinkTo( self ); + } + else + { + org.origin = self.origin; + org.angles = self.angles; + org LinkTo( self ); + } + +// org endon( "death" ); + org PlayLoopSound( alias ); +// PrintLn( "playing loop sound ", alias, " on entity at origin ", self.origin, " at ORIGIN ", org.origin ); + + self waittill( "stop sound" + alias ); + org StopLoopSound( alias ); + org Delete(); +} + +/* +============= +///ScriptDocBegin +"Name: stop_loop_sound_on_entity( )" +"Summary: Stop playing the the loop sound alias on an entity" +"Module: Sound" +"CallOn: An entity" +"MandatoryArg: : Sound alias to stop looping" +"Example: vehicle thread stop_loop_sound_on_entity( "engine_belt_run" );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +stop_loop_sound_on_entity( alias ) +{ + self notify( "stop sound" + alias ); +} + +/* +============= +///ScriptDocBegin +"Name: delete_on_death( )" +"Summary: Delete the entity when "self" dies." +"Module: Entity" +"CallOn: An entity" +"MandatoryArg: : " +"OptionalArg: : " +"Example: level.helicopter thread delete_on_death( someRandomScriptOriginThatISpawned );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +delete_on_death( ent ) +{ + //self ==> the entity you want to wait to die before deleting the ent + ent endon( "death" ); + self waittill( "death" ); + if ( IsDefined( ent ) ) + ent Delete(); +} + +error( msg ) +{ + PrintLn( "^c * ERROR * ", msg ); + waitframe(); + + /# + if ( GetDvar( "debug" ) != "1" ) + AssertMsg( "This is a forced error - attach the log file. \n" + msg ); + #/ +} + +/* +============= +///ScriptDocBegin +"Name: exploder( )" +"Summary: Sets off the desired exploder" +"Module: Utility" +"MandatoryArg: : The exploder number" +"Example: exploder( 5 );" +"SPMP: both" +///ScriptDocEnd +============= +*/ +exploder( num ) +{ + [[ level._exploderFunction ]]( num ); +} + + +/* +============= +///ScriptDocBegin +"Name: create_dvar( , )" +"Summary: Initialize a dvar with a given value" +"Module: Utility" +"MandatoryArg: : Name of the dvar" +"MandatoryArg: : Default value" +"Example: create_dvar( "fish", "on" );" +"SPMP: singleplayer" +///ScriptDocEnd +============= +*/ +create_dvar( var, val ) +{ + SetDvarIfUninitialized( var, val ); +} + + +void() +{ +} \ No newline at end of file diff --git a/maps/animated_models/accessories_windsock_wind_medium.gsc b/maps/animated_models/accessories_windsock_wind_medium.gsc new file mode 100644 index 0000000..1681560 --- /dev/null +++ b/maps/animated_models/accessories_windsock_wind_medium.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "accessories_windsock"; + if ( SP ) + { + level._anim_prop_models[ model ][ "wind_medium" ] = %windsock_wind_medium; + } + else + level._anim_prop_models[ model ][ "wind_medium" ] = "windsock_wind_medium"; +} \ No newline at end of file diff --git a/maps/animated_models/com_roofvent2.gsc b/maps/animated_models/com_roofvent2.gsc new file mode 100644 index 0000000..eea84be --- /dev/null +++ b/maps/animated_models/com_roofvent2.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "com_roofvent2_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "rotate" ] = %roofvent_rotate; + } + else + level._anim_prop_models[ model ][ "rotate" ] = "roofvent_rotate"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_dead_pine_lg_sway2.gsc b/maps/animated_models/foliage_dead_pine_lg_sway2.gsc new file mode 100644 index 0000000..af75151 --- /dev/null +++ b/maps/animated_models/foliage_dead_pine_lg_sway2.gsc @@ -0,0 +1,13 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Uses .animation + model = "foliage_dead_pine_lg_animated_sway2"; + level._anim_prop_models[ model ][ "sway2" ] = "foliage_dead_pine_lg_mp_sway2"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_dead_pine_med_sway2.gsc b/maps/animated_models/foliage_dead_pine_med_sway2.gsc new file mode 100644 index 0000000..c1fac78 --- /dev/null +++ b/maps/animated_models/foliage_dead_pine_med_sway2.gsc @@ -0,0 +1,13 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Uses .animation + model = "foliage_dead_pine_med_animated_sway2"; + level._anim_prop_models[ model ][ "sway2" ] = "foliage_dead_pine_med_mp_sway2"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_desertbrush_1.gsc b/maps/animated_models/foliage_desertbrush_1.gsc new file mode 100644 index 0000000..87abd43 --- /dev/null +++ b/maps/animated_models/foliage_desertbrush_1.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_desertbrush_1_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_desertbrush_1_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_desertbrush_1_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_pacific_fern01.gsc b/maps/animated_models/foliage_pacific_fern01.gsc new file mode 100644 index 0000000..c7c3421 --- /dev/null +++ b/maps/animated_models/foliage_pacific_fern01.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_pacific_fern01_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_pacific_fern01_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_pacific_fern01_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_pacific_fern02.gsc b/maps/animated_models/foliage_pacific_fern02.gsc new file mode 100644 index 0000000..b3d653f --- /dev/null +++ b/maps/animated_models/foliage_pacific_fern02.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_pacific_fern02_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_pacific_fern02_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_pacific_fern02_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_pacific_palms06.gsc b/maps/animated_models/foliage_pacific_palms06.gsc new file mode 100644 index 0000000..ff096b0 --- /dev/null +++ b/maps/animated_models/foliage_pacific_palms06.gsc @@ -0,0 +1,12 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + model = "foliage_pacific_palms06_animated"; + level._anim_prop_models[ model ][ "sway" ] = "foliage_pacific_palms06_sway"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_pacific_palms08.gsc b/maps/animated_models/foliage_pacific_palms08.gsc new file mode 100644 index 0000000..2d3f3fb --- /dev/null +++ b/maps/animated_models/foliage_pacific_palms08.gsc @@ -0,0 +1,21 @@ +#include common_scripts\utility; +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_pacific_palms08_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_pacific_palms08_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_pacific_palms08_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_pacific_tropic_shrub01.gsc b/maps/animated_models/foliage_pacific_tropic_shrub01.gsc new file mode 100644 index 0000000..160c890 --- /dev/null +++ b/maps/animated_models/foliage_pacific_tropic_shrub01.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_pacific_tropic_shrub01_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_pacific_tropic_shrub01_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_pacific_tropic_shrub01_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_red_pine_lg.gsc b/maps/animated_models/foliage_red_pine_lg.gsc new file mode 100644 index 0000000..8e2a7eb --- /dev/null +++ b/maps/animated_models/foliage_red_pine_lg.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_red_pine_lg_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_red_pine_lg_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_red_pine_lg_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_grey_oak_lg_a.gsc b/maps/animated_models/foliage_tree_grey_oak_lg_a.gsc new file mode 100644 index 0000000..53f118f --- /dev/null +++ b/maps/animated_models/foliage_tree_grey_oak_lg_a.gsc @@ -0,0 +1,12 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + model = "foliage_tree_grey_oak_lg_a_animated"; + level._anim_prop_models[ model ][ "sway" ] = "foliage_tree_grey_oak_lg_a_sway"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_grey_oak_xl_a.gsc b/maps/animated_models/foliage_tree_grey_oak_xl_a.gsc new file mode 100644 index 0000000..11a09a4 --- /dev/null +++ b/maps/animated_models/foliage_tree_grey_oak_xl_a.gsc @@ -0,0 +1,12 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + model = "foliage_tree_grey_oak_xl_a_animated"; + level._anim_prop_models[ model ][ "sway" ] = "foliage_tree_grey_oak_xl_a_sway"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_oak_1.gsc b/maps/animated_models/foliage_tree_oak_1.gsc new file mode 100644 index 0000000..604a225 --- /dev/null +++ b/maps/animated_models/foliage_tree_oak_1.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_oak_1_animated2"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_tree_oak_1_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_tree_oak_1_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_bushy_1.gsc b/maps/animated_models/foliage_tree_palm_bushy_1.gsc new file mode 100644 index 0000000..c86be4f --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_bushy_1.gsc @@ -0,0 +1,24 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_bushy_1"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_bushy1_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_bushy1_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_bushy1_sway"; + } + 3 \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_bushy_2.gsc b/maps/animated_models/foliage_tree_palm_bushy_2.gsc new file mode 100644 index 0000000..02f5ffe --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_bushy_2.gsc @@ -0,0 +1,23 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_bushy_2"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_bushy2_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_bushy2_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_bushy2_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_bushy_3.gsc b/maps/animated_models/foliage_tree_palm_bushy_3.gsc new file mode 100644 index 0000000..388c273 --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_bushy_3.gsc @@ -0,0 +1,23 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_bushy_3"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_bushy3_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_bushy3_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_bushy3_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_tall_1.gsc b/maps/animated_models/foliage_tree_palm_tall_1.gsc new file mode 100644 index 0000000..d5b250b --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_tall_1.gsc @@ -0,0 +1,23 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_tall_1"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_tall1_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_tall1_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_tall1_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_tall_2.gsc b/maps/animated_models/foliage_tree_palm_tall_2.gsc new file mode 100644 index 0000000..a37fb8b --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_tall_2.gsc @@ -0,0 +1,23 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_tall_2"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_tall2_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_tall2_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_tall2_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_palm_tall_3.gsc b/maps/animated_models/foliage_tree_palm_tall_3.gsc new file mode 100644 index 0000000..3169f86 --- /dev/null +++ b/maps/animated_models/foliage_tree_palm_tall_3.gsc @@ -0,0 +1,23 @@ +#include common_scripts\utility; + + #using_animtree( "animated_props" ); + main() + { + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_palm_tall_3"; + if ( SP ) + { + level._anim_prop_models[ model ][ "still" ] = %palmtree_tall3_still; + level._anim_prop_models[ model ][ "strong" ] = %palmtree_tall3_sway; + } + else + level._anim_prop_models[ model ][ "strong" ] = "palmtree_mp_tall3_sway"; + } \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_river_birch_lg_a.gsc b/maps/animated_models/foliage_tree_river_birch_lg_a.gsc new file mode 100644 index 0000000..55f2077 --- /dev/null +++ b/maps/animated_models/foliage_tree_river_birch_lg_a.gsc @@ -0,0 +1,12 @@ +#include common_scripts\utility; + +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + model = "foliage_tree_river_birch_lg_a_animated"; + level._anim_prop_models[ model ][ "sway" ] = "foliage_tree_river_birch_lg_a_sway"; +} + +// SP not currently supported because this requires updating "animated_props" animtree \ No newline at end of file diff --git a/maps/animated_models/foliage_tree_river_birch_med_a.gsc b/maps/animated_models/foliage_tree_river_birch_med_a.gsc new file mode 100644 index 0000000..e2500c8 --- /dev/null +++ b/maps/animated_models/foliage_tree_river_birch_med_a.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "foliage_tree_river_birch_med_a_animated"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %foliage_tree_river_birch_med_a_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "foliage_tree_river_birch_med_a_sway"; +} \ No newline at end of file diff --git a/maps/animated_models/highrise_fencetarp_01.gsc b/maps/animated_models/highrise_fencetarp_01.gsc new file mode 100644 index 0000000..0de2d03 --- /dev/null +++ b/maps/animated_models/highrise_fencetarp_01.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "highrise_fencetarp_01"; + if ( SP ) + { + level._anim_prop_models[ model ][ "wind" ] = %highrise_fencetarp_01_wind; + } + else + level._anim_prop_models[ model ][ "wind" ] = "highrise_fencetarp_01_wind"; +} \ No newline at end of file diff --git a/maps/animated_models/highrise_fencetarp_09.gsc b/maps/animated_models/highrise_fencetarp_09.gsc new file mode 100644 index 0000000..426355a --- /dev/null +++ b/maps/animated_models/highrise_fencetarp_09.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "highrise_fencetarp_09"; + if ( SP ) + { + level._anim_prop_models[ model ][ "wind" ] = %highrise_fencetarp_09_wind; + } + else + level._anim_prop_models[ model ][ "wind" ] = "highrise_fencetarp_09_wind"; +} \ No newline at end of file diff --git a/maps/animated_models/nx_color_tv_sign.gsc b/maps/animated_models/nx_color_tv_sign.gsc new file mode 100644 index 0000000..d97755c --- /dev/null +++ b/maps/animated_models/nx_color_tv_sign.gsc @@ -0,0 +1,22 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + if( !isdefined ( level._anim_prop_models ) ) + level._anim_prop_models = []; + + // Would use isSP() but this runs before we can + mapname = tolower( getdvar( "mapname" ) ); + SP = true; + if ( string_starts_with( mapname, "mp_" ) ) + SP = false; + + model = "color_tv_sign"; + if ( SP ) + { + level._anim_prop_models[ model ][ "sway" ] = %nx_pr_color_tv_sign_sway; + } + else + level._anim_prop_models[ model ][ "sway" ] = "nx_pr_color_tv_sign_sway"; +} \ No newline at end of file diff --git a/maps/createart/mp_nx_fallout_art.gsc b/maps/createart/mp_nx_fallout_art.gsc new file mode 100644 index 0000000..dfc890f --- /dev/null +++ b/maps/createart/mp_nx_fallout_art.gsc @@ -0,0 +1,15 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 1601.52, 28892.1, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + VisionSetNaked( "mp_nx_fallout", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_galleria_art.gsc b/maps/createart/mp_nx_galleria_art.gsc new file mode 100644 index 0000000..ea0edf7 --- /dev/null +++ b/maps/createart/mp_nx_galleria_art.gsc @@ -0,0 +1,16 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 722, 50000, 0.7372549, 0.7372549, 0.7686275, 0.05416667, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.8392157, 0.6862745, 0.5647059, ( 0.00390755, 0, 0 ), 0, 92, 2.25 ); + //setExpFog( 2702.33, 9214.93, 0.870588, 0.45098, 0.341176, 0.407261, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + VisionSetNaked( "mp_nx_galleria", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_meteor_art.gsc b/maps/createart/mp_nx_meteor_art.gsc new file mode 100644 index 0000000..7282e6c --- /dev/null +++ b/maps/createart/mp_nx_meteor_art.gsc @@ -0,0 +1,15 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 1711.38, 760.507, 0.254902, 0.392157, 0.282353, 0.33911, 0, 0, 0, 1, 1, 1, 1, 1, 1); + VisionSetNaked( "mp_nx_meteor", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_pitstop_art.gsc b/maps/createart/mp_nx_pitstop_art.gsc new file mode 100644 index 0000000..72e3220 --- /dev/null +++ b/maps/createart/mp_nx_pitstop_art.gsc @@ -0,0 +1,17 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + //setExpFog( 0, 80579, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + //setExpFog (, , , , ,, , , , , , ,, ); + setExpFog( 1600, 50000, 0.6784314, 0.8156863, 0.9882353, 0.0505, 0, 0, 0, 1, 1, 1, 1, 1, 1 ); + VisionSetNaked( "mp_nx_pitstop", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_skylab_art.gsc b/maps/createart/mp_nx_skylab_art.gsc new file mode 100644 index 0000000..c57c168 --- /dev/null +++ b/maps/createart/mp_nx_skylab_art.gsc @@ -0,0 +1,15 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 3133.49, 26045.9, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + VisionSetNaked( "mp_nx_skylab", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_stasis_art.gsc b/maps/createart/mp_nx_stasis_art.gsc new file mode 100644 index 0000000..d1fafb5 --- /dev/null +++ b/maps/createart/mp_nx_stasis_art.gsc @@ -0,0 +1,15 @@ +// _createart generated. modify at your own risk. Changing values should be fine. +main() +{ + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 4804.66, 23283.2, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + VisionSetNaked( "mp_nx_stasis", 0 ); + +} \ No newline at end of file diff --git a/maps/createart/mp_nx_ugvhh_art.gsc b/maps/createart/mp_nx_ugvhh_art.gsc new file mode 100644 index 0000000..bef27f0 --- /dev/null +++ b/maps/createart/mp_nx_ugvhh_art.gsc @@ -0,0 +1,15 @@ +// _createart generated. modify at your own risk. Changing values should be fine. + main() + { + + level.tweakfile = true; + + + //* Fog section * + + setDevDvar( "scr_fog_disable", "0" ); + + setExpFog( 23185.5, 78310.7, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0.839216, 0.690196, 0.568627, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 ); + VisionSetNaked( "mp_nx_ugvhh", 0 ); + + } \ No newline at end of file diff --git a/maps/createfx/mp_nx_fallout_fx.gsc b/maps/createfx/mp_nx_fallout_fx.gsc new file mode 100644 index 0000000..c175ce0 --- /dev/null +++ b/maps/createfx/mp_nx_fallout_fx.gsc @@ -0,0 +1,130 @@ +//_createfx generated. Do not touch!! +#include common_scripts\utility; +#include common_scripts\_createfx; +main() +{ + // CreateFX entities size: 19 + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 2017.18, -1199.75, 204.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "battlefield_smokebank_S_warm_thick" ); + ent.v[ "origin" ] = ( 2438.32, -1227.45, -71.929 ); + ent.v[ "angles" ] = ( 270, 0, -90 ); + ent.v[ "fxid" ] = "battlefield_smokebank_S_warm_thick"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 3470.61, -1185.94, 333.584 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 3951.19, 420.776, 158.521 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 4120.57, 1965.89, 284.069 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 3221.7, 2587.15, 278.106 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_mp_ash_aftermath_fallout" ); + ent.v[ "origin" ] = ( 1348.14, 939.963, 250.806 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_mp_ash_aftermath_fallout"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "battlefield_smokebank_S_warm_thick" ); + ent.v[ "origin" ] = ( 2669.5, 670.057, -54.8789 ); + ent.v[ "angles" ] = ( 270, 359.464, -89.4642 ); + ent.v[ "fxid" ] = "battlefield_smokebank_S_warm_thick"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "tank_fire_hatch" ); + ent.v[ "origin" ] = ( 2499.02, 1250.83, -0.891108 ); + ent.v[ "angles" ] = ( 311.769, 179.925, -175.979 ); + ent.v[ "fxid" ] = "tank_fire_hatch"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "battlefield_smokebank_S_warm_thick" ); + ent.v[ "origin" ] = ( 1678.6, -467.411, 4.4418 ); + ent.v[ "angles" ] = ( 272, 0, -90 ); + ent.v[ "fxid" ] = "battlefield_smokebank_S_warm_thick"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "battlefield_smokebank_S_warm_thick" ); + ent.v[ "origin" ] = ( 1847.72, -1496.66, 37.6898 ); + ent.v[ "angles" ] = ( 272, 0, -90 ); + ent.v[ "fxid" ] = "battlefield_smokebank_S_warm_thick"; + ent.v[ "delay" ] = -15; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 2312, 760, 72.1 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf220_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 2312, 762, 70.1 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf220_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1810.12, -1525.88, 78.1 ); + ent.v[ "angles" ] = ( 286.848, 225, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf221_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1808, -1528, 80.1 ); + ent.v[ "angles" ] = ( 0, 45, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf221_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1818.12, -1525.88, 78 ); + ent.v[ "angles" ] = ( 0, 225, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf228_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1816, -1528, 80 ); + ent.v[ "angles" ] = ( 0, 45, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf228_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1530.12, 2346.12, 86 ); + ent.v[ "angles" ] = ( 0, 225, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf229_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 1528, 2344, 88 ); + ent.v[ "angles" ] = ( 0, 45, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf229_2"; + + // CreateFX entities placed: 19 +} \ No newline at end of file diff --git a/maps/createfx/mp_nx_galleria_fx.gsc b/maps/createfx/mp_nx_galleria_fx.gsc new file mode 100644 index 0000000..88ac0dd --- /dev/null +++ b/maps/createfx/mp_nx_galleria_fx.gsc @@ -0,0 +1,1889 @@ +//_createfx generated. Do not touch!! +#include common_scripts\utility; +#include common_scripts\_createfx; +main() +{ + // CreateFX entities size: 292 + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1118.71, 7726.44, 247.63 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_palm_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2163.95, 8648.78, 148.763 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_palm_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3325.34, 7951.7, 88 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_palm_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1544.92, 6279.71, 97.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_water_stream_slow"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2360.41, 8176.89, 123.935 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_water_stream_falls"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2643.88, 6156.11, -23.6399 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3405.65, 8593.36, 76.9109 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3329.67, 6792.03, 104.194 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2297.08, 6418.28, -14.5962 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2296.06, 6021.98, -25.944 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3910.32, 7285.8, 164.219 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_galleria_music_01"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 801.829, 8417.88, 220.064 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_galleria_music_02"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1072.13, 7024.55, 160.855 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_galleria_tv_static"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2025.64, 6097.01, 117.921 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle_high"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2916.81, 9155.15, 84.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle_high"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1574.2, 8241.98, 114.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle_high"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2222.99, 7279.62, -36 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle_high"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2206.57, 6976.02, -36 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_palm_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1548.18, 6770.11, 104.685 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3599.62, 8559.88, 82.0095 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_tree_leaf_rustle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3278.75, 5335.91, -49.55 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "hithard_policerad"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1684.51, 4955.32, -68.7102 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "hithard_policerad"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 3246.63, 5007.65, -50.8782 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "hithard_radioloop"; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 2412.78, 7448.35, -18.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2593.68, 5867.62, 237.849 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 2509.8, 6160.67, -54.0599 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 1720.29, 6891.64, -17.9666 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 1113.21, 8054.15, 157.94 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 2578.73, 8857.02, 127.814 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3801.38, 9534.8, 35.6419 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3439.88, 8655.72, 76.7774 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3527.02, 7193.02, 96.1282 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3533.03, 6663.22, 72.1835 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3167.52, 6188.81, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2945.07, 5870.21, 163.49 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_building_distant" ); + ent.v[ "origin" ] = ( 10488.7, -6680.05, 5790.94 ); + ent.v[ "angles" ] = ( 0.415459, 137.993, -1.95618 ); + ent.v[ "fxid" ] = "nx_fire_building_distant"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_building_distant" ); + ent.v[ "origin" ] = ( 10241.3, -6951.87, 4513.33 ); + ent.v[ "angles" ] = ( 0.415459, 137.993, -1.95618 ); + ent.v[ "fxid" ] = "nx_fire_building_distant"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_building_distant" ); + ent.v[ "origin" ] = ( 10710.8, -6716.29, 5059.25 ); + ent.v[ "angles" ] = ( 0.415459, 137.993, -1.95618 ); + ent.v[ "fxid" ] = "nx_fire_building_distant"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_building_distant" ); + ent.v[ "origin" ] = ( 15593.8, -551.714, 4721.47 ); + ent.v[ "angles" ] = ( 0.415459, 137.993, -1.95618 ); + ent.v[ "fxid" ] = "nx_fire_building_distant"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_ash_cloud_heavy" ); + ent.v[ "origin" ] = ( 3224.78, 5767.45, 583.533 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_ash_cloud_heavy"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "dust_wind_fast_paper" ); + ent.v[ "origin" ] = ( 2460.99, 5415.37, 324.094 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "dust_wind_fast_paper"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_big_orange_glows" ); + ent.v[ "origin" ] = ( 8974.49, 2125.89, 701.912 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_big_orange_glows"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_building_large" ); + ent.v[ "origin" ] = ( 3475.11, 3482.03, 406.234 ); + ent.v[ "angles" ] = ( 354, 180, 0 ); + ent.v[ "fxid" ] = "nx_fire_building_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 1621.19, 8684.41, 137.164 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 2991.78, 5862.07, 371.45 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 3097.81, 5012.67, -88.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 4723.37, 9250.92, 163.807 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 3214.38, 9772.28, 63.6914 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 2023.16, 9259.88, 220.164 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2387.02, 8824.5, 72.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2262.9, 8314.02, 72.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 1009.76, 8152.09, 96.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 1980.09, 5946.85, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2988.56, 6130.84, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2853.82, 6466.94, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2335.45, 6517.31, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 2444.2, 7218.49, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_blowing_trash" ); + ent.v[ "origin" ] = ( 3585.96, 7620.26, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_blowing_trash"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "paper_falling_burning" ); + ent.v[ "origin" ] = ( 3740.82, 7214.02, 641.397 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "paper_falling_burning"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 2524.82, 7373.14, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 1858.57, 8278.83, 82.1361 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 1331.9, 7959.13, 96.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 1419.84, 6971.39, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 1736.64, 6197.47, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2776.79, 9320.69, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 3101.12, 7716.71, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 4249.35, 8733.74, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 3181.62, 8901.88, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 3196.36, 6695.11, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2441.93, 6971.43, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2916.67, 8157.78, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 3867.93, 7815.46, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_huge_periph_dark_preseed" ); + ent.v[ "origin" ] = ( 15551.2, 5830.69, 3219.69 ); + ent.v[ "angles" ] = ( 270, 0, 170 ); + ent.v[ "fxid" ] = "nx_smoke_plume_huge_periph_dark_preseed"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "blood_pool" ); + ent.v[ "origin" ] = ( 2862.21, 6160.29, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "blood_pool"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2850.3, 6250.26, 64.125 ); + ent.v[ "angles" ] = ( 270, 0.911188, 17.0888 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2840.57, 6246.55, 64.125 ); + ent.v[ "angles" ] = ( 270, 359.108, 6.89169 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2851.8, 6212.97, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2821.68, 6193.8, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2842.31, 6300.61, 64.125 ); + ent.v[ "angles" ] = ( 270, 1.38452, -25.3845 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2853.56, 6340.65, 64.125 ); + ent.v[ "angles" ] = ( 270, 2.74261, -28.7426 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2866.41, 6361.68, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, -20 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2843.73, 6276.3, 64.125 ); + ent.v[ "angles" ] = ( 270, 0.911188, 17.0888 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2866.38, 6115.24, 64.125 ); + ent.v[ "angles" ] = ( 270, 0.911188, 17.0888 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "drips_fast" ); + ent.v[ "origin" ] = ( 3178.93, 5930.44, 179.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "drips_fast"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat" ); + ent.v[ "origin" ] = ( 3579.7, 6759.53, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 3574.32, 6655.56, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2882.12, 6106.23, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2947.58, 6173.84, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2084.31, 6017.89, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 1065.05, 8060.55, 96.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 3187.32, 9768.23, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 3239.4, 8651.63, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2458.97, 8756.48, 72.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_light_emergency_red" ); + ent.v[ "origin" ] = ( 3701, 6680.56, 100.503 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_light_emergency_red"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sparks_falling_runner" ); + ent.v[ "origin" ] = ( 3693.77, 6738.61, 178.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_sparks_falling_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sparks_falling_runner" ); + ent.v[ "origin" ] = ( 3707.43, 7086.68, 143.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_sparks_falling_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sparks_falling_runner" ); + ent.v[ "origin" ] = ( 1018.4, 5926.25, 167.092 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_sparks_falling_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 1392.13, 6109.57, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_1024" ); + ent.v[ "origin" ] = ( 1343.34, 6734.4, 100.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_1024"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_1024" ); + ent.v[ "origin" ] = ( 3872.63, 9365.19, 77.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_1024"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "crawling_death_blood_smear" ); + ent.v[ "origin" ] = ( 2598.11, 5725.6, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "crawling_death_blood_smear"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat" ); + ent.v[ "origin" ] = ( 2875.48, 6192.55, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat" ); + ent.v[ "origin" ] = ( 1933.95, 6582.38, -11.7792 ); + ent.v[ "angles" ] = ( 300, 110, -90 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2310.4, 6382.78, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2350.19, 6164.36, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2378.19, 5745.63, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2598.54, 5718.69, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2546.63, 5719.6, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2611.76, 5758.88, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2592.48, 5747.66, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2453.88, 5828.38, -32.328 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2547.92, 5703.91, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2550.57, 5669.36, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_flesh_hit_splat_large" ); + ent.v[ "origin" ] = ( 2572.15, 5694.33, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_flesh_hit_splat_large"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 1042.96, 6799.88, 112.423 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 1712.13, 6031.57, 155.587 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 2387.72, 7563.8, 195.386 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 1266.13, 8459.65, 512.241 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ground_smoke_dcburning1200x1200" ); + ent.v[ "origin" ] = ( 2660.58, 9292.08, 405.927 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ground_smoke_dcburning1200x1200"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2470.44, 9062.56, 72.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 1843.15, 7187.85, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2561.55, 6449.59, -60.4199 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2371.54, 5556.15, -63.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "trash_spiral_runner" ); + ent.v[ "origin" ] = ( 2962.67, 5954.4, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "trash_spiral_runner"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3319.69, 7750.83, 41.016 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 4195.66, 8246.64, 40.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 3695.71, 8618.61, 192.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "room_smoke_400" ); + ent.v[ "origin" ] = ( 1122.73, 8510.27, 111.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "room_smoke_400"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150" ); + ent.v[ "origin" ] = ( 3310.2, 6847.88, 308.21 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_godray_150"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150" ); + ent.v[ "origin" ] = ( 2162.18, 6896.76, 100.537 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_godray_150"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150" ); + ent.v[ "origin" ] = ( 2234.62, 6822.17, 99.9367 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_godray_150"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150" ); + ent.v[ "origin" ] = ( 2232.12, 6935.85, 222.539 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_godray_150"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150" ); + ent.v[ "origin" ] = ( 4367.98, 9661.88, 428.109 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_godray_150"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 3845.79, 6872.56, 64.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 3762.16, 7046.16, 94.2086 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 4902.47, 8109.55, 14.9947 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 4533.5, 8089.9, 76.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 3495.05, 9283.81, 72.5115 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_add" ); + ent.v[ "origin" ] = ( 3737.08, 9702.88, 73.5535 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_add"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_huge_periph_dark_preseed" ); + ent.v[ "origin" ] = ( 10514.6, -10039.6, 4083.56 ); + ent.v[ "angles" ] = ( 270, 5.19443, 110.806 ); + ent.v[ "fxid" ] = "nx_smoke_plume_huge_periph_dark_preseed"; + ent.v[ "delay" ] = -15; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2796_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2797_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2808_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2809_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2891_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2892_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2903_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2904_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2865_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2866_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2877_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf2878_2"; + + // CreateFX entities placed: 292 +} \ No newline at end of file diff --git a/maps/createfx/mp_nx_pitstop_fx.gsc b/maps/createfx/mp_nx_pitstop_fx.gsc new file mode 100644 index 0000000..528309e --- /dev/null +++ b/maps/createfx/mp_nx_pitstop_fx.gsc @@ -0,0 +1,1072 @@ +//_createfx generated. Do not touch!! +#include common_scripts\utility; +#include common_scripts\_createfx; +main() +{ + // CreateFX entities size: 183 + ent = createLoopSound(); + ent.v[ "origin" ] = ( -2241.77, 387.955, -145.037 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_chainlink_fence_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 995.844, 825.551, -23.3354 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_chainlink_fence_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -346.578, -256.489, 11.6484 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_box"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 815.097, 92.7677, -43.8069 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1065.59, 1366.27, -119.375 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1745.04, 55.4136, 42.4061 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_creak_hvy"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -663.922, -1332.74, -30.6772 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_elec_transformer_close"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1474.89, -1564.98, 5.00994 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_rattle_flagpole"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1874.72, 883.97, -177.702 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2663.07, -1030.49, -119.075 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1655.32, -715.41, -121.567 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1352.15, -1111.54, -36.5174 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -604.064, 1075.26, -92.3097 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -304.933, 1018.7, -17.3501 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_metal_sheet_knocking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 84.2043, -1329.02, 16.8055 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 6.12783, -596.502, 4.74984 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -370.859, -50.8267, -38.6929 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -896.759, -1478.39, -34.0955 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -478.751, -321.005, -29.3747 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2011.16, -845.645, -107.078 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_corrugate_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -897.599, 351.616, -151.273 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1454.49, 943.259, -157.382 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -834.431, 1104.73, -123.484 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2714.52, 197.325, -39.1087 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2477.41, -980.371, -134.864 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1898.01, -944.313, -114.077 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1730.87, -435.192, -98.2476 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1291.36, 1088.22, -164.801 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2491.57, 14.7764, -80.6186 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 523.456, -1225.65, -64.592 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_ac_metal_rattle"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1065.63, -255.321, -75.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_heavy"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -728.475, -1041.57, 38.6577 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_heavy"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1249.05, -448.344, -16.7846 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_light"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -849.328, -468.842, -30.8429 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_light"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -897.035, -835.159, -75.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_light"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -456.119, -1149.82, -59.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_light"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -795.809, -199.442, -35.1707 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_wood_creak_light"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2099.65, -169.834, -74.7697 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_debris_mvmnt"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 186.679, -85.2885, -37.6133 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_debris_mvmnt"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1554.87, -101.726, -17.8793 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_debris_mvmnt"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -1931.35, 702.47, -138.022 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_debris_mvmnt"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -85.82, 120.574, 189.69 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -348.475, -348.591, -4.95592 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1457.78, -853.236, -37.5981 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1409.73, -135.737, -25.9904 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 1813.95, 593.304, -29.3466 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 522.661, 17.4833, -17.5682 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_bridge_creaking"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 2913.99, 137.502, 5.54213 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_creak_hvy"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( -268.817, 115.796, -61.922 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "soundalias" ] = "emt_mtl_creak_hvy"; + + ent = createLoopSound(); + ent.v[ "origin" ] = ( 136.241, -287.591, -74.875 ); + ent.v[ "angles" ] = ( 270, 2.29061, -28.2906 ); + ent.v[ "soundalias" ] = "emt_gas_station_radio"; + + ent = createOneshotEffect( "nx_dust_wind_canyon_mp" ); + ent.v[ "origin" ] = ( -1889.11, -163.926, -32.9235 ); + ent.v[ "angles" ] = ( 270, 0, -138 ); + ent.v[ "fxid" ] = "nx_dust_wind_canyon_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_wind_canyon_mp" ); + ent.v[ "origin" ] = ( -900.989, 1216.44, -59.0891 ); + ent.v[ "angles" ] = ( 270, 0, -178 ); + ent.v[ "fxid" ] = "nx_dust_wind_canyon_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_wind_canyon_mp" ); + ent.v[ "origin" ] = ( -1177.46, 917.381, -91.2697 ); + ent.v[ "angles" ] = ( 270, 0, -156 ); + ent.v[ "fxid" ] = "nx_dust_wind_canyon_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_wind_canyon_mp" ); + ent.v[ "origin" ] = ( -1499.43, 709.588, -92.3419 ); + ent.v[ "angles" ] = ( 270, 2.60256, -138.603 ); + ent.v[ "fxid" ] = "nx_dust_wind_canyon_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_wind_canyon_mp" ); + ent.v[ "origin" ] = ( 2092.4, -119.441, -7.02371 ); + ent.v[ "angles" ] = ( 270, 0, 92 ); + ent.v[ "fxid" ] = "nx_dust_wind_canyon_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -1420, -312.641, -135.673 ); + ent.v[ "angles" ] = ( 0, 50, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 1424.38, 778.494, -82.9126 ); + ent.v[ "angles" ] = ( 0, 142, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 761.063, 657.474, -82.9915 ); + ent.v[ "angles" ] = ( 0, 252, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 1735.45, -889.199, -164.559 ); + ent.v[ "angles" ] = ( 352, 212, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -198.189, -931.871, -71.1908 ); + ent.v[ "angles" ] = ( 0, 26, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -387.006, -545.842, -2.42067 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -967.327, 185.997, -106.8 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 1973.32, 576.863, -5.75847 ); + ent.v[ "angles" ] = ( 0, 96, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 1109.1, -1406.7, -19 ); + ent.v[ "angles" ] = ( 0, 96, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 295.178, -730.317, -29.843 ); + ent.v[ "angles" ] = ( 0, 78, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -1719.9, -1248.91, -16.3998 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -1614.27, -1688.4, -7.14452 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( -730.018, -572.057, -34.2364 ); + ent.v[ "angles" ] = ( 0.476599, 310.2, 24.5196 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( -797.201, -508.605, -78.4371 ); + ent.v[ "angles" ] = ( 0.476603, 310.2, 24.5197 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_225_soft" ); + ent.v[ "origin" ] = ( -945.592, -593.045, 230.662 ); + ent.v[ "angles" ] = ( 0.476602, 310.2, 32.5196 ); + ent.v[ "fxid" ] = "nx_godray_225_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( -812.203, -480.948, 104.739 ); + ent.v[ "angles" ] = ( 0.476602, 310.2, 30.5197 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( -876.654, -399.395, 104.61 ); + ent.v[ "angles" ] = ( 0.476602, 310.2, 32.5197 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( -741.263, -553.852, 104.631 ); + ent.v[ "angles" ] = ( 0.476602, 310.2, 30.5197 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_225_soft" ); + ent.v[ "origin" ] = ( -861.339, -689.51, 230.876 ); + ent.v[ "angles" ] = ( 0.476604, 310.2, 32.5196 ); + ent.v[ "fxid" ] = "nx_godray_225_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -804.183, -500.017, -17.4545 ); + ent.v[ "angles" ] = ( 270, 359.875, 2.12534 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1095.71, -429.003, -37.4411 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1537.45, -682.731, -116.316 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1234.66, 44.5394, -100.929 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -747.148, -584.096, -17.0652 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1179.81, -408.237, -39.9127 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -84.4537, -536.103, -3.61928 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1504.95, 499.633, -117.074 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1173.91, 93.7537, -115.325 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -2408.72, 55.8584, -125.708 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -621.671, -1148.47, 18.125 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 24.5074, 312.942, 3.02765 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 1683.75, -599.889, -118.988 ); + ent.v[ "angles" ] = ( 0, 96, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 846.539, -1000.98, -38.926 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 897.557, -732.422, -33.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 849.988, -825.992, -33.4972 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 678.235, -922.446, -39.028 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 841.921, -993.019, 169.817 ); + ent.v[ "angles" ] = ( 359.074, 211.745, 34.1333 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 942.259, -922.227, 169.885 ); + ent.v[ "angles" ] = ( 359.074, 211.745, 34.1333 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 1100.08, -819.861, 169.895 ); + ent.v[ "angles" ] = ( 359.074, 211.745, 34.1333 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 1200.34, -757.757, 169.647 ); + ent.v[ "angles" ] = ( 359.074, 211.745, 34.1333 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -148.567, -424.619, -0.131501 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( -1135.12, -1294.61, 30 ); + ent.v[ "angles" ] = ( 0, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -912.153, -1157.78, -28.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1040.63, -1191.24, -29.1137 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -807.156, -1275.47, -35 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1201.76, -831.106, -12.4649 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -2043.09, -163.813, -97.8068 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 331.022, -118.308, 14.1382 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 445.938, -46.2902, 5.11893 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1999.49, 870.384, -31.4048 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1614.35, 803.089, -46.7341 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 2604.07, -436.904, -82.0336 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_spiral_runner_mp" ); + ent.v[ "origin" ] = ( 2533.15, -860.825, -66.875 ); + ent.v[ "angles" ] = ( 0, 186, 0 ); + ent.v[ "fxid" ] = "nx_dust_spiral_runner_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 2694.32, -473.169, -145.711 ); + ent.v[ "angles" ] = ( 6, 258, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -1168.96, -519.174, -12.2205 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -261.979, 75.207, -1.33464 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -111.024, 160.616, 1.73879 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -731.137, -994.168, -37.1947 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -917.959, -488.233, -54.923 ); + ent.v[ "angles" ] = ( 270, 0, 26 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -776.902, -989.954, -51.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_blend" ); + ent.v[ "origin" ] = ( -813.013, -1000.04, -55.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_blend"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_blend" ); + ent.v[ "origin" ] = ( -889.514, -604.841, -60 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_blend"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -895.937, -778.765, -63.3109 ); + ent.v[ "angles" ] = ( 270, 0, 50 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_blend" ); + ent.v[ "origin" ] = ( 2326.75, 802.043, -85.4022 ); + ent.v[ "angles" ] = ( 270.694, 190, 135.987 ); + ent.v[ "fxid" ] = "amb_smoke_blend"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( 2357.28, 803.73, -77.9487 ); + ent.v[ "angles" ] = ( 270, 359.647, 14.3532 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( 1728.94, 910.945, -94.0273 ); + ent.v[ "angles" ] = ( 270, 355.914, 86.0856 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( 1862.1, 460.921, -62.2232 ); + ent.v[ "angles" ] = ( 270, 0, 94 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( 1954.72, -331.952, -120.071 ); + ent.v[ "angles" ] = ( 270, 359.139, -15.1393 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 292.215, 726.815, -18.2189 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 465.736, 862.82, -14.4791 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 374.217, 977.753, 0.213581 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 2868.68, -80.7265, -112 ); + ent.v[ "angles" ] = ( 0, 188, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1346.32, 287.543, 112.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1258.62, 391.217, 118.112 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 1233.75, 567.002, -21.0999 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( 1380.93, 288.24, 84.1559 ); + ent.v[ "angles" ] = ( 0, 254, 28 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 1402.47, 448.18, 151.572 ); + ent.v[ "angles" ] = ( 0, 254, 28 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_150_soft" ); + ent.v[ "origin" ] = ( 1355.67, 353.346, 150.149 ); + ent.v[ "angles" ] = ( 0, 254, 28 ); + ent.v[ "fxid" ] = "nx_godray_150_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_ash_ceiling_100_mp" ); + ent.v[ "origin" ] = ( -858.288, -581.817, 218.682 ); + ent.v[ "angles" ] = ( 270, 357.138, 126.862 ); + ent.v[ "fxid" ] = "nx_ash_ceiling_100_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( -894.052, 105.627, -75.2926 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( -45.0817, 360.366, 17.4808 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( 816.792, 131.476, 10.3501 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( 1955.43, 686.491, 0.404671 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( 1677.19, 243.141, 25.5504 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( 305.377, 417.896, -62.9905 ); + ent.v[ "angles" ] = ( 270, 0, 94 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -130.801, 531.537, -59.6075 ); + ent.v[ "angles" ] = ( 270, 0, 94 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_small_dl" ); + ent.v[ "origin" ] = ( -17.6574, 529.671, -45.9706 ); + ent.v[ "angles" ] = ( 270, 0, 94 ); + ent.v[ "fxid" ] = "firelp_small_dl"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "amb_smoke_blend" ); + ent.v[ "origin" ] = ( -89.875, 530.96, -62.7337 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "amb_smoke_blend"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -990.786, -599.281, 78.7994 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -873.082, -583.566, 78.3167 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( -881.529, -710.115, 72.7265 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_trash_runner_256" ); + ent.v[ "origin" ] = ( -591.675, -1123.74, 31.125 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_trash_runner_256"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( 2399.94, -786.241, -158.909 ); + ent.v[ "angles" ] = ( 0, 182, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -520.912, 1339.54, -127.758 ); + ent.v[ "angles" ] = ( 346.314, 316.287, 14.4833 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -2077.11, 11.3523, -202.169 ); + ent.v[ "angles" ] = ( 352, 308, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -1605.6, 818.674, -203.608 ); + ent.v[ "angles" ] = ( 0, 314, 0 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_sand_mp" ); + ent.v[ "origin" ] = ( -534.437, 46.5321, -173.985 ); + ent.v[ "angles" ] = ( 334.526, 39.2656, 0.634884 ); + ent.v[ "fxid" ] = "nx_sand_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 555.652, -1033.91, -36.0319 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 2265.93, 441.855, -10.4565 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 2392.38, 450.618, -10.1264 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 383.223, 442.726, -17.5259 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( 380.465, 443.592, 0.875 ); + ent.v[ "angles" ] = ( 0, 0, 90 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( 482.779, 515.415, -0.177139 ); + ent.v[ "angles" ] = ( 0, 0, 90 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 465.026, 500.693, -17.0274 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_godray_75_soft" ); + ent.v[ "origin" ] = ( 433.911, 479.365, -0.32105 ); + ent.v[ "angles" ] = ( 0, 0, 90 ); + ent.v[ "fxid" ] = "nx_godray_75_soft"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 792.993, 1238.32, -21.875 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_hawks_mp" ); + ent.v[ "origin" ] = ( -3498.84, -2390.97, 750.115 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_hawks_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_trashfire_mp" ); + ent.v[ "origin" ] = ( 4149.98, -43.6195, 72.7597 ); + ent.v[ "angles" ] = ( 314.119, 318.708, 49.321 ); + ent.v[ "fxid" ] = "nx_smoke_trashfire_mp"; + ent.v[ "delay" ] = -50; + + ent = createOneshotEffect( "nx_smoke_trashfire_small" ); + ent.v[ "origin" ] = ( 3578.61, -534.507, 78.6162 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_smoke_trashfire_small"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_trashfire_small" ); + ent.v[ "origin" ] = ( 3009.47, 518.059, 50.7671 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_smoke_trashfire_small"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_dust_mote_80" ); + ent.v[ "origin" ] = ( 75.8005, 774.327, 3.9502 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_dust_mote_80"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_fire_barrel" ); + ent.v[ "origin" ] = ( -29.1339, 267.372, -29.6974 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_fire_barrel"; + ent.v[ "delay" ] = -15; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1020_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1020_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1021_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1021_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1026_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1026_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1027_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1027_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 392, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1020_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 0, 394, -65.9 ); + ent.v[ "angles" ] = ( 281.421, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1020_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 539, -65.9 ); + ent.v[ "angles" ] = ( 286.858, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1021_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 144, 536, -63.9 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1021_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1026_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( -192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1026_1"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 139, -66 ); + ent.v[ "angles" ] = ( 0, 270, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1027_2"; + + ent = createExploder( "No FX" ); + ent.v[ "origin" ] = ( 192, 136, -64 ); + ent.v[ "angles" ] = ( 0, 90, 0 ); + ent.v[ "fxid" ] = "No FX"; + ent.v[ "delay" ] = 0; + ent.v[ "exploder" ] = "pf1027_2"; + + // CreateFX entities placed: 183 +} \ No newline at end of file diff --git a/maps/createfx/mp_nx_skylab_fx.gsc b/maps/createfx/mp_nx_skylab_fx.gsc new file mode 100644 index 0000000..1404303 --- /dev/null +++ b/maps/createfx/mp_nx_skylab_fx.gsc @@ -0,0 +1,6 @@ +//_createfx generated. Do not touch!! +#include common_scripts\utility; +#include common_scripts\_createfx; +main() +{ +} \ No newline at end of file diff --git a/maps/createfx/mp_nx_stasis_fx.gsc b/maps/createfx/mp_nx_stasis_fx.gsc new file mode 100644 index 0000000..0a8d3de --- /dev/null +++ b/maps/createfx/mp_nx_stasis_fx.gsc @@ -0,0 +1,62 @@ +//_createfx generated. Do not touch!! +#include common_scripts\utility; +#include common_scripts\_createfx; +main() +{ + // CreateFX entities size: 17 + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 2607.87, 7429.89, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 732.965, 8613.04, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 3675.38, 8377.6, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 4016.22, 7012.39, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 1654.56, 5970.16, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 1162.62, 6763.8, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 3730.14, 5152.77, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 2911.27, 5955.64, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "snow_light" ); + ent.v[ "origin" ] = ( 2105.03, 8611.94, 100 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "snow_light"; + ent.v[ "delay" ] = -15; + + // CreateFX entities placed: 9 +} \ No newline at end of file diff --git a/maps/createfx/mp_nx_ugvhh_fx.gsc b/maps/createfx/mp_nx_ugvhh_fx.gsc new file mode 100644 index 0000000..b4d3ea7 --- /dev/null +++ b/maps/createfx/mp_nx_ugvhh_fx.gsc @@ -0,0 +1,124 @@ +//_createfx generated. Do not touch!! + #include common_scripts\utility; + #include common_scripts\_createfx; + main() + { + // CreateFX entities size: 24 + ent = createOneshotEffect( "ash_aftermath_ugv_mp" ); + ent.v[ "origin" ] = ( 539.157, 1279.55, 596.643 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ash_aftermath_ugv_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ash_aftermath_ugv_mp" ); + ent.v[ "origin" ] = ( 1565.22, 3073.81, 699.572 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ash_aftermath_ugv_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "ash_aftermath_ugv_mp" ); + ent.v[ "origin" ] = ( 5983.87, 4730.37, 825.99 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "ash_aftermath_ugv_mp"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_large_pm_bh1" ); + ent.v[ "origin" ] = ( 1170.73, 1200.51, 226 ); + ent.v[ "angles" ] = ( 296, 180, 180 ); + ent.v[ "fxid" ] = "firelp_large_pm_bh1"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_med_pm_bh1" ); + ent.v[ "origin" ] = ( 815.138, 1434.87, 250.526 ); + ent.v[ "angles" ] = ( 282, 180, 180 ); + ent.v[ "fxid" ] = "firelp_med_pm_bh1"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "firelp_med_pm_bh1" ); + ent.v[ "origin" ] = ( 1087.65, 832.262, 442 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "firelp_med_pm_bh1"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "large_fire" ); + ent.v[ "origin" ] = ( -1530.24, 2073.87, 489.872 ); + ent.v[ "angles" ] = ( 4, 4, 0 ); + ent.v[ "fxid" ] = "large_fire"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_periph_large_black" ); + ent.v[ "origin" ] = ( -1346.8, 894.056, 301.98 ); + ent.v[ "angles" ] = ( 270, 320.936, 39.0635 ); + ent.v[ "fxid" ] = "nx_smoke_plume_periph_large_black"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_periph_large_black" ); + ent.v[ "origin" ] = ( 555.964, -1769.39, 563.125 ); + ent.v[ "angles" ] = ( 304.108, 164.878, 93.3438 ); + ent.v[ "fxid" ] = "nx_smoke_plume_periph_large_black"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_periph_large_black" ); + ent.v[ "origin" ] = ( 4200.01, 1853.93, 199.766 ); + ent.v[ "angles" ] = ( 337.767, 305.881, 62.5061 ); + ent.v[ "fxid" ] = "nx_smoke_plume_periph_large_black"; + ent.v[ "delay" ] = -15; + + ent = createOneshotEffect( "nx_smoke_plume_periph_large_black" ); + ent.v[ "origin" ] = ( 7216.51, 5639.86, 479.075 ); + ent.v[ "angles" ] = ( 284, 90, 96 ); + ent.v[ "fxid" ] = "nx_smoke_plume_periph_large_black"; + ent.v[ "delay" ] = -15; + + ent = createExploder( "nx_orbital_laser_01" ); + ent.v[ "origin" ] = ( -2045.08, 3938.13, 712.706 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_orbital_laser_01"; + ent.v[ "delay" ] = 0; + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = "fx_orbital_laser_02"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + + ent = createExploder( "nx_orbital_laser_01" ); + ent.v[ "origin" ] = ( -2005.55, 4289.13, 725.282 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_orbital_laser_01"; + ent.v[ "delay" ] = 0; + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = "fx_orbital_laser_04"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + + ent = createExploder( "nx_orbital_laser_01" ); + ent.v[ "origin" ] = ( -1867.38, 5205.8, 694.934 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_orbital_laser_01"; + ent.v[ "delay" ] = 0; + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = "fx_orbital_laser_05"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + + ent = createExploder( "nx_orbital_laser_01" ); + ent.v[ "origin" ] = ( -1493.62, 5253.13, 704.413 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_orbital_laser_01"; + ent.v[ "delay" ] = 0; + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = "fx_orbital_laser_03"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + + ent = createExploder( "nx_orbital_laser_02" ); + ent.v[ "origin" ] = ( -2019.07, 4678.03, 685.431 ); + ent.v[ "angles" ] = ( 270, 0, 0 ); + ent.v[ "fxid" ] = "nx_orbital_laser_02"; + ent.v[ "delay" ] = 0; + ent.v[ "flag" ] = "nil"; + ent.v[ "exploder" ] = "fx_orbital_laser_01"; + ent.v[ "soundalias" ] = "nil"; + ent.v[ "loopsound" ] = "nil"; + + // CreateFX entities placed: 16 + } \ No newline at end of file diff --git a/maps/mp/_adrenaline.gsc b/maps/mp/_adrenaline.gsc new file mode 100644 index 0000000..8af9dee --- /dev/null +++ b/maps/mp/_adrenaline.gsc @@ -0,0 +1,471 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +ADRENALINE_UPDATE_TIME_SEC = 0.3; +ADRENALINE_MIN_HUD_ALPHA = 0.5; +ADRENALINE_FLASH_REMAINING_TIME_SEC = 5; +ADRENALINE_MIN_ALPHA_VALUE = 0.5; +ADRENALINE_FLASH_TIME_LEFT_SEC = 5.0; +ADRENALINE_ICON_PULSE_SCALE = 1.1; + +//******************************************************************* +// * +// * +//******************************************************************* + +init() +{ + if( getDvarInt( "prototype_adrenaline_enabled" ) == 1 ) + { + println( "Adrenaline enabled" ); + initAdrenaline(); + + level thread onPlayerConnect(); + } + else + { + println( "Adrenaline disabled" ); + } +} + + +adrenalineDebugging() +{ + return getDvarInt( "set adrenaline_debugging" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +initAdrenaline() +{ + // setup the models and stuff we need for intel + precacheShader("combathigh_overlay"); + level._adrenalineIconAsset = "hud_adrenaline"; + precacheShader( level._adrenalineIconAsset ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + player thread onPlayerSpawned(); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onPlayerSpawned() +{ + for(;;) + { + if( adrenalineDebugging()) + println( "Adrenaline: onPlayerSpawned" ); + + self waittill( "spawned_player" ); + + self setupAdrenaline(); + + // update adrenaline value + self thread adrenalineThink(); + + // clean up the hud at death + self thread adrenalineWaitTillDeath(); + + // update the hud + self thread adrenalineUpdate(); + + // cleanup when ready + self thread adrenalineWaitCleanup(); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineThink() +{ + self endon( "disconnect" ); + self endon( "death" ); + + oldSPM = 0; + for(;;) + { + // cull out old scores + self adrenalineCleanScores(); + + newSPM = self adrenalineScorePerMin(); + + oldTime = self._adrenalineTimeSec; + + if( adrenalineDebugging() && newSPM > 0 ) + { + println( "old spm " + oldSPM + " new spm " + newSPM + " thres " + addrenalineGetSPMThreshold() + " adren time " + self._adrenalineTimeSec + " dvar " + getDvarInt( "adrenaline_winddown_time_sec" ) ); + } + + // calculate if we are in adrenaline mode + if( oldSPM < newSPM && addrenalineGetSPMThreshold() <= newSPM ) + { + self._adrenalineTimeSec = getDvarInt( "adrenaline_winddown_time_sec" ); + self notify( "adrenaline_update" ); + } + + oldSPM = newSPM; + + // wait for another update run + wait ADRENALINE_UPDATE_TIME_SEC; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineGetAlphaValue() +{ + alpha = ( self._adrenalineTimeSec - ADRENALINE_FLASH_TIME_LEFT_SEC )/( getDvarFloat( "adrenaline_winddown_time_sec" ) - ADRENALINE_FLASH_TIME_LEFT_SEC ) * (1 - ADRENALINE_MIN_ALPHA_VALUE); + + alpha += ADRENALINE_MIN_ALPHA_VALUE; + if( alpha > 1.0 ) + { + alpha = 1.0; + } + //println( "alpha value calc ", alpha ); + return alpha; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineCleanScores() +{ + for ( i = 0; i < self._adrenScoreTimes.size; i++ ) + { + if( gettime() - self._adrenScoreTimes[i] > getDvarFloat( "adrenaline_history_mins" ) * 60 * 1000 ) + { + self._adrenScoreTimes[i] = undefined; + self._adrenScores[i] = undefined; + } + } + + self._adrenScoreTimes = array_removeUndefined( self._adrenScoreTimes ); + self._adrenScores = array_removeUndefined( self._adrenScores ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineScorePerMin() +{ + totalScore = 0; + foreach( score in self._adrenScores ) + { + totalScore += score; + } + + return totalScore / ( getDvarFloat( "adrenaline_history_mins" ) * 1.0 ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +addrenalineGetSPMThreshold() +{ + deaths = self GetPlayerData( "deaths" ); + kills = self GetPlayerData( "kills" ); + ratio = 1; + if( deaths > 0 ) + { + ratio = kills / ( deaths * 1.0 ); + } + if( ratio < 1 ) + { + ratio = 1; + } + + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + "kdratio " + ratio ); + } + return getDvarInt( "adrenaline_spm_threshold" ) * ratio; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineAddScore( score ) +{ + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + " added score " + score ); + } + if( isDefined( self._adrenalineOverlayOn )) + { + self._adrenScoreTimes[self._adrenScoreTimes.size] = gettime(); + self._adrenScores[self._adrenScores.size] = score; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineGetXPMultiplier() +{ + mult = 1; + if( isDefined( self._adrenalineOverlayOn ) && self._adrenalineOverlayOn ) + { + mult = getDvarInt( "adrenaline_xp_multiplier" ); + } + return mult; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +setupAdrenaline() +{ + self._adrenalineTimeSec = 0; + + self._adrenScoreTimes = []; + self._adrenScores = []; + self._adrenalineOverlayOn = false; + self._adrenalineXPEarned = false; + + self.adrenalineOverlay = undefined; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineSetXPEarned() +{ + self._adrenalineXPEarned = true; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineDidEarnXP() +{ + ret = false; + + if( getDvarInt( "prototype_adrenaline_enabled" ) == 1 ) + { + ret = self._adrenalineXPEarned; + } + return ret; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineInAdrenalineMode() +{ + ret = false; + + if( getDvarInt( "prototype_adrenaline_enabled" ) == 1 && isDefined( self._adrenalineOverlayOn )) + { + ret = self._adrenalineOverlayOn; + } + return ret; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineTrySplash( killedPlayer ) +{ + if( killedPlayer adrenalineInAdrenalineMode()) + { + if( killedPlayer adrenalineDidEarnXP()) + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "adrenaline_mood_killer", 0 ); + } + else + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "adrenaline_iced", 0 ); + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +enterAdrenaline() +{ + if( !self._adrenalineOverlayOn ) + { + self.adrenalineOverlay = newClientHudElem( self ); + self.adrenalineOverlay.x = 0; + self.adrenalineOverlay.y = 0; + self.adrenalineOverlay.alignX = "left"; + self.adrenalineOverlay.alignY = "top"; + self.adrenalineOverlay.horzAlign = "fullscreen"; + self.adrenalineOverlay.vertAlign = "fullscreen"; + self.adrenalineOverlay setshader ( "combathigh_overlay", 640, 480 ); + self.adrenalineOverlay.sort = -10; + self.adrenalineOverlay.archived = true; + self.adrenalineOverlay.alpha = 0; + self._adrenalineOverlayOn = true; + + self.adrenalineIcon = createIcon( level._adrenalineIconAsset, 40, 40 ); + self.adrenalineIcon.horzAlign = "left"; + self.adrenalineIcon.alignX = "left"; + self.adrenalineIcon.y = 0; + self.adrenalineIcon.x = 110; + self.adrenalineIcon.sort = -10; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineUpdate() +{ + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "adrenaline_update" ); + if( !self._adrenalineOverlayOn ) + { + wait 0.05; + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + " enterAdrenaline" ); + } + self enterAdrenaline(); + self thread maps\mp\gametypes\_hud_message::SplashNotify( "adrenaline_enter", 0 ); + } + self.adrenalineOverlay fadeOverTime( 0.3 ); + self.adrenalineOverlay.alpha = 1; + wait 0.3; + self thread adrenalineThreadWinddown(); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineThreadWinddown() +{ + self endon( "adrenaline_update" ); + self endon( "death" ); + self endon( "disconnect" ); + // the normal fade down + while( self._adrenalineTimeSec > ADRENALINE_FLASH_TIME_LEFT_SEC ) + { + alpha = self adrenalineGetAlphaValue(); + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + " update alpha " + alpha ); + } + self.adrenalineOverlay fadeOverTime( ADRENALINE_UPDATE_TIME_SEC ); + self.adrenalineOverlay.alpha = alpha; + wait ADRENALINE_UPDATE_TIME_SEC; + self._adrenalineTimeSec -= ADRENALINE_UPDATE_TIME_SEC; + } + origWidth = 40; + origHeight = 40; + while( self._adrenalineTimeSec > 0 ) + { + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + " update alpha " + ADRENALINE_MIN_ALPHA_VALUE ); + } + + self.AdrenalineOverlay fadeOverTime( 0.1 ); + self.adrenalineOverlay.alpha = ADRENALINE_MIN_ALPHA_VALUE * 1.3; + self.adrenalineIcon scaleOverTime( 0.05, int( origWidth * ADRENALINE_ICON_PULSE_SCALE ), int( origHeight * ADRENALINE_ICON_PULSE_SCALE ) ); + wait 0.05; + self.adrenalineIcon scaleOverTime( 0.3, origWidth, origHeight ); + self.AdrenalineOverlay fadeOverTime( 0.1 ); + self.adrenalineOverlay.alpha = ADRENALINE_MIN_ALPHA_VALUE; + wait 0.9; + self._adrenalineTimeSec -= 1; + } + self.AdrenalineOverlay fadeOverTime( 0.3 ); + self.adrenalineOverlay.alpha = 0; + wait 0.3; + self notify( "adrenaline_cleanup" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineWaitCleanup() +{ + for(;;) + { + self waittill_any_return( "adrenaline_cleanup", "death", "disconnect" ); + if( adrenalineDebugging()) + { + println( "Adrenaline: " + self.name + "adrenalineWaitCleanup()" ); + } + if( self._adrenalineOverlayOn ) + { + self._adrenalineOverlayOn = false; + self.adrenalineOverlay destroy(); + self.adrenalineOverlay = undefined; + + self.adrenalineIcon destroy(); + self.adrenalineIcon = undefined; + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +adrenalineWaitTillDeath() +{ + self waittill( "death" ); + self notify( "adrenaline_cleanup" ); +} \ No newline at end of file diff --git a/maps/mp/_animatedmodels.gsc b/maps/mp/_animatedmodels.gsc new file mode 100644 index 0000000..49f33ed --- /dev/null +++ b/maps/mp/_animatedmodels.gsc @@ -0,0 +1,64 @@ +#include common_scripts\utility; + +#using_animtree( "animated_props" ); +main() +{ + //level.init_animatedmodels_dump = false; + + if ( !isdefined( level._anim_prop_models ) ) + level._anim_prop_models = []; // this is what the LD puts in their map + + // Do special MP anim precaching + model_keys = GetArrayKeys( level._anim_prop_models ); + foreach ( model_key in model_keys ) + { + anim_keys = GetArrayKeys( level._anim_prop_models[model_key] ); + foreach ( anim_key in anim_keys ) + PrecacheMpAnim( level._anim_prop_models[model_key][anim_key] ); + //PrecacheMpAnim( level.anim_prop_models[ "foliage_tree_palm_bushy_1" ][ "strong" ] ); + } + + // wait until the end of the frame so that maps can init their trees + // in their _anim instead of only above _load + waittillframeend; + + level._init_animatedmodels = []; + + animated_models = getentarray( "animated_model", "targetname" ); + //array_thread( animated_models, ::model_init ); + + // one or more of the models initialized by model_init() was not setup by the map + // so print this helpful note so the designer can see how to add it ot their level + //if ( level.init_animatedmodels_dump ) + //assertmsg( "anims not cached for animated prop model, Repackage Zones and Rebuild Precache Script in Launcher:" ); + + array_thread( animated_models, ::animateModel ); + + level._init_animatedmodels = undefined; +} + +// Disabled for now since we are precaching .animation prefabs in a non-standard way +/*model_init() +{ + if ( !isdefined( level.anim_prop_models[ self.model ] ) ) + level.init_animatedmodels_dump = true; +}*/ + +// TODO: When we have multiple animations, instead of choosing randomly, do round-robin to get an even spread +animateModel() +{ + if ( IsDefined( self.animation ) ) + { + animation = self.animation; + } + else + { + keys = GetArrayKeys( level._anim_prop_models[ self.model ] ); + animkey = keys[ RandomInt( keys.size ) ]; + animation = level._anim_prop_models[ self.model ][ animkey ]; + } + + //wait( RandomFloatRange( 0, 5 ) ); // TODO: get a way to play animations at random starting points + self ScriptModelPlayAnim( animation ); + self willNeverChange(); +} \ No newline at end of file diff --git a/maps/mp/_areas.gsc b/maps/mp/_areas.gsc new file mode 100644 index 0000000..2f67947 --- /dev/null +++ b/maps/mp/_areas.gsc @@ -0,0 +1,111 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +/*QUAKED trigger_multiple_area (0.12 0.23 1.0) +defaulttexture="trigger" +"script_area" - A localized string that names the area. e.g. "MP_FLOWER_SHOP" +Defines an area that the player is in.*/ + +/*QUAKED trigger_multiple_softlanding (0.12 0.23 1.0) +defaulttexture="trigger" +"script_type" - "car", "boxes", "trash" +Defines a soft landing area.*/ + +/*QUAKED script_vehicle_snowmobile_player_mp (1 0 0) (-16 -16 -24) (16 16 32) USABLE SPAWNER + + +maps\_snowmobile_player::main( "vehicle_snowmobile" ); + + +include,vehicle_snowmobile_snowmobile_player +sound,vehicle_snowmobile,vehicle_standard,all_sp + + +defaultmdl="vehicle_snowmobile" +default:"vehicletype" "snowmobile_player_mp" +*/ + +init() +{ + level._softLandingTriggers = getEntArray( "trigger_multiple_softlanding", "classname" ); + + destructibles = getEntArray( "destructible_vehicle", "targetname" ); + + foreach ( trigger in level._softLandingTriggers ) + { + if ( trigger.script_type != "car" ) + continue; + + foreach ( destructible in destructibles ) + { + /* + if ( !trigger isTouching( destructible ) ) + { + println( distance( trigger.origin, destructible.origin ) ); + continue; + } + */ + + if ( distance( trigger.origin, destructible.origin ) > 64.0 ) + continue; + + assert( !isDefined( trigger.destructible ) ); + + trigger.destructible = destructible; + } + } + + //foreach ( trigger in level.softLandingTriggers ) + // trigger thread common_scripts\_dynamic_world::triggerTouchThink( ::playerEnterSoftLanding, ::playerLeaveSoftLanding ); + + thread onPlayerConnect(); +} + + +onPlayerConnect() +{ + for ( ;; ) + { + level waittill ( "connected", player ); + + player.softLanding = undefined; + + player thread softLandingWaiter(); + } +} + + +playerEnterSoftLanding( trigger ) +{ + self.softLanding = trigger; +} + + +playerLeaveSoftLanding( trigger ) +{ + self.softLanding = undefined; +} + + +softLandingWaiter() +{ + self endon ( "disconnect" ); + + for ( ;; ) + { + self waittill ( "soft_landing", trigger, damage ); + + //if ( damage < 10 ) + // continue; + + if ( !isDefined( trigger.destructible ) ) + continue; + + //magicBullet( "mp5_mp", self.origin, self.origin + (0,0,-100), self ); + + //self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, dflags ); + + //traceData = bulletTrace( self.origin, self.origin + (0,0,-100), true, self ); + + } +} \ No newline at end of file diff --git a/maps/mp/_art.gsc b/maps/mp/_art.gsc new file mode 100644 index 0000000..0d98371 --- /dev/null +++ b/maps/mp/_art.gsc @@ -0,0 +1,189 @@ +// This function should take care of grain and glow settings for each map, plus anything else that artists +// need to be able to tweak without bothering level designers. +#include common_scripts\utility; +#include common_scripts\_artCommon; + +main() +{ + /# + setDevDvarIfUninitialized( "scr_art_tweak", 0 ); + setDevDvarIfUninitialized( "scr_dof_enable", "1" ); + setDevDvarIfUninitialized( "scr_cmd_plr_sun", "0" ); + setDevDvarIfUninitialized( "scr_cinematic_autofocus", "1" ); + setDevDvarIfUninitialized( "scr_art_visionfile", level._script ); + + if ( !isDefined( level._dofDefault ) ) + { + level._dofDefault[ "nearStart" ] = 0; + level._dofDefault[ "nearEnd" ] = 1; + level._dofDefault[ "farStart" ] = 8000; + level._dofDefault[ "farEnd" ] = 10000; + level._dofDefault[ "nearBlur" ] = 6; + level._dofDefault[ "farBlur" ] = 0; + } + + level._curDoF = ( level._dofDefault[ "farStart" ] - level._dofDefault[ "nearEnd" ] ) / 2; + + thread tweakart(); + + if ( !isdefined( level._script ) ) + level._script = ToLower( GetDvar( "mapname" ) ); + #/ +} + +tweakart() +{ + /# + if ( !isdefined( level._tweakfile ) ) + level._tweakfile = false; + + // not in DEVGUI + SetDevDvar( "scr_fog_fraction", "1.0" ); + SetDevDvar( "scr_art_dump", "0" ); + + // update the devgui variables to current settings + SetDevDvar( "scr_dof_nearStart", level._dofDefault[ "nearStart" ] ); + SetDevDvar( "scr_dof_nearEnd", level._dofDefault[ "nearEnd" ] ); + SetDevDvar( "scr_dof_farStart", level._dofDefault[ "farStart" ] ); + SetDevDvar( "scr_dof_farEnd", level._dofDefault[ "farEnd" ] ); + SetDevDvar( "scr_dof_nearBlur", level._dofDefault[ "nearBlur" ] ); + SetDevDvar( "scr_dof_farBlur", level._dofDefault[ "farBlur" ] ); + + // not in DEVGUI + level._fogfraction = 1.0; + + file = undefined; + filename = undefined; + + for ( ;; ) + { + while ( GetDvarInt( "scr_art_tweak", 0 ) == 0 ) + { + AssertEx( GetDvarInt( "scr_art_dump", 0 ) == 0, "Must Enable Art Tweaks to export _art file." ); + wait .05; + if ( ! GetDvarInt( "scr_art_tweak", 0 ) == 0 ) + common_scripts\_artCommon::setfogsliders();// sets the sliders to whatever the current fog value is + } + + + if ( GetDvarInt( "scr_art_tweak_message" ) ) + { + SetDevDvar( "scr_art_tweak_message", "0" ); + IPrintLnBold( "ART TWEAK ENABLED" ); + } + + //translate the slider values to script variables + common_scripts\_artCommon::translateFogSlidersToScript(); + +// dofvarupdate(); + + // catch all those cases where a slider can be pushed to a place of conflict + fovslidercheck(); + + dump = dumpsettings();// dumps and returns true if the dump dvar is set + + common_scripts\_artCommon::updateFogFromScript(); + +// level.player setDefaultDepthOfField(); + if ( dump ) + { + IPrintLnBold( "Art settings dumped success!" ); + SetdevDvar( "scr_art_dump", "0" ); + } + wait .1; + } + #/ +} + +fovslidercheck() +{ + /# + // catch all those cases where a slider can be pushed to a place of conflict + if ( level._dofDefault[ "nearStart" ] >= level._dofDefault[ "nearEnd" ] ) + { + level._dofDefault[ "nearStart" ] = level._dofDefault[ "nearEnd" ] - 1; + SetDevDvar( "scr_dof_nearStart", level._dofDefault[ "nearStart" ] ); + } + if ( level._dofDefault[ "nearEnd" ] <= level._dofDefault[ "nearStart" ] ) + { + level._dofDefault[ "nearEnd" ] = level._dofDefault[ "nearStart" ] + 1; + SetDevDvar( "scr_dof_nearEnd", level._dofDefault[ "nearEnd" ] ); + } + if ( level._dofDefault[ "farStart" ] >= level._dofDefault[ "farEnd" ] ) + { + level._dofDefault[ "farStart" ] = level._dofDefault[ "farEnd" ] - 1; + SetDevDvar( "scr_dof_farStart", level._dofDefault[ "farStart" ] ); + } + if ( level._dofDefault[ "farEnd" ] <= level._dofDefault[ "farStart" ] ) + { + level._dofDefault[ "farEnd" ] = level._dofDefault[ "farStart" ] + 1; + SetDevDvar( "scr_dof_farEnd", level._dofDefault[ "farEnd" ] ); + } + if ( level._dofDefault[ "farBlur" ] >= level._dofDefault[ "nearBlur" ] ) + { + level._dofDefault[ "farBlur" ] = level._dofDefault[ "nearBlur" ] - .1; + SetDevDvar( "scr_dof_farBlur", level._dofDefault[ "farBlur" ] ); + } + if ( level._dofDefault[ "farStart" ] <= level._dofDefault[ "nearEnd" ] ) + { + level._dofDefault[ "farStart" ] = level._dofDefault[ "nearEnd" ] + 1; + SetDevDvar( "scr_dof_farStart", level._dofDefault[ "farStart" ] ); + } + #/ +} + +dumpsettings() +{ + /# + if ( GetDvarInt( "scr_art_dump" ) == 0 ) + return false; + + filename = "createart/" + GetDvar( "scr_art_visionfile" ) + "_art.gsc"; + + artStartFogFileExport(); + fileprint_launcher( "// _createart generated. modify at your own risk. Changing values should be fine." ); + fileprint_launcher( "main()" ); + fileprint_launcher( "{" ); + + fileprint_launcher( "" ); + fileprint_launcher( "\tlevel.tweakfile = true;" ); + fileprint_launcher( " " ); + + artfxprintlnFog(); + fileprint_launcher( "\tVisionSetNaked( \"" + level._script + "\", 0 );" ); + + fileprint_launcher( "" ); + fileprint_launcher( "}" ); + artEndFogFileExport(); + + visionFilename = "vision/" + GetDvar( "scr_art_visionfile" ) + ".vision"; + + artStartVisionFileExport(); + + fileprint_launcher( "r_glow \"" + GetDvar( "r_glowTweakEnable" ) + "\"" ); + fileprint_launcher( "r_glowRadius0 \"" + GetDvar( "r_glowTweakRadius0" ) + "\"" ); + fileprint_launcher( "r_glowBloomCutoff \"" + GetDvar( "r_glowTweakBloomCutoff" ) + "\"" ); + fileprint_launcher( "r_glowBloomDesaturation \"" + GetDvar( "r_glowTweakBloomDesaturation" ) + "\"" ); + fileprint_launcher( "r_glowBloomIntensity0 \"" + GetDvar( "r_glowTweakBloomIntensity0" ) + "\"" ); + fileprint_launcher( " " ); + fileprint_launcher( "r_filmEnable \"" + GetDvar( "r_filmTweakEnable" ) + "\"" ); + fileprint_launcher( "r_filmContrast \"" + GetDvar( "r_filmTweakContrast" ) + "\"" ); + fileprint_launcher( "r_filmBrightness \"" + GetDvar( "r_filmTweakBrightness" ) + "\"" ); + fileprint_launcher( "r_filmDesaturation \"" + GetDvar( "r_filmTweakDesaturation" ) + "\"" ); + fileprint_launcher( "r_filmDesaturationDark \"" + GetDvar( "r_filmTweakDesaturationDark" ) + "\"" ); + fileprint_launcher( "r_filmInvert \"" + GetDvar( "r_filmTweakInvert" ) + "\"" ); + fileprint_launcher( "r_filmLightTint \"" + GetDvar( "r_filmTweakLightTint" ) + "\"" ); + fileprint_launcher( "r_filmMediumTint \"" + GetDvar( "r_filmTweakMediumTint" ) + "\"" ); + fileprint_launcher( "r_filmDarkTint \"" + GetDvar( "r_filmTweakDarkTint" ) + "\"" ); + fileprint_launcher( " " ); + fileprint_launcher( "r_primaryLightUseTweaks \"" + GetDvar( "r_primaryLightUseTweaks" ) + "\"" ); + fileprint_launcher( "r_primaryLightTweakDiffuseStrength \"" + GetDvar( "r_primaryLightTweakDiffuseStrength" ) + "\"" ); + fileprint_launcher( "r_primaryLightTweakSpecularStrength \"" + GetDvar( "r_primaryLightTweakSpecularStrength" ) + "\"" ); + + if ( ! artEndVisionFileExport() ) + return false; + + IPrintLnBold( "ART DUMPED SUCCESSFULLY" ); + return true; + #/ +} \ No newline at end of file diff --git a/maps/mp/_awards.gsc b/maps/mp/_awards.gsc new file mode 100644 index 0000000..56fdc0a --- /dev/null +++ b/maps/mp/_awards.gsc @@ -0,0 +1,1142 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +init() +{ + initAwards(); + + level thread onPlayerConnect(); + level thread monitorMovementDistance(); + level thread monitorEnemyDistance(); +} + +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + // Reset player awards to none + + if ( !isDefined( player.pers["stats"] ) ) + player.pers["stats"] = []; + + player.stats = player.pers["stats"]; + + if ( !player.stats.size ) + { + player setPlayerData( "round", "awardCount", 0 ); + + // Initialize player stats + foreach ( ref, award in level._awards ) + { + if ( isDefined( level._awards[ ref ].defaultvalue ) ) + player initPlayerStat( ref, level._awards[ ref ].defaultvalue ); + else + player initPlayerStat( ref ); + } + } + + player.prevPos = player.origin; + player.previousDeaths = 0; + player.altitudePolls = 0; + player.totalAltitudeSum = 0; + player.usedWeapons = []; + + player thread onPlayerSpawned(); + player thread monitorPositionCamping(); + player thread monitorClassChange(); + } +} + +onPlayerSpawned() +{ + self endon( "disconnect" ); + + for(;;) + { + self waittill( "spawned_player" ); + + self thread monitorReloads(); + self thread monitorShotsFired(); + self thread monitorSwaps(); + self thread monitorExplosionsSurvived(); + self thread monitorExplosiveHits(); + self thread monitorShieldBlocks(); + self thread monitorFlashHits(); + self thread monitorStunHits(); + self thread monitorStanceTime(); + } +} + +initAwards() +{ + if ( isDefined( level._initGametypeAwards ) ) + [[ level._initGametypeAwards ]](); + + // flags generated from other stats, these are not awards, + // but are checked against for the assignment of some awards + initAwardFlag( "10kills", ::isAtleast, 10, "kills" ); + initAwardFlag( "1death", ::isAtleast, 1, "deaths" ); + initAwardFlag( "nodeaths", ::isAtMost, 0, "deaths" ); + initAwardFlag( "nokills", ::isAtMost, 0, "kills" ); + + // ordered in priority assigned + // TODO: should decouple dependency processing order from order assigned + initMultiAward( "mvp", "kills", "deaths" ); + initMultiAward( "highlander", "10kills", "nodeaths" ); + initThresholdAward( "kdratio10", ::isAtleast, 10, "kdratio" ); + initMultiAward( "punisher", "kills", "killstreak" ); + initMultiAward( "overkill", "kills", "headshots" ); + initDerivedAward( "killedotherteamonelife" ); + initStatAward( "kdratio", 0, ::highestWins ); + initStatAward( "kills", 0, ::highestWins ); + initStatAward( "higherrankkills", 0, ::highestWins ); + initStatAward( "deaths", 0, ::lowestWithHalfPlayedTime ); + initStatAward( "killstreak", 0, ::highestWins ); + initStatAward( "headshots", 0, ::highestWins ); + initDerivedAward( "finalkill" ); + initDerivedAward( "killedotherteam" ); + initStatAward( "closertoenemies", 0, ::highestWins ); + initStatAward( "throwingknifekills", 0, ::highestWins ); + initStatAward( "grenadekills", 0, ::highestWins ); + initStatAward( "helicopters", 0, ::highestWins ); + initStatAward( "airstrikes", 0, ::highestWins ); + initStatAward( "uavs", 0, ::highestWins ); + initStatAward( "mostmultikills", 0, ::highestWins ); + initStatAward( "multikill", 0, ::highestWins ); + initStatAward( "knifekills", 0, ::highestWins ); + initStatAward( "flankkills", 0, ::highestWins ); + initStatAward( "bulletpenkills", 0, ::highestWins ); + initStatAward( "laststandkills", 0, ::highestWins ); + initStatAward( "laststanderkills", 0, ::highestWins ); + initStatAward( "assists", 0, ::highestWins ); + initStatAward( "checkpoints", 0, ::highestWins ); + initStatAward( "c4kills", 0, ::highestWins ); + initStatAward( "claymorekills", 0, ::highestWins ); + initStatAward( "fragkills", 0, ::highestWins ); + initStatAward( "semtexkills", 0, ::highestWins ); + initStatAward( "explosionssurvived",0, ::highestWins ); + initStat( "explosivehits", 0 ); + initStatAward( "mosttacprevented", 0, ::highestWins ); + initStatAward( "avengekills", 0, ::highestWins ); + initStatAward( "rescues", 0, ::highestWins ); + initStatAward( "longshots", 0, ::highestWins ); + initStatAward( "adskills", 0, ::highestWins ); + initStatAward( "hipfirekills", 0, ::highestWins ); + initStatAward( "revengekills", 0, ::highestWins ); + initStatAward( "longestlife", 0, ::highestWins ); + initStatAward( "throwbacks", 0, ::highestWins ); + initStatAward( "thumperkills", 0, ::highestWins ); + initStatAward( "otherweaponkills", 0, ::highestWins ); + initStatAward( "killedsameplayer", 0, ::highestWins, 2 ); + initStatAward( "mostweaponsused", 0, ::highestWins, 3 ); + initStatAward( "distancetraveled", 0, ::highestWins ); + initStatAward( "mostreloads", 0, ::highestWins ); + initStatAward( "mostswaps", 0, ::highestWins ); + initStat( "flankdeaths", 0 ); + initDerivedAward( "noflankdeaths", ::isAtMostWithHalfPlayedTime, 0, "flankdeaths" ); + initStatAward( "thermalkills", 0, ::highestWins ); + initStatAward( "mostcamperkills", 0, ::highestWins ); + initStatAward( "fbhits", 0, ::highestWins ); + initStatAward( "stunhits", 0, ::highestWins ); + initStatAward( "scopedkills", 0, ::highestWins ); + initStatAward( "arkills", 0, ::highestWins ); + initStatAward( "arheadshots", 0, ::highestWins ); + initStatAward( "lmgkills", 0, ::highestWins ); + initStatAward( "lmgheadshots", 0, ::highestWins ); + initStatAward( "sniperkills", 0, ::highestWins ); + initStatAward( "sniperheadshots", 0, ::highestWins ); + initStatAward( "shieldblocks", 0, ::highestWins ); + initStatAward( "shieldkills", 0, ::highestWins ); + initStatAward( "smgkills", 0, ::highestWins ); + initStatAward( "smgheadshots", 0, ::highestWins ); + initStatAward( "shotgunkills", 0, ::highestWins ); + initStatAward( "shotgunheadshots", 0, ::highestWins ); + initStatAward( "pistolkills", 0, ::highestWins ); + initStatAward( "pistolheadshots", 0, ::highestWins ); + initStatAward( "rocketkills", 0, ::highestWins ); + initStatAward( "equipmentkills", 0, ::highestWins ); + initStatAward( "mostclasseschanged",0, ::highestWins ); + initStatAward( "lowerrankkills", 0, ::highestWins ); + initStatAward( "sprinttime", 0, ::highestWins, 1 ); + initStatAward( "crouchtime", 0, ::highestWins ); + initStatAward( "pronetime", 0, ::highestWins ); + initStatAward( "comebacks", 0, ::highestWins ); + initStatAward( "mostshotsfired", 0, ::highestWins ); + initStatAward( "timeinspot", 0, ::highestWins ); + initStatAward( "killcamtimewatched",0, ::highestWins ); + initStatAward( "greatestavgalt", 0, ::highestWins ); + initStatAward( "leastavgalt", 9999999, ::lowestWins ); + initStat( "machinepistolkills", 0 ); + initStat( "machinepistolheadshots", 0 ); + initStat( "killswhilepushingugv", 0 ); + initStat( "killsenemywhopushesugv", 0 ); + initStat( "intelCompleted", 0 ); + initStat( "crouchkills", 0 ); + initStat( "pronekills", 0 ); + initStat( "firstblood", 0 ); + initStat( "backstabber", 0 ); + initStat( "bombsdefender", 0 ); + initStat( "killstunnedenemy", 0 ); + initStat( "killcookedgrenade", 0 ); + initStat( "killwithstolenweapons", 0 ); + initStat( "killwithkillstreaks", 0 ); + initStat( "gamewinningkill", 0 ); + initStat( "killstreakdestroyed", 0 ); + initStat( "killduringenemyairkillstreak", 0 ); + initStat( "topscore", 0 ); + + // Offline/private match only awards + if ( !matchMakingGame() ) + { + initStatAward( "killcamskipped", 0, ::highestWins ); + initStatAward( "killsteals", 0, ::highestWins ); + if ( !getGametypeNumLives() ) + initStatAward( "deathstreak", 0, ::highestWins ); + initStatAward( "shortestlife", 9999999, ::lowestWins ); + initStatAward( "suicides", 0, ::highestWins ); + initStatAward( "mostff", 0, ::highestWins ); + initStatAward( "shotgundeaths", 0, ::highestWins ); + initStatAward( "shielddeaths", 0, ::highestWins ); + initStatAward( "flankdeaths", 0, ::highestWins ); // sets the process property of the "stat only" init above + initMultiAward( "participant", "nokills", "1death" ); + initMultiAward( "afk", "nokills", "nodeaths" ); + + // special case post process award + initDerivedAward( "noawards" ); + } +} + +initBaseAward( ref ) +{ + assert( isDefined( ref ) ); + + level._awards[ ref ] = spawnStruct(); + level._awards[ ref ].winners = []; + level._awards[ ref ].exclusive = true; // For now just make all awards exclusive +} + +initAwardProcess( ref, process, var1, var2 ) +{ + if ( isDefined( process ) ) + level._awards[ ref ].process = process; + + if ( isDefined( var1 ) ) + level._awards[ ref ].var1 = var1; + + if ( isDefined( var2 ) ) + level._awards[ ref ].var2 = var2; +} + +initStat( ref, defaultvalue ) +{ + initBaseAward( ref ); + level._awards[ ref ].defaultvalue = defaultvalue; + level._awards[ ref ].type = "stat"; +} + +initStatAward( ref, defaultvalue, process, var1, var2 ) +{ + initBaseAward( ref ); + initAwardProcess( ref, process, var1, var2 ); + level._awards[ ref ].defaultvalue = defaultvalue; + level._awards[ ref ].type = "stat"; +} + +initDerivedAward( ref, process, var1, var2 ) +{ + initBaseAward( ref ); + initAwardProcess( ref, process, var1, var2 ); + level._awards[ ref ].type = "derived"; +} + +initAwardFlag( ref, process, var1, var2 ) +{ + initBaseAward( ref ); + initAwardProcess( ref, process, var1, var2 ); + level._awards[ ref ].type = "flag"; +} + +initMultiAward( ref, award1_ref, award2_ref ) +{ + assert( isDefined( award1_ref ) ); + assert( isDefined( award2_ref ) ); + + initBaseAward( ref ); + level._awards[ ref ].award1_ref = award1_ref; + level._awards[ ref ].award2_ref = award2_ref; + level._awards[ ref ].type = "multi"; +} + +initThresholdAward( ref, process, var1, var2 ) +{ + initBaseAward( ref ); + initAwardProcess( ref, process, var1, var2 ); + level._awards[ ref ].type = "threshold"; +} + +setMatchRecordIfGreater( ref ) +{ + playerValue = self getPlayerStat( ref ); + playerTime = self getPlayerStatTime( ref ); + recordValue = getAwardRecord( ref ); + recordTime = getAwardRecordTime( ref ); + + if ( !IsDefined( recordValue ) || ( playerValue > recordValue ) ) + { + clearAwardWinners( ref ); + addAwardWinner( ref, self.clientid ); + setAwardRecord( ref, playerValue, playerTime ); + } + else if ( playerValue == recordValue ) + { + if ( isAwardExclusive( ref ) ) + { + if ( !IsDefined( recordTime ) || ( playerTime < recordTime ) ) + { + clearAwardWinners( ref ); + addAwardWinner( ref, self.clientid ); + setAwardRecord( ref, playerValue, playerTime ); + } + } + else + addAwardWinner( ref, self.clientid ); + } +} + +setMatchRecordIfLower( ref ) +{ + playerValue = self getPlayerStat( ref ); + playerTime = self getPlayerStatTime( ref ); + recordValue = getAwardRecord( ref ); + recordTime = getAwardRecordTime( ref ); + + if ( !IsDefined( recordValue ) || ( playerValue < recordValue ) ) + { + clearAwardWinners( ref ); + addAwardWinner( ref, self.clientid ); + setAwardRecord( ref, playerValue, playerTime ); + } + else if ( playerValue == recordValue ) + { + if ( isAwardExclusive( ref ) ) + { + if ( !IsDefined( recordTime ) || ( playerTime < recordTime ) ) + { + clearAwardWinners( ref ); + addAwardWinner( ref, self.clientid ); + setAwardRecord( ref, playerValue, playerTime ); + } + } + else + addAwardWinner( ref, self.clientid ); + } +} + +getDecodedRatio( value ) +{ + loVal = getRatioLoVal( value ); + hiVal = getRatioHiVal( value ); + + if ( !loVal ) + return ( hiVal + 0.001 ); // favor the "n:0" case + + return ( hiVal / loVal ); +} + +setPersonalBestIfGreater( ref ) +{ + recordValue = self getPlayerData( "bests", ref ); + playerValue = self getPlayerStat( ref ); + + if ( recordValue == 0 || ( playervalue > recordValue ) ) + { + playerValue = getFormattedValue( ref, playerValue ); + self setPlayerData( "bests", ref, playerValue ); + } +} + +setPersonalBestIfLower( ref ) +{ + recordvalue = self getPlayerData( "bests", ref ); + playervalue = self getPlayerStat( ref ); + + if ( recordValue == 0 || ( playervalue < recordvalue ) ) + { + playerValue = getFormattedValue( ref, playerValue ); + self setPlayerData( "bests", ref, playerValue ); + } +} + +incPlayerRecord( ref ) +{ + recordValue = self getPlayerData( "awards", ref ); + self setPlayerData( "awards", ref, recordValue + 1 ); + + /# + if ( !isDefined( self.statprint ) ) + self.statprint = []; + + if ( hasDisplayValue( ref ) ) + value = self getPlayerStat( ref ); + else + value = true; + + stat = spawnstruct(); + stat.ref = ref; + stat.value = value; + + self.statprint[ self.statprint.size ] = stat; + #/ +} + +addAwardWinner( ref, clientid ) +{ + foreach ( winner in level._awards[ ref ].winners ) + { + if ( winner == clientid ) + return; + } + + level._awards[ ref ].winners[ level._awards[ ref ].winners.size ] = clientid; +} + +getAwardWinners( ref ) +{ + return level._awards[ ref ].winners; +} + +clearAwardWinners( ref ) +{ + level._awards[ ref ].winners = []; +} + +setAwardRecord( ref, value, time ) +{ + level._awards[ ref ].value = value; + level._awards[ ref ].time = time; +} + +getAwardRecord( ref ) +{ + return level._awards[ ref ].value; +} + +getAwardRecordTime( ref ) +{ + return level._awards[ ref ].time; +} + +// does this work correctly for roundbased games? +assignAwards() +{ + println( "Awards: Assigning" ); + + // Special case handling of awards which get stat values updated at the end of a game + foreach ( player in level._players ) + { + kills = player getPlayerStat( "kills" ); + deaths = player getPlayerStat( "deaths" ); + + if ( deaths == 0 ) + deaths = 1; + + player setPlayerStat( "kdratio", ( kills / deaths ) ); + + if ( isAlive( player ) ) + { + timeAlive = getTime() - player.spawnTime; + player setPlayerStatIfGreater( "longestlife", timeAlive ); + } + } + + // process end of match stats + foreach ( ref, award in level._awards ) + { + if ( !isDefined( level._awards[ ref ].process ) ) + continue; + + process = level._awards[ ref ].process; + var1 = level._awards[ ref ].var1; + var2 = level._awards[ ref ].var2; + + if ( isDefined( var1 ) && isDefined( var2 ) ) + [[ process ]]( ref, var1, var2 ); + else if ( isDefined( var1 ) ) + [[ process ]]( ref, var1 ); + else + [[ process ]]( ref ); + } + + // set multi-award winners + foreach ( ref, award in level._awards ) + { + if ( !isMultiAward( ref ) ) + continue; + + award1_ref = level._awards[ ref ].award1_ref; + award2_ref = level._awards[ ref ].award2_ref; + award1_winners = getAwardWinners( award1_ref ); + award2_winners = getAwardWinners( award2_ref ); + + if ( !isDefined( award1_winners ) || !isDefined( award2_winners ) ) + continue; + + foreach ( winner1 in award1_winners ) + { + foreach ( winner2 in award2_winners ) + { + if ( winner1 == winner2 ) + { + addAwardWinner( ref, winner1 ); + player = playerForClientId( winner1 ); + stat1 = player getPlayerStat( award1_ref ); + stat2 = player getPlayerStat( award2_ref ); + player setPlayerStat( ref, encodeRatio( stat1, stat2 ) ); + } + } + } + } + + // assign awards + foreach ( ref, award in level._awards ) + { + if ( !isAwardFlag( ref ) ) + assignAward( ref ); + } + + // assign "noawards" winners + if ( !matchMakingGame() ) + { + foreach ( player in level._players ) + { + awardCount = player getPlayerData( "round", "awardCount" ); + if ( awardCount == 0 ) + player giveAward( "noawards" ); + } + } + + foreach ( player in level._players ) + { + awardCount = player getPlayerData( "round", "awardCount" ); + + println( "Awards: [", player.name, "] won ", awardCount, " awards" ); + + for ( i = 0; (i < awardCount && i < 3 ); i++ ) + { + award = player getPlayerData( "round", "awards", i, "award" ); + value = player getPlayerData( "round", "awards", i, "value" ); + + println( "Awards: [", player.name, "][", i, "] ", award, " ", value ); + } + + /# + if ( isDefined( player.statprint ) ) + { + for ( i = 3; i < player.statprint.size; i++ ) + println( "Awards: [", player.name, "][", i, "] ", player.statprint[i].ref, " ", player.statprint[i].value ); + } + #/ + } + + println( "Awards: Finished assigning" ); +} + +assignAward( ref ) +{ + winners = getAwardWinners( ref ); + if ( !isDefined( winners ) ) + return; + + foreach ( winner in winners ) + { + foreach ( player in level._players ) + { + if ( player.clientid == winner ) + { + player giveAward( ref ); + // /# player writeAwardLine( ref ); #/ + } + } + } +} + +getAwardType( ref ) +{ + if ( isDefined( level._awards[ ref ].type ) ) + return level._awards[ ref ].type; + else + return "none"; +} + +isMultiAward( ref ) +{ + return ( getAwardType( ref ) == "multi" ); +} + +isStatAward( ref ) +{ + return ( getAwardType( ref ) == "stat" ); +} + +isThresholdAward( ref ) +{ + return ( getAwardType( ref ) == "threshold" ); +} + +isAwardFlag( ref ) +{ + return ( getAwardType( ref ) == "flag" ); +} + +isAwardExclusive( ref ) +{ + if ( isDefined( level._awards[ ref ].exclusive ) ) + return level._awards[ ref ].exclusive; + else + return true; +} + +hasDisplayValue( ref ) +{ + type = getAwardType( ref ); + switch ( type ) + { + case "derived": + hasDisplayValue = false; + break; + case "stat": + case "multi": + default: + hasDisplayValue = true; + break; + } + + return ( hasDisplayValue ); +} + +giveAward( ref ) +{ + awardCount = self getPlayerData( "round", "awardCount" ); + self incPlayerRecord( ref ); + + if ( hasDisplayValue( ref ) ) + { + if ( isStatAward( ref ) ) + assertex( self getPlayerStat( ref ) == getAwardRecord( ref ), "Ref is: " + ref + ", PlayerStat is: " + self getPlayerStat( ref ) + ", MatchRecord is: " + getAwardRecord( ref ) ); + + value = self getPlayerStat( ref ); + } + else + value = true; + + value = getFormattedValue( ref, value ); + + if ( awardCount < 3 ) + { + self setPlayerData( "round", "awards", awardCount, "award", ref ); + self setPlayerData( "round", "awards", awardCount, "value", value ); + } + + awardCount++; + self SetPlayerData( "round", "awardCount", awardCount ); + + if ( awardCount == 1 ) + maps\mp\_highlights::giveHighlight( ref, value ); +} + +getFormattedValue( ref, value ) +{ + awardFormat = tableLookup( "mp/awardTable.csv", 1, ref, 7 ); + switch ( awardFormat ) + { + case "float": + value = limitDecimalPlaces( value, 2 ); + value = value * 100; + break; + case "ratio": + case "multi": + case "count": + case "time": + case "distance": + case "none": + default: + break; + } + + value = int( value ); + return ( value ); +} + +highestWins( ref, minAwardable ) +{ + foreach ( player in level._players ) + { + if ( player statValueChanged( ref ) && ( !isDefined( minAwardable ) || player getPlayerStat( ref ) >= minAwardable ) ) + { + player setMatchRecordIfGreater( ref ); + if ( !isAwardFlag( ref ) ) + player setPersonalBestIfGreater( ref ); + } + } +} + +lowestWins( ref, maxAwardable) +{ + foreach ( player in level._players ) + { + if ( player statValueChanged( ref ) && ( !isDefined( maxAwardable ) || player getPlayerStat( ref ) <= maxAwardable ) ) + { + player setMatchRecordIfLower( ref ); + if ( !isAwardFlag( ref ) ) + player setPersonalBestIfLower( ref ); + } + } +} + +lowestWithHalfPlayedTime( ref ) +{ + gameLength = getTimePassed() / 1000; + halfGameLength = gameLength * 0.5; + + foreach ( player in level._players ) + { + // hasSpawned check is required or players who pick a team and never spawn can win awards + if ( player.hasSpawned && player.timePlayed["total"] >= halfGameLength ) + { + player setMatchRecordIfLower( ref ); + if ( !isAwardFlag( ref ) ) + player setPersonalBestIfLower( ref ); + } + } +} + +statValueChanged( ref ) +{ + playervalue = self getPlayerStat( ref ); + defaultvalue = level._awards[ ref ].defaultvalue; + + if ( playervalue == defaultvalue ) + return false; + else + return true; +} + + +isAtLeast( ref, minimum, checkAwardRef ) +{ + foreach ( player in level._players ) + { + playerValue = player getPlayerStat( checkAwardRef ); + checkValue = playerValue; + + if ( checkValue >= minimum ) + addAwardWinner( ref, player.clientid ); + + // TODO: Instead of copying the value, reference the other stat directly + if ( isThresholdAward( ref ) || isAwardFlag( ref ) ) + player setPlayerStat( ref, playerValue ); + } +} + + +isAtMost( ref, maximum, award_ref ) +{ + foreach ( player in level._players ) + { + playerValue = player getPlayerStat( award_ref ); + + if ( playerValue <= maximum ) + addAwardWinner( ref, player.clientid ); + } +} + + +isAtMostWithHalfPlayedTime( ref, maximum, award_ref ) +{ + gameLength = getTimePassed() / 1000; + halfGameLength = gameLength * 0.5; + + foreach ( player in level._players ) + { + // hasSpawned check is required or players who pick a team and never spawn can win awards + if ( player.hasSpawned && player.timePlayed["total"] >= halfGameLength ) + { + playerValue = player getPlayerStat( award_ref ); + + if ( playerValue <= maximum ) + addAwardWinner( ref, player.clientid ); + } + } +} + + +setRatio( ref, award1_ref, award2_ref ) +{ + foreach ( player in level._players ) + { + playerValue1 = player getPlayerStat( award1_ref ); + playerValue2 = player getPlayerStat( award2_ref ); + + if ( playerValue2 == 0 ) + player setPlayerStat( ref, playerValue1 ); + else + { + ratio = playerValue1 / playerValue2; + player setPlayerStat( ref, ratio ); + } + } +} + +getKillstreakAwardRef( streakName ) +{ + switch( streakName ) + { + case "uav": + case "double_uav": + case "counter_uav": + return "uavs"; + case "airstrike": + case "precision_airstrike": + case "stealth_airstrike": + case "harrier_airstrike": + case "super_airstrike": + return "airstrikes"; + case "helicopter": + case "helicopter_minigun": + case "helicopter_mk19": + case "helicopter_blackbox": + case "helicopter_flares": + return "helicopters"; + default: + return undefined; + } +} + +monitorReloads() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for ( ;; ) + { + self waittill( "reload" ); + self incPlayerStat( "mostreloads", 1 ); + } +} + +monitorShotsFired() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for ( ;; ) + { + self waittill( "weapon_fired" ); + self incPlayerStat( "mostshotsfired", 1 ); + } +} + +monitorSwaps() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + lastWeapon = "none"; + + for ( ;; ) + { + self waittill( "weapon_change", weapon ); + + if ( lastWeapon == weapon ) + continue; + + if ( weapon == "none" ) + continue; + + if ( ! maps\mp\gametypes\_weapons::isPrimaryWeapon( weapon ) ) + continue; + + lastWeapon = weapon; + + self incPlayerStat( "mostswaps", 1 ); + + alreadyUsed = false; + + //creates an array of weapons used + foreach( usedWeapon in self.usedWeapons ) + { + if ( weapon == usedWeapon ) + { + alreadyUsed = true; + break; + } + } + + if ( !alreadyUsed ) + { + self.usedWeapons[self.usedWeapons.size] = weapon; + self incPlayerStat( "mostweaponsused", 1 ); + } + } +} + + +monitorMovementDistance() +{ + level endon( "game_ended" ); + self endon( "disconnect" ); + + for ( ;; ) + { + foreach ( player in level._players ) + { + if ( !isAlive( Player ) ) + continue; + + if ( player.deaths != player.previousDeaths ) + { + player.prevPos = player.origin; + player.previousDeaths = player.deaths; + } + + distanceTraveled = Distance( player.origin, player.prevPos ); + player incPlayerStat( "distancetraveled", distanceTraveled ); + + player.prevPos = player.origin; + + player.altitudePolls++; + player.totalAltitudeSum += player.origin[2]; + avgAltitude = player.totalAltitudeSum / player.altitudePolls; + player setPlayerStat( "leastavgalt", avgAltitude ); + player setPlayerStat( "greatestavgalt", avgAltitude ); + + wait( 0.05 ); + } + wait( 0.05 ); + } +} + +monitorPositionCamping() +{ + level endon( "game_ended" ); + self endon( "disconnect" ); + + self.lastCampChecked = getTime(); + self.positionArray = []; + + CAMPTHRESHOLD = 512; + + for ( ;; ) + { + if ( !isAlive( self ) ) + { + wait( 0.5 ); + self.lastCampChecked = getTime(); + self.positionArray = []; + continue; + } + self.positionArray[self.positionArray.size] = self.origin; + + if ( ( getTime() - self.lastCampChecked ) >= 15000 ) + { + if ( Distance( self.positionArray[0], self.origin ) < CAMPTHRESHOLD && Distance( self.positionArray[1], self.positionArray[0] ) < CAMPTHRESHOLD ) + { + timeCamping = getTime() - self.lastCampChecked; + self incPlayerStat( "timeinspot", timeCamping ); + } + + self.positionArray = []; + + self.lastCampChecked = getTime(); + } + wait( 5 ); + } +} + +encodeRatio( value1, value2 ) +{ + return ( value1 + (value2 << 16) ); +} + +getRatioHiVal( value ) +{ + return (value & 65535); +} + +getRatioLoVal( value ) +{ + return (value >> 16); +} + +monitorEnemyDistance() +{ + level endon( "game_ended" ); + self endon( "disconnect" ); + + while( level._players.size < 3 ) + wait( 1 ); + + prof_begin( "EnemyDistance" ); + for ( ;; ) + { + foreach ( player in level._players ) + { + + if ( !isdefined( player ) ) + continue; + + if ( player.team == "spectator" ) + continue; + + if ( !isAlive( player ) ) + continue; + + sortedPlayersByDistance = SortByDistance( level._players, player.origin ); + + if( !sortedPlayersByDistance.size ) + { + wait( 0.05 ); + continue; + } + + if ( sortedPlayersByDistance.size < 2 ) + { + wait( 0.05 ); + continue; + } + + if ( sortedPlayersByDistance[1].team != player.team ) + player incPlayerStat( "closertoenemies", 0.05 ); + + wait( 0.05 ); + } + + wait( 0.05); + } + + prof_end( "EnemyDistance" ); +} + +monitorClassChange() +{ + level endon( "game_ended" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "spawned" ); + + if ( self.team == "spectator" ) + continue; + + if( isDefined( self.lastClass ) && self.lastClass != "" && self.lastClass != self.class ) + { + self incPlayerStat( "mostclasseschanged", 1 ); + } + + self.lastClass = self.class; + } +} + +monitorExplosionsSurvived() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "survived_explosion" ); + self incPlayerStat( "explosionssurvived", 1 ); + wait( 0.05 ); + } +} + +monitorExplosiveHits() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "explosive_hits" ); + self incPlayerStat( "explosivehits", 1 ); + wait( 0.05 ); + } +} + +monitorShieldBlocks() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "shield_blocked" ); + self incPlayerStat( "shieldblocks", 1 ); + wait( 0.05 ); + } +} + +monitorFlashHits() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "flash_hit" ); + self incPlayerStat( "fbhits", 1 ); + wait( 0.05 ); + } +} + +monitorStunHits() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + self waittill( "stun_hit" ); + self incPlayerStat( "stunhits", 1 ); + wait( 0.05 ); + } +} + +//this approximates a players time spent in crouch or prone. +monitorStanceTime() +{ + level endon( "game_ended" ); + self endon( "spawned_player" ); + self endon( "death" ); + self endon( "disconnect" ); + + for(;;) + { + if ( self GetStance() == "crouch" ) + self incPlayerStat( "crouchtime", 500 ); + else if ( self GetStance() == "prone" ) + self incPlayerStat( "pronetime", 500 ); + + wait( 0.5 ); + } +} \ No newline at end of file diff --git a/maps/mp/_compass.gsc b/maps/mp/_compass.gsc new file mode 100644 index 0000000..a1c77c4 --- /dev/null +++ b/maps/mp/_compass.gsc @@ -0,0 +1,79 @@ +setupMiniMap(material) +{ + // use 0 for no required map aspect ratio. + requiredMapAspectRatio = level._requiredMapAspectRatio; + + corners = getentarray("minimap_corner", "targetname"); + if (corners.size != 2) + { + println("^1Error: There are not exactly two \"minimap_corner\" entities in the map. Could not set up minimap."); + return; + } + + corner0 = (corners[0].origin[0], corners[0].origin[1], 0); + corner1 = (corners[1].origin[0], corners[1].origin[1], 0); + + cornerdiff = corner1 - corner0; + + north = (cos(getnorthyaw()), sin(getnorthyaw()), 0); + west = (0 - north[1], north[0], 0); + + // we need the northwest and southeast corners. all we know is that corner0 is opposite of corner1. + if (vectordot(cornerdiff, west) > 0) { + // corner1 is further west than corner0 + if (vectordot(cornerdiff, north) > 0) { + // corner1 is northwest, corner0 is southeast + northwest = corner1; + southeast = corner0; + } + else { + // corner1 is southwest, corner0 is northeast + side = vecscale(north, vectordot(cornerdiff, north)); + northwest = corner1 - side; + southeast = corner0 + side; + } + } + else { + // corner1 is further east than corner0 + if (vectordot(cornerdiff, north) > 0) { + // corner1 is northeast, corner0 is southwest + side = vecscale(north, vectordot(cornerdiff, north)); + northwest = corner0 + side; + southeast = corner1 - side; + } + else { + // corner1 is southeast, corner0 is northwest + northwest = corner0; + southeast = corner1; + } + } + + // expand map area to fit required aspect ratio + if ( requiredMapAspectRatio > 0 ) + { + northportion = vectordot(northwest - southeast, north); + westportion = vectordot(northwest - southeast, west); + mapAspectRatio = westportion / northportion; + if ( mapAspectRatio < requiredMapAspectRatio ) + { + incr = requiredMapAspectRatio / mapAspectRatio; + addvec = vecscale( west, westportion * (incr - 1) * 0.5 ); + } + else + { + incr = mapAspectRatio / requiredMapAspectRatio; + addvec = vecscale( north, northportion * (incr - 1) * 0.5 ); + } + northwest += addvec; + southeast -= addvec; + } + + level._mapSize = vectordot(northwest - southeast, north); + + setMiniMap(material, northwest[0], northwest[1], southeast[0], southeast[1]); +} + +vecscale(vec, scalar) +{ + return (vec[0]*scalar, vec[1]*scalar, vec[2]*scalar); +} \ No newline at end of file diff --git a/maps/mp/_createfx.gsc b/maps/mp/_createfx.gsc new file mode 100644 index 0000000..ba5f073 --- /dev/null +++ b/maps/mp/_createfx.gsc @@ -0,0 +1,82 @@ +#include common_scripts\utility; +#include maps\mp\_utility; +#include common_scripts\_createFxMenu; +#include common_scripts\_createfx; +#include common_scripts\_fx; + +createfx() +{ + // tagPP by the time createfx is called, player position is already updated so those 2 functions don't work anymore. + level._func_position_player = ::void; + level._func_position_player_get = ::func_position_player_get; + + level._func_loopfxthread = ::loopfxthread; + level._func_oneshotfxthread = ::oneshotfxthread; + level._func_create_loopsound = ::create_loopsound; + level._func_updatefx = ::restart_fx_looper; + level._func_process_fx_rotater = ::process_fx_rotater; + level._mp_createfx = true; + + // tagPP what do they do? + // level.func_exploder_preload = ::exploder_before_load; + // level.func_exploder_postload = ::exploder_after_load; + + + // MP only stuff + // level._callbackStartGameType = ::void; // Take it out because it broke server/client message. + level._callbackPlayerConnect = ::void; + level._callbackPlayerDisconnect = ::void; + level._callbackPlayerDamage = ::void; + level._callbackPlayerKilled = ::void; + level._callbackCodeEndGame = ::void; + level._callbackPlayerLastStand = ::void; + level._callbackPlayerConnect = ::Callback_PlayerConnect; + level._callbackPlayerMigrated = ::void; + + // build _effect_keys array + func_get_level_fx(); + + // remove triggers, turn on painter. + createfx_common(); + + level waittill( "eternity" ); +} + +func_position_player_get( lastPlayerOrigin ) +{ + return level._player.origin; +} + +Callback_PlayerConnect() +{ + self waittill( "begin" ); + + if ( !isdefined( level._player ) ) + { + spawnpoints = getentarray( "mp_global_intermission", "classname" ); + + self spawn( spawnpoints[0].origin, spawnpoints[0].angles ); + self maps\mp\gametypes\_playerlogic::updateSessionState( "playing", "" ); + self.maxhealth = 10000000; + self.health = 10000000; + + level._player = self; + + // createFX thread + thread createFxLogic(); + + // hack + thread ufo_mode(); + } + else + { + kick( self GetEntityNumber() ); + } +} + +ufo_mode() +{ + // painter.menu execs some console commands( ufo mode ).. sneaky hacks. + level._player openpopupmenu( "painter_mp" ); + level._player closepopupmenu( "painter_mp" ); +} \ No newline at end of file diff --git a/maps/mp/_defcon.gsc b/maps/mp/_defcon.gsc new file mode 100644 index 0000000..08a9baf --- /dev/null +++ b/maps/mp/_defcon.gsc @@ -0,0 +1,137 @@ +#include common_scripts\utility; +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; + +// if ( game["state"] == "postgame" && game["teamScores"][attacker.team] > game["teamScores"][level.otherTeam[attacker.team]] ) + +ICONSIZE = 20; + +init() +{ + if ( !isDefined( level._defconMode ) || level._defconMode == false ) + return; + + if ( !isDefined( game["defcon"] ) ) + game["defcon"] = 4; + + makeDvarServerInfo( "scr_defcon", game["defcon"] ); + + /# setDevDvarIfUninitialized( "scr_defconStreak", 10 ); #/ + + level._defconStreakAdd[5] = 0; + level._defconStreakAdd[4] = 0; + level._defconStreakAdd[3] = -1; + level._defconStreakAdd[2] = -1; + level._defconStreakAdd[1] = -1; + + level._defconPointMod[5] = 1; + level._defconPointMod[4] = 1; + level._defconPointMod[3] = 1; + level._defconPointMod[2] = 1; + level._defconPointMod[1] = 2; + + updateDefcon( game["defcon"] ); + thread defconKillstreakThread(); +} + +defconKillstreakWait( streakCount ) +{ + for ( ;; ) + { + level waittill ( "player_got_killstreak_" + streakCount, player ); + level notify ( "defcon_killstreak", streakCount, player ); + } +} + + +defconKillstreakThread() +{ + level endon ( "game_ended" ); + + requiredKillCount = 10; + + /# + requiredKillCount = getDvarInt( "scr_defconStreak" ); + #/ + + level thread defconKillstreakWait( requiredKillCount ); + level thread defconKillstreakWait( requiredKillCount - 1 ); + level thread defconKillstreakWait( requiredKillCount - 2 ); + + level thread defconKillstreakWait( (requiredKillCount * 2) ); + level thread defconKillstreakWait( (requiredKillCount * 2) - 1 ); + level thread defconKillstreakWait( (requiredKillCount * 2) - 2 ); + + level thread defconKillstreakWait( (requiredKillCount * 3) ); + level thread defconKillstreakWait( (requiredKillCount * 3) - 1 ); + level thread defconKillstreakWait( (requiredKillCount * 3) - 2 ); + + for ( ;; ) + { + level waittill ( "defcon_killstreak", streakCount, changingPlayer ); + + if ( game["defcon"] <= 1 ) + continue; + + if ( (streakCount % requiredKillCount) == requiredKillCount - 2 ) + { + foreach ( player in level._players ) + { + if ( !isAlive( player ) ) + continue; + + player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "two_from_defcon", changingPlayer ); + } + } + else if ( (streakCount % requiredKillCount) == requiredKillCount - 1 ) + { + foreach ( player in level._players ) + { + if ( !isAlive( player ) ) + continue; + + player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "one_from_defcon", changingPlayer ); + } + } + else + { + updateDefcon( game["defcon"] - 1, changingPlayer, streakCount ); + } + } +} + + +updateDefcon( newDefcon, changingPlayer, streakCount ) +{ + newDefcon = int( newDefcon ); + oldDefcon = game["defcon"]; + game["defcon"] = newDefcon; + +// level.killStreakMod = level.defconStreakAdd[newDefcon]; + level._objectivePointsMod = level._defconPointMod[newDefcon]; + + setDvar( "scr_defcon", game["defcon"] ); + + //isdefined used for variable init + if( isDefined( changingPlayer ) ) + changingPlayer notify( "changed_defcon" ); + + if ( newDefcon == oldDefcon ) + return; + + if ( game["defcon"] == 3 && isDefined( changingPlayer ) ) + { + changingPlayer maps\mp\killstreaks\_killstreaks::giveKillstreak( "airdrop_mega" ); + changingPlayer thread maps\mp\gametypes\_hud_message::splashNotify( "caused_defcon" , streakCount ); + } + + foreach ( player in level._players ) + { + if ( isAlive( player ) ) + { + player thread maps\mp\gametypes\_hud_message::defconSplashNotify( game["defcon"], newDefcon < oldDefcon ); + if ( isDefined( changingPlayer ) ) + player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "changed_defcon", changingPlayer ); + } + } +} \ No newline at end of file diff --git a/maps/mp/_destructables.gsc b/maps/mp/_destructables.gsc new file mode 100644 index 0000000..07abc12 --- /dev/null +++ b/maps/mp/_destructables.gsc @@ -0,0 +1,100 @@ +init() +{ + // level.destructableFX = loadfx("breakables/exp_wall_cinderblock_96"); + + ents = getentarray("destructable", "targetname"); + + if (getdvar("scr_destructables") == "0") + { + for (i = 0; i < ents.size; i++) + ents[i] delete(); + } + else + { + for (i = 0; i < ents.size; i++) + { + ents[i] thread destructable_think(); + } + } +} + +destructable_think() +{ + accumulate = 40; + threshold = 0; + + if (isdefined(self.script_accumulate)) + accumulate = self.script_accumulate; + if (isdefined(self.script_threshold)) + threshold = self.script_threshold; + + if (isdefined(self.script_destructable_area)) { + areas = strtok(self.script_destructable_area, " "); + for (i = 0; i < areas.size; i++) + self blockArea(areas[i]); + } + + if ( isdefined( self.script_fxid ) ) + self.fx = loadfx( self.script_fxid ); + + dmg = 0; + + self setcandamage(true); + while(1) + { + self waittill("damage", amount, other); + if (amount >= threshold) + { + dmg += amount; + if (dmg >= accumulate) + { + self thread destructable_destruct(); + return; + } + } + } +} + +destructable_destruct() +{ + ent = self; + if (isdefined(self.script_destructable_area)) { + areas = strtok(self.script_destructable_area, " "); + for (i = 0; i < areas.size; i++) + self unblockArea(areas[i]); + } + if ( isdefined( ent.fx ) ) + playfx( ent.fx, ent.origin + (0,0,6) ); + ent delete(); +} + +blockArea(area) +{ + spawns = getentarray("mp_tdm_spawn", "classname"); + blockEntsInArea(spawns, area); + spawns = getentarray("mp_dm_spawn", "classname"); + blockEntsInArea(spawns, area); +} +blockEntsInArea(ents, area) +{ + for (i = 0; i < ents.size; i++) { + if (!isdefined(ents[i].script_destructable_area) || ents[i].script_destructable_area != area) + continue; + ents[i].blockedoff = true; + } +} +unblockArea(area) +{ + spawns = getentarray("mp_tdm_spawn", "classname"); + unblockEntsInArea(spawns, area); + spawns = getentarray("mp_dm_spawn", "classname"); + unblockEntsInArea(spawns, area); +} +unblockEntsInArea(ents, area) +{ + for (i = 0; i < ents.size; i++) { + if (!isdefined(ents[i].script_destructable_area) || ents[i].script_destructable_area != area) + continue; + ents[i].blockedoff = false; + } +} \ No newline at end of file diff --git a/maps/mp/_doorbreach.gsc b/maps/mp/_doorbreach.gsc new file mode 100644 index 0000000..023a22c --- /dev/null +++ b/maps/mp/_doorbreach.gsc @@ -0,0 +1,1602 @@ +//**************************************************************************** + // ** + // Confidential - (C) Activision Publishing, Inc. 2011 ** + // ** + //**************************************************************************** + // ** + // Module: _doorbreach.gsc ** + // ** + // Created: 5/24/2011 - Eric Milota ** + // ** + //**************************************************************************** + + #include maps\mp\_utility; + #include common_scripts\utility; + #include maps\mp\gametypes\_hud_util; + + //**************************************************************************** + // How to add door breaching tech to your levels. + // + // (1) Drop down one or more \\DEPOT\TREES\NX1\GAME\MAP_SOURCE\PREFABS\MP\DOORBREACH_DOOR1.MAP + // throughout your level in doorways. + // (2) Drop one and only one "\\DEPOT\TREES\NX1\GAME\MAP_SOURCE\PREFABS\MP\DOORBREACH_GRAVEYARD.MAP" + // somewhere outside the working area of your map. + // (3) Add "rawfile,maps/mp/_doorbreach.gsc" to your level CSV file. + // (4) Add the following to your level main() function: + // (a) If you want to start the level with doors installed, add + // maps\mp\_doorbreach::doorbreach_setup( 1, 1 ); // 0=start with no doors/walls, 1=start with doors/walls, -1=default (no doors, yes walls) + // (b) If you want to start the level with doors absent, add + // maps\mp\_doorbreach::doorbreach_setup( 0, 1 ); // 0=start with no doors/walls, 1=start with doors/walls, -1=default (no doors, yes walls) + // NOTE: Use can use -1 for "default", which currently is NO DOORS. + // + // Compile your map and build and run your level. That should be it! + // + // -------------------------------------------------------------------- + // Known bugs/issues: + // + // * Timings are currently hard coded. See doorbreach_setup() for info. + // * If doorbreach_setup() is passes a 0, currently doors/walls are + // not placed, but you can't immediately install....there's a bug + // that is currently preventing me from starting them in + // the "no_door_ready" state, so instead I'm using "no_door_wait" state, + // which appears to work. + // + // -------------------------------------------------------------------- + // What's in those prefabs? + // + // Door prefabs: + // + // * Script origin with "targetname" equal to "doorbreachorigin". + // This object should be at the center of your doorway. + // * Script brush with "targetname" equal to "doorbreachmodel". + // This object should be your door model. + // * Script model with "targetname" equal to "doorbreachnogo". + // This object should be the brush that will block you from going + // through the doorway. + // * Script origin with "targetname" equal to "doorbreachtriggerfront". + // This object will be the centerpoint of where you need to stand to + // trigger the front bomb placement. + // * Script model with "targetname" equal to "doorbreachbombfront". + // This object should be your front bomb model. + // * Script origin with "targetname" equal to "doorbreachtriggerback". + // This object will be the centerpoint of where you need to stand to + // trigger the back bomb placement. + // * Script model with "targetname" equal to "doorbreachbombback". + // This object should be your back bomb model. + // + // Graveyard prefabs: + // + // * Script origin with "targetname" equal to "doorbreachnogograveyard" + // If a script origin with this name exists on the map, this is where + /// NOGO objects are moved when the door has been breached. + // + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_setup( start_with_doors, start_with_walls ) // 0=start with no doors/walls, 1=start with doors/walls, -1=default (no doors, yes walls) + { + originarray = GetEntArray( "doorbreachorigin", "targetname" ); + if( !IsDefined( originarray[0] ) ) + { + return; // no door breach origin objects, therefore there is nothing to do + } + + if( !IsDefined( start_with_doors ) ) + { + start_with_doors = -1; // set to "default" + } + + if( !IsDefined( start_with_walls ) ) + { + start_with_walls = -1; // set to "default" + } + + // setup constants... + level._doorbreach_time_door_plant_bomb = 2.0 * 1000; // 2 seconds + level._doorbreach_time_door_build = 2.0 * 1000; // 2 seconds + level._doorbreach_time_door_rebuild = 2.0 * 1000; // 2 seconds + level._doorbreach_time_wall_plant_bomb = 6.0 * 1000; // 6 seconds + level._doorbreach_time_wall_build = 10.0 * 1000; // 10 seconds + level._doorbreach_time_wall_rebuild = 12.0 * 1000; // 12 seconds + level._doorbreach_wait_time_before_breachable = 0.0; // must wait this long after building door/wall before it becomes breachable + level._doorbreach_wait_time_bomb_fuse = 5.0; // bombs take this long before they blow up + level._doorbreach_wait_time_before_can_rebuild = 0.0; // door/wall must have been exploded for this long before you can rebuild it again + level._doorbreach_move_delta_x = 0.0; + level._doorbreach_move_delta_y = 0.0; + level._doorbreach_move_delta_z = -3000.0; + level._doorbreach_blocked_door_distance = 30.0; + level._doorbreach_blocked_wall_distance = 80.0; + level._doorbreach_explosion_flashbang_distance = 250.0; + level._doorbreach_explosion_shake_radius = 2000.0; + level._doorbreach_collecting_objects_max_distance = 200.0; // 200.0/12.0 --> 16.6 feet. All items pertaining to this door must be within this radius! + + level._doorbreach_soundfx_explosion = "prototype_door_explode"; //sentry_explode"; //mortar_explosion1"; //"sentry_explode" + level._doorbreach_soundfx_bomb_placed = "prototype_door_activate"; + level._doorbreach_soundfx_bomb_beep = "prototype_door_beep"; //elevator_pass_floor_beep"; //"sentry_gun_beep" + level._doorbreach_soundfx_door_blocked = "prototype_door_blocked"; + level._doorbreach_soundfx_door_created = "prototype_door_create"; + level._doorbreach_soundfx_wall_blocked = "prototype_door_blocked"; + level._doorbreach_soundfx_wall_created = "prototype_door_create"; + + level._doorbreach_text_planting_bomb = &"MP_DOORBREACH_PLANTING_BOMB"; // "Planting bomb. Stand by..."; + level._doorbreach_text_countdown_5 = &"MP_DOORBREACH_COUNTDOWN_5"; // "5 seconds..."; + level._doorbreach_text_countdown_4 = &"MP_DOORBREACH_COUNTDOWN_4"; // "4 seconds..."; + level._doorbreach_text_countdown_3 = &"MP_DOORBREACH_COUNTDOWN_3"; // "3 seconds..."; + level._doorbreach_text_countdown_2 = &"MP_DOORBREACH_COUNTDOWN_2"; // "2 seconds..."; + level._doorbreach_text_countdown_1 = &"MP_DOORBREACH_COUNTDOWN_1"; // "1 seconds..."; + + level._doorbreach_text_door_press_and_hold_to_breach = &"MP_DOORBREACH_DOOR_BREACH"; // "Press and hold^3 &&1 ^7to breach door"; + level._doorbreach_text_door_press_and_hold_to_install = &"MP_DOORBREACH_DOOR_INSTALL"; // "Press and hold^3 &&1 ^7to install door"; + level._doorbreach_text_door_press_and_hold_to_rebuild = &"MP_DOORBREACH_DOOR_REBUILD"; // "Press and hold^3 &&1 ^7to repair door"; + level._doorbreach_text_door_blocked = &"MP_DOORBREACH_DOOR_BLOCKED"; // "Clear the doorway first!"; + level._doorbreach_text_door_installing = &"MP_DOORBREACH_DOOR_INSTALLING"; // "Installing door. Stand by..."; + level._doorbreach_text_door_repairing = &"MP_DOORBREACH_DOOR_REPAIRING"; // "Repairing door. Stand by..."; + level._doorbreach_text_door_installed = &"MP_DOORBREACH_DOOR_INSTALLED"; // "Door installed"; + level._doorbreach_text_door_repaired = &"MP_DOORBREACH_DOOR_REPAIRED"; // "Door repaired"; + level._doorbreach_text_door_breached = &"MP_DOORBREACH_DOOR_BREACHED"; // "Door breached!"; + + level._doorbreach_text_wall_press_and_hold_to_breach = &"MP_DOORBREACH_WALL_BREACH"; // "Press and hold^3 &&1 ^7to breach wall"; + level._doorbreach_text_wall_press_and_hold_to_install = &"MP_DOORBREACH_WALL_INSTALL"; // "Press and hold^3 &&1 ^7to install wall"; + level._doorbreach_text_wall_press_and_hold_to_rebuild = &"MP_DOORBREACH_WALL_REBUILD"; // "Press and hold^3 &&1 ^7to repair wall"; + level._doorbreach_text_wall_blocked = &"MP_DOORBREACH_WALL_BLOCKED"; // "Clear the pathway first!"; + level._doorbreach_text_wall_installing = &"MP_DOORBREACH_WALL_INSTALLING"; // "Installing wall. Stand by..."; + level._doorbreach_text_wall_repairing = &"MP_DOORBREACH_WALL_REPAIRING"; // "Repairing wall. Stand by..."; + level._doorbreach_text_wall_installed = &"MP_DOORBREACH_WALL_INSTALLED"; // "Wall installed"; + level._doorbreach_text_wall_repaired = &"MP_DOORBREACH_WALL_REPAIRED"; // "Wall repaired"; + level._doorbreach_text_wall_breached = &"MP_DOORBREACH_WALL_BREACHED"; // "Wall breached!"; + + level._effect["doorbreach_explosion"] = loadfx( "explosions/tanker_explosion" ); + + level._doorbreach_origins = []; // let's default to empty list + + + precacheString( level._doorbreach_text_planting_bomb ); // = &"MP_DOORBREACH_PLANTING_BOMB"; // "Planting bomb. Stand by..."; + precacheString( level._doorbreach_text_countdown_5 ); // = &"MP_DOORBREACH_COUNTDOWN_5"; // "5 seconds..."; + precacheString( level._doorbreach_text_countdown_4 ); // = &"MP_DOORBREACH_COUNTDOWN_4"; // "4 seconds..."; + precacheString( level._doorbreach_text_countdown_3 ); // = &"MP_DOORBREACH_COUNTDOWN_3"; // "3 seconds..."; + precacheString( level._doorbreach_text_countdown_2 ); // = &"MP_DOORBREACH_COUNTDOWN_2"; // "2 seconds..."; + precacheString( level._doorbreach_text_countdown_1 ); // = &"MP_DOORBREACH_COUNTDOWN_1"; // "1 seconds..."; + + precacheString( level._doorbreach_text_door_press_and_hold_to_breach ); // = &"MP_DOORBREACH_DOOR_BREACH"; // "Press and hold^3 &&1 ^7to breach door"; + precacheString( level._doorbreach_text_door_press_and_hold_to_install ); // = &"MP_DOORBREACH_DOOR_INSTALL"; // "Press and hold^3 &&1 ^7to install door"; + precacheString( level._doorbreach_text_door_press_and_hold_to_rebuild ); // = &"MP_DOORBREACH_DOOR_REBUILD"; // "Press and hold^3 &&1 ^7to repair door"; + precacheString( level._doorbreach_text_door_blocked ); // = &"MP_DOORBREACH_DOOR_BLOCKED"; // "Clear the doorway first!"; + precacheString( level._doorbreach_text_door_installing ); // = &"MP_DOORBREACH_DOOR_INSTALLING"; // "Installing door. Stand by..."; + precacheString( level._doorbreach_text_door_repairing ); // = &"MP_DOORBREACH_DOOR_REPAIRING"; // "Repairing door. Stand by..."; + precacheString( level._doorbreach_text_door_installed ); // = &"MP_DOORBREACH_DOOR_INSTALLED"; // "Door installed"; + precacheString( level._doorbreach_text_door_repaired ); // = &"MP_DOORBREACH_DOOR_REPAIRED"; // "Door repaired"; + precacheString( level._doorbreach_text_door_breached ); // = &"MP_DOORBREACH_DOOR_BREACHED"; // "Door breached!"; + + precacheString( level._doorbreach_text_wall_press_and_hold_to_breach ); // = &"MP_DOORBREACH_WALL_BREACH"; // "Press and hold^3 &&1 ^7to breach wall"; + precacheString( level._doorbreach_text_wall_press_and_hold_to_install ); // = &"MP_DOORBREACH_WALL_INSTALL"; // "Press and hold^3 &&1 ^7to install wall"; + precacheString( level._doorbreach_text_wall_press_and_hold_to_rebuild ); // = &"MP_DOORBREACH_WALL_REBUILD"; // "Press and hold^3 &&1 ^7to repair wall"; + precacheString( level._doorbreach_text_wall_blocked ); // = &"MP_DOORBREACH_WALL_BLOCKED"; // "Clear the pathway first!"; + precacheString( level._doorbreach_text_wall_installing ); // = &"MP_DOORBREACH_WALL_INSTALLING"; // "Installing wall. Stand by..."; + precacheString( level._doorbreach_text_wall_repairing ); // = &"MP_DOORBREACH_WALL_REPAIRING"; // "Repairing wall. Stand by..."; + precacheString( level._doorbreach_text_wall_installed ); // = &"MP_DOORBREACH_WALL_INSTALLED"; // "Wall installed"; + precacheString( level._doorbreach_text_wall_repaired ); // = &"MP_DOORBREACH_WALL_REPAIRED"; // "Wall repaired"; + precacheString( level._doorbreach_text_wall_breached ); // = &"MP_DOORBREACH_WALL_BREACHED"; // "Wall breached!"; + + // we've got some breaching doors! + + level._doorbreach_origins = originarray; + + modelarray = GetEntArray( "doorbreachmodel", "targetname" ); + nogoarray = GetEntArray( "doorbreachnogo", "targetname" ); + triggerfrontarray = GetEntArray( "doorbreachtriggerfront", "targetname" ); + bombfrontarray = GetEntArray( "doorbreachbombfront", "targetname" ); + triggerbackarray = GetEntArray( "doorbreachtriggerback", "targetname" ); + bombbackarray = GetEntArray( "doorbreachbombback", "targetname" ); + model2array = GetEntArray( "doorbreachmodel2", "targetname" ); + model3array = GetEntArray( "doorbreachmodel3", "targetname" ); + + level._doorbreach_nogo_graveyard_object = undefined; + nogograveyardarray = GetEntArray( "doorbreachnogograveyard", "targetname" ); + if( IsDefined( nogograveyardarray[0] ) ) + { + level._doorbreach_nogo_graveyard_object = nogograveyardarray[0]; + } + + for( i = 0; i < level._doorbreach_origins.size; i++ ) + { + originobject = level._doorbreach_origins[ i ]; + + // find models + modelobject = doorbreach_find_best_object( modelarray, originobject ); + if( IsDefined( modelobject ) ) + { + modelarray = doorbreach_remove_object_from_list( modelarray, modelobject ); + } + nogoobject = doorbreach_find_best_object( nogoarray, originobject ); + if( IsDefined( nogoobject ) ) + { + nogoarray = doorbreach_remove_object_from_list( nogoarray, nogoobject ); + } + triggerfrontobject = doorbreach_find_best_object( triggerfrontarray, originobject ); + if( IsDefined( triggerfrontobject ) ) + { + triggerfrontarray = doorbreach_remove_object_from_list( triggerfrontarray, triggerfrontobject ); + } + bombfrontobject = doorbreach_find_best_object( bombfrontarray, originobject ); + if( IsDefined( bombfrontobject ) ) + { + bombfrontarray = doorbreach_remove_object_from_list( bombfrontarray, bombfrontobject ); + } + triggerbackobject = doorbreach_find_best_object( triggerbackarray, originobject ); + if( IsDefined( triggerbackobject ) ) + { + triggerbackarray = doorbreach_remove_object_from_list( triggerbackarray, triggerbackobject ); + } + bombbackobject = doorbreach_find_best_object( bombbackarray, originobject ); + if( IsDefined( bombbackobject ) ) + { + bombbackarray = doorbreach_remove_object_from_list( bombbackarray, bombbackobject ); + } + model2object = doorbreach_find_best_object( model2array, originobject ); + if( IsDefined( model2object ) ) + { + model2array = doorbreach_remove_object_from_list( model2array, model2object ); + } + model3object = doorbreach_find_best_object( model3array, originobject ); + if( IsDefined( model3object ) ) + { + model3array = doorbreach_remove_object_from_list( model3array, model3object ); + } + + doortype = "door"; + if( IsDefined( model2object ) || IsDefined( model3object ) ) + { + doortype = "wall"; + } + + // start this guy + originobject thread doorbreach_DoorMainThread( doortype, start_with_doors, start_with_walls, modelobject, nogoobject, triggerfrontobject, bombfrontobject, triggerbackobject, bombbackobject, model2object, model3object ); + } + + // start! + level thread onPlayerConnect(); + //thread doorbreach_DebugPump(); + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_find_best_object( list, node ) + { + if( !IsDefined( node ) ) + { + return undefined; + } + if( !IsDefined( list[0] ) ) + { + return undefined; + } + + best_dist = -1; + best_item = undefined; + + for( x = 0; x < list.size; x++ ) + { + item = list[ x ]; + if( IsDefined( item ) ) + { + dist = distance( node.origin, item.origin ); + if( dist < level._doorbreach_collecting_objects_max_distance ) + { + if( !IsDefined( best_item ) ) + { + best_item = item; + best_dist = dist; + } + else if ( dist < best_dist ) + { + best_item = item; + best_dist = dist; + } + } + } + } + + return best_item; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_remove_object_from_list( list, node ) + { + if( !IsDefined( node ) ) + { + return list; + } + if( !IsDefined( list[0] ) ) + { + return list; + } + + best_dist = -1; + best_item = undefined; + + newlist = []; + found = false; + + for( x = 0; x < list.size; x++ ) + { + item = list[ x ]; + if( IsDefined( item ) ) + { + if( item == node ) + { + // found match! + found = true; + } + else + { + newlist[ newlist.size ] = item; + } + } + } + + if( !found ) + { + return list; // item not in list + } + + return newlist; + } + + + //******************************************************************* + // * + // * + //******************************************************************* + onPlayerConnect() + { + for(;;) + { + level waittill( "connected", player ); + player thread onPlayerSpawned(); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + onPlayerSpawned() + { + self endon( "disconnect" ); + + for(;;) + { + self waittill( "spawned_player" ); + doorbreach_setup_player( self ); + } + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_setup_player( player ) + { + for( i = 0; i < level._doorbreach_origins.size; i++ ) + { + originobject = level._doorbreach_origins[ i ]; + + if( IsDefined( originobject._doorbreach_action ) ) + { + if( originobject._doorbreach_action == "ActionBreach" ) + { + if( IsDefined( originobject._doorbreach_triggerfrontobject ) ) + { + triggerobject = originobject._doorbreach_triggerfrontobject; + triggerobject enablePlayerUse( player ); + } + if( IsDefined( originobject._doorbreach_triggerbackobject ) ) + { + triggerobject = originobject._doorbreach_triggerbackobject; + triggerobject enablePlayerUse( player ); + } + //originobject disablePlayerUse( player ); + } + else if ( originobject._doorbreach_action == "ActionRebuild" ) + { + //originobject enablePlayerUse( player ); + if( IsDefined( originobject._doorbreach_triggerfrontobject ) ) + { + triggerobject = originobject._doorbreach_triggerfrontobject; + triggerobject enablePlayerUse( player ); + } + if( IsDefined( originobject._doorbreach_triggerbackobject ) ) + { + triggerobject = originobject._doorbreach_triggerbackobject; + triggerobject enablePlayerUse( player ); + } + //originobject disablePlayerUse( player ); + } + else + { + if( IsDefined( originobject._doorbreach_triggerfrontobject ) ) + { + triggerobject = originobject._doorbreach_triggerfrontobject; + triggerobject disablePlayerUse( player ); + } + if( IsDefined( originobject._doorbreach_triggerbackobject ) ) + { + triggerobject = originobject._doorbreach_triggerbackobject; + triggerobject disablePlayerUse( player ); + } + //originobject disablePlayerUse( player ); + } + } + } + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_draw_circle( radius ) + { + x = self.origin[0]; + y = self.origin[1]; + z = self.origin[2]; + + radius2 = radius * 0.707; + Print3d( ( x + radius, y, z ), "'", (1,0,0), 1, 1, 10 ); // 0 + Print3d( ( x + radius2, y + radius2, z ), "'", (1,0,0), 1, 1, 10 ); // 45 + Print3d( ( x, y + radius, z ), "'", (1,0,0), 1, 1, 10 ); // 90 + Print3d( ( x - radius2, y + radius2, z ), "'", (1,0,0), 1, 1, 10 ); // 135 + Print3d( ( x - radius, y, z ), "'", (1,0,0), 1, 1, 10 ); // 180 + Print3d( ( x - radius2, y - radius2, z ), "'", (1,0,0), 1, 1, 10 ); // 225 + Print3d( ( x, y - radius, z ), "'", (1,0,0), 1, 1, 10 ); // 270 + Print3d( ( x + radius2, y - radius2, z ), "'", (1,0,0), 1, 1, 10 ); // 315 + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_draw_circles( radius ) + { + for( i = 0; i < level._doorbreach_origins.size; i++ ) + { + originobject = level._doorbreach_origins[ i ]; + + originobject doorbreach_draw_circle( radius ); + //if( IsDefined( originobject._doorbreach_triggerfrontobject ) ) + //{ + // originobject._doorbreach_triggerfrontobject doorbreach_draw_circle( radius * 4.0 ); + //} + //if( IsDefined( originobject._doorbreach_triggerbackobject ) ) + //{ + // originobject._doorbreach_triggerbackobject doorbreach_draw_circle( radius * 4.0 ); + //} + } + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_gameHasStarted() + { + if ( level._teamBased ) + return( level._hasSpawned[ "axis" ] || level._hasSpawned[ "allies" ] ); + else + return( level._maxPlayerCount > 0 ); + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_gameHasEnded() + { + return level._gameEnded; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DebugPump() + { + showing = false; + timestarted = GetTime(); + + while( 1 ) + { + timenow = GetTime(); + if( ( doorbreach_gameHasStarted() ) && ( !doorbreach_gameHasEnded() ) ) + { + if( showing ) + { + doorbreach_draw_circles( 25.0 ); + if( timenow > ( timestarted + ( 1.0 * 1000 ) ) ) + { + showing = false; + timestarted = timenow; + } + } + else + { + if( timenow > ( timestarted + ( 0.5 * 1000 ) ) ) + { + showing = true; + timestarted = timenow; + } + } + } + + wait 0.25; + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_TriggerEnableForAllPlayers() + { + playerlist = GetEntArray( "player", "classname" ); + if( IsDefined( playerlist[0] ) ) + { + foreach ( player in playerlist ) + { + self enablePlayerUse( player ); + } + } + } + + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_TriggerDisableForAllPlayers() + { + playerlist = GetEntArray( "player", "classname" ); + if( IsDefined( playerlist[0] ) ) + { + foreach ( player in playerlist ) + { + self disablePlayerUse( player ); + } + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_ActionDisable() + { + if( IsDefined( self._doorbreach_triggerfrontobject ) ) + { + triggerobject = self._doorbreach_triggerfrontobject; + triggerobject makeUnusable(); + triggerobject doorbreach_TriggerDisableForAllPlayers(); + triggerobject notify( "doorbreachremovetrigger" ); + } + if( IsDefined( self._doorbreach_triggerbackobject ) ) + { + triggerobject = self._doorbreach_triggerbackobject; + triggerobject makeUnusable(); + triggerobject doorbreach_TriggerDisableForAllPlayers(); + triggerobject notify( "doorbreachremovetrigger" ); + } + + self._doorbreach_action = ""; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_ActionBreach() + { + if( IsDefined( self._doorbreach_triggerfrontobject ) ) + { + triggerobject = self._doorbreach_triggerfrontobject; + + triggerobject SetCursorHint( "HINT_ACTIVATE" ); + if( self._doorbreach_doortype == "wall" ) + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_breach ); + } + else + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_breach ); + } + triggerobject makeUsable(); + triggerobject doorbreach_TriggerEnableForAllPlayers(); + if( self._doorbreach_doortype == "wall" ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachtriggerfront", level._doorbreach_time_wall_plant_bomb, level._doorbreach_text_planting_bomb, undefined ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachtriggerfront", level._doorbreach_time_door_plant_bomb, level._doorbreach_text_planting_bomb, undefined ); + } + } + + if( IsDefined( self._doorbreach_triggerbackobject ) ) + { + triggerobject = self._doorbreach_triggerbackobject; + + triggerobject SetCursorHint( "HINT_ACTIVATE" ); + if( self._doorbreach_doortype == "wall" ) + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_breach ); + } + else + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_breach ); + } + triggerobject makeUsable(); + triggerobject doorbreach_TriggerEnableForAllPlayers(); + if( self._doorbreach_doortype == "wall" ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachtriggerback", level._doorbreach_time_wall_plant_bomb, level._doorbreach_text_planting_bomb, undefined ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachtriggerback", level._doorbreach_time_door_plant_bomb, level._doorbreach_text_planting_bomb, undefined ); + } + } + + self._doorbreach_action = "ActionBreach"; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_ActionRebuild( ) + { + if( IsDefined( self._doorbreach_triggerfrontobject ) ) + { + triggerobject = self._doorbreach_triggerfrontobject; + + triggerobject SetCursorHint( "HINT_ACTIVATE" ); + if( self._doorbreach_doortype == "wall" ) + { + if( self._doorbreach_count == 0 ) + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_install ); + } + else + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_rebuild ); + } + } + else + { + if( self._doorbreach_count == 0 ) + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_install ); + } + else + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_rebuild ); + } + } + triggerobject makeUsable(); + triggerobject doorbreach_TriggerEnableForAllPlayers(); + if( self._doorbreach_doortype == "wall" ) + { + if( self._doorbreach_count == 0 ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_wall_build, level._doorbreach_text_wall_installing, self ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_wall_rebuild, level._doorbreach_text_wall_repairing, self ); + } + } + else + { + if( self._doorbreach_count == 0 ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_build, level._doorbreach_text_door_installing, self ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_rebuild, level._doorbreach_text_door_repairing, self ); + } + } + } + + if( IsDefined( self._doorbreach_triggerbackobject ) ) + { + triggerobject = self._doorbreach_triggerbackobject; + + triggerobject SetCursorHint( "HINT_ACTIVATE" ); + if( self._doorbreach_doortype == "wall" ) + { + if( self._doorbreach_count == 0 ) + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_install ); + } + else + { + triggerobject setHintString( level._doorbreach_text_wall_press_and_hold_to_rebuild ); + } + } + else + { + if( self._doorbreach_count == 0 ) + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_install ); + } + else + { + triggerobject setHintString( level._doorbreach_text_door_press_and_hold_to_rebuild ); + } + } + triggerobject makeUsable(); + triggerobject doorbreach_TriggerEnableForAllPlayers(); + if( self._doorbreach_doortype == "wall" ) + { + if( self._doorbreach_count == 0 ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_build, level._doorbreach_text_wall_installing, self ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_rebuild, level._doorbreach_text_wall_repairing, self ); + } + } + else + { + if( self._doorbreach_count == 0 ) + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_build, level._doorbreach_text_door_installing, self ); + } + else + { + triggerobject thread doorbreach_TriggerThread( self, "doorbreachinstall", level._doorbreach_time_door_rebuild, level._doorbreach_text_door_repairing, self ); + } + } + } + + self._doorbreach_action = "ActionRebuild"; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DisplayDoor() + { + if( IsDefined( self._doorbreach_modelobject ) ) + { + self._doorbreach_modelobject doorbreach_Move( 1 ); + self._doorbreach_modelobject show(); + } + if( IsDefined( self._doorbreach_nogoobject ) ) + { + self._doorbreach_nogoobject doorbreach_Move( 1 ); + self._doorbreach_nogoobject show(); + } + if( IsDefined( self._doorbreach_bombfrontobject ) ) + { + self._doorbreach_bombfrontobject doorbreach_Move( 0 ); + self._doorbreach_bombfrontobject show(); + } + if( IsDefined( self._doorbreach_bombbackobject ) ) + { + self._doorbreach_bombbackobject doorbreach_Move( 0 ); + self._doorbreach_bombbackobject show(); + } + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_Move( 0 ); + self._doorbreach_model2object show(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_Move( 0 ); + self._doorbreach_model3object show(); + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DisplayBombFront() + { + if( IsDefined( self._doorbreach_modelobject ) ) + { + self._doorbreach_modelobject doorbreach_Move( 1 ); + self._doorbreach_modelobject show(); + } + if( IsDefined( self._doorbreach_nogoobject ) ) + { + self._doorbreach_nogoobject doorbreach_Move( 1 ); + self._doorbreach_nogoobject show(); + } + if( IsDefined( self._doorbreach_bombfrontobject ) ) + { + self._doorbreach_bombfrontobject doorbreach_Move( 1 ); + self._doorbreach_bombfrontobject show(); + } + if( IsDefined( self._doorbreach_bombbackobject ) ) + { + self._doorbreach_bombbackobject doorbreach_Move( 0 ); + self._doorbreach_bombbackobject show(); + } + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_Move( 0 ); + self._doorbreach_model2object show(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_Move( 0 ); + self._doorbreach_model3object show(); + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DisplayBombBack() + { + if( IsDefined( self._doorbreach_modelobject ) ) + { + self._doorbreach_modelobject doorbreach_Move( 1 ); + self._doorbreach_modelobject show(); + } + if( IsDefined( self._doorbreach_nogoobject ) ) + { + self._doorbreach_nogoobject doorbreach_Move( 1 ); + self._doorbreach_nogoobject show(); + } + if( IsDefined( self._doorbreach_bombfrontobject ) ) + { + self._doorbreach_bombfrontobject doorbreach_Move( 0 ); + self._doorbreach_bombfrontobject show(); + } + if( IsDefined( self._doorbreach_bombbackobject ) ) + { + self._doorbreach_bombbackobject doorbreach_Move( 1 ); + self._doorbreach_bombbackobject show(); + } + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_Move( 0 ); + self._doorbreach_model2object show(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_Move( 0 ); + self._doorbreach_model3object show(); + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DisplayNoDoor() + { + if( IsDefined( self._doorbreach_modelobject ) ) + { + self._doorbreach_modelobject doorbreach_Move( 0 ); + self._doorbreach_modelobject show(); + } + if( IsDefined( self._doorbreach_nogoobject ) ) + { + self._doorbreach_nogoobject doorbreach_Move( 0 ); + self._doorbreach_nogoobject show(); + } + if( IsDefined( self._doorbreach_bombfrontobject ) ) + { + self._doorbreach_bombfrontobject doorbreach_Move( 0 ); + self._doorbreach_bombfrontobject show(); + } + if( IsDefined( self._doorbreach_bombbackobject ) ) + { + self._doorbreach_bombbackobject doorbreach_Move( 0 ); + self._doorbreach_bombbackobject show(); + } + if( self._doorbreach_count == 0 ) + { + // hide it all + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_Move( 0 ); + self._doorbreach_model2object show(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_Move( 0 ); + self._doorbreach_model3object show(); + } + } + else + { + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_Move( 1 ); + self._doorbreach_model2object show(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_Move( 1 ); + self._doorbreach_model3object show(); + } + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_Explosion() + { + playerlist = GetEntArray( "player", "classname" ); + if( IsDefined( playerlist[0] ) ) + { + foreach ( player in playerlist ) + { + dist = distance( self.origin, player.origin ); + if ( dist < level._doorbreach_explosion_flashbang_distance ) + { + player thread maps\mp\_flashgrenades::applyFlash( 2.5, 1 ); + //player maps\mp\_utility::flashBangStart( 5.00 ); + } + } + } + + playfx( level._effect[ "doorbreach_explosion" ], self.origin ); + self PlaySound( level._doorbreach_soundfx_explosion ); + + Earthquake( 0.5, 1, self.origin, level._doorbreach_explosion_shake_radius ); + + //iPrintLnBold( "BOOM!! DOOR BREACHED!!!" ); + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_GotoState( state ) + { + if( self._doorbreach_state == state ) + { + return; // we're already in this state! + } + + // leaving current state + switch( self._doorbreach_state ) + { + case "no_door_ready": // Door doesn't exist, but you can build/rebuild it if you want + self doorbreach_ActionDisable(); + break; + case "new_door_wait": // Door exist and is NOT breachable (yet) + break; + case "new_door_ready": // Door exist and is breachable + self doorbreach_ActionDisable(); + break; + case "bomb_planted": // Door exist and bomb has been planted...waiting for it to explode! + break; + case "no_door_wait": // Door exploded! + break; + default: + break; + } + + // enter this state! + self._doorbreach_state = state; + + // entering new state + switch( self._doorbreach_state ) + { + case "no_door_ready": // Door doesn't exist, but you can build/rebuild it if you want + self doorbreach_DisplayNoDoor(); + self doorbreach_ActionRebuild(); + break; + case "new_door_wait": // Door exist and is NOT breachable (yet) + self doorbreach_DisplayDoor(); + break; + case "new_door_ready": // Door exist and is breachable + self doorbreach_DisplayDoor(); + self doorbreach_ActionBreach(); + break; + case "bomb_planted": // Door exist and bomb has been planted...waiting for it to explode! + if( self._doorbreach_bombside == "back" ) + { + self doorbreach_DisplayBombBack(); + } + else + { + self doorbreach_DisplayBombFront(); + } + break; + case "no_door_wait": // Door exploded! + self doorbreach_DisplayNoDoor(); + break; + default: + self doorbreach_GotoState( "no_door_ready" ); + break; + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_TriggerThread( originnode, notification, usetime, usemessage, doorwayblockingnode ) + { + level endon ( "game_ended" ); + self endon( "doorbreachremovetrigger" ); + + while ( true ) + { + self waittill ( "trigger", player ); + + if( ( originnode._doorbreach_state != "no_door_ready" ) && + ( originnode._doorbreach_state != "new_door_ready" ) ) + { + break; + } + + blocked = false; + if( IsDefined( doorwayblockingnode ) ) + { + blocked = doorwayblockingnode doorbreach_IsDoorwayBlocked( originnode._doorbreach_doortype ); + } + if( blocked ) + { + if( originnode._doorbreach_doortype == "wall" ) + { + player iPrintLnBold( level._doorbreach_text_wall_blocked ); + player PlaySound( level._doorbreach_soundfx_wall_blocked ); + } + else + { + player iPrintLnBold( level._doorbreach_text_door_blocked ); + player PlaySound( level._doorbreach_soundfx_door_blocked ); + } + } + else + { + self doorbreach_TriggerManageHold( originnode, notification, player, usetime, usemessage ); + } + + } + + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_personalUseBar( object, usemessage, originnode ) + { + self endon("disconnect"); + + useBar = createPrimaryProgressBar(); + useBarText = createPrimaryProgressBarText(); + useBarText setText( usemessage ); + + lastRate = -1; + lastHostMigrationState = isDefined( level._hostMigrationTimer ); + while ( isReallyAlive( self ) && object.inUse && !level._gameEnded ) + { + if( ( originnode._doorbreach_state != "no_door_ready" ) && + ( originnode._doorbreach_state != "new_door_ready" ) ) + { + break; + } + if ( lastRate != object.useRate || lastHostMigrationState != isDefined( level._hostMigrationTimer ) ) + { + if( object.curProgress > object.useTime) + object.curProgress = object.useTime; + + progress = object.curProgress / object.useTime; + rate = (1000 / object.useTime) * object.useRate; + if ( isDefined( level._hostMigrationTimer ) ) + rate = 0; + + useBar updateBar( progress, rate ); + + if ( !object.useRate ) + { + useBar hideElem(); + useBarText hideElem(); + } + else + { + useBar showElem(); + useBarText showElem(); + } + } + lastRate = object.useRate; + lastHostMigrationState = isDefined( level._hostMigrationTimer ); + wait ( 0.05 ); + } + + useBar destroyElem(); + useBarText destroyElem(); + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_TriggerManageHold( originnode, notification, player, usetime, usemessage ) + { + level endon ( "game_ended" ); + self endon( "doorbreachremovetrigger" ); + self endon( "disabled" ); + + if ( !isReallyAlive( player ) ) + { + return; + } + + if ( !player isOnGround() ) + { + return; + } + + player notify ( "use_hold" ); + + player playerLinkTo( self ); + player PlayerLinkedOffsetEnable(); + // player clientClaimTrigger( self ); + // player.claimTrigger = self; + + self.curProgress = 0; + self.inUse = true; + self.useRate = 1; + self.useTime = usetime; + + player thread doorbreach_personalUseBar( self, usemessage, originnode ); + + holdcompleted = false; + while ( true ) + { + if( !isReallyAlive( player ) ) + { + break; + } + + // if( !player isTouching( self ) ) + // { + // break; + // } + if( !player useButtonPressed() ) + { + break; + } + + if( ( originnode._doorbreach_state != "no_door_ready" ) && + ( originnode._doorbreach_state != "new_door_ready" ) ) + { + break; + } + + self.curProgress += (50.0); + if ( self.curProgress >= self.useTime ) + { + // done! + holdcompleted = true; + break; + } + + wait 0.05; + maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone(); + } + + self.inUse = false; + // player clientReleaseTrigger( self ); + // player.claimTrigger = undefined; + player unlink(); + + player notify( "done_using" ); + + self notify ( "finished_use" ); + + if ( !holdcompleted ) + { + return; + } + + // done! + originnode._doorbreach_player = player; + + originnode notify( notification ); + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_SetupCoords() + { + self._doorbreach_origin_normal_position = self.origin; + if( IsDefined( level._doorbreach_nogo_graveyard_object ) ) + { + self._doorbreach_origin_graveyard_position = level._doorbreach_nogo_graveyard_object.origin; + } + else + { + self._doorbreach_origin_graveyard_position = self._doorbreach_origin_normal_position + ( level._doorbreach_move_delta_x, level._doorbreach_move_delta_y, level._doorbreach_move_delta_z ); + } + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_Move( move_position ) + { + if( move_position == 0 ) // 0=graveyard position , 1=normal position + { + if( !IsDefined( self._doorbreach_origin_graveyard_position ) ) + { + return; + } + dest_origin = self._doorbreach_origin_graveyard_position; + } + else + { + if( !IsDefined( self._doorbreach_origin_normal_position ) ) + { + return; + } + dest_origin = self._doorbreach_origin_normal_position; + } + + move_distance = distance( self.origin, dest_origin ); + if ( move_distance > 0.0 ) + { + self moveto( dest_origin, 0.05, 0.0, 0.0 ); + } + } + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_IsDoorwayBlocked( doortype ) + { + blocked = false; + playerlist = GetEntArray( "player", "classname" ); + if( IsDefined( playerlist[0] ) ) + { + if( doortype == "wall" ) + { + distvalue = level._doorbreach_blocked_wall_distance; + } + else + { + distvalue = level._doorbreach_blocked_door_distance; + } + + foreach ( tempplayer in playerlist ) + { + dist = distance( self.origin, tempplayer.origin ); + if ( dist < distvalue ) + { + blocked = true; + } + } + } + return blocked; + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_CountdownMessage( counter ) + { + if( IsDefined( self._doorbreach_player ) ) + { + numsecs = int( counter ); + if( numsecs == 5 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_countdown_5 ); + } + else if( numsecs == 4 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_countdown_4 ); + } + else if( numsecs == 3 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_countdown_3 ); + } + else if( numsecs == 2 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_countdown_2 ); + } + else if( numsecs == 1 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_countdown_1 ); + } + } + } + + + + //******************************************************************* + // * + // * + //******************************************************************* + doorbreach_DoorMainThread( doortype, start_with_doors, start_with_walls, modelobject, nogoobject, triggerfrontobject, bombfrontobject, triggerbackobject, bombbackobject, model2object, model3object ) + { + // init + self._doorbreach_doortype = doortype; + self._doorbreach_modelobject = modelobject; + self._doorbreach_nogoobject = nogoobject; + self._doorbreach_triggerfrontobject = triggerfrontobject; + self._doorbreach_bombfrontobject = bombfrontobject; + self._doorbreach_triggerbackobject = triggerbackobject; + self._doorbreach_bombbackobject = bombbackobject; + self._doorbreach_model2object = model2object; + self._doorbreach_model3object = model3object; + + // setup coords + if( IsDefined( self._doorbreach_modelobject ) ) + { + self._doorbreach_modelobject doorbreach_SetupCoords(); + } + if( IsDefined( self._doorbreach_nogoobject ) ) + { + self._doorbreach_nogoobject doorbreach_SetupCoords(); + } + if( IsDefined( self._doorbreach_bombfrontobject ) ) + { + self._doorbreach_bombfrontobject doorbreach_SetupCoords(); + } + if( IsDefined( self._doorbreach_bombbackobject ) ) + { + self._doorbreach_bombbackobject doorbreach_SetupCoords(); + } + if( IsDefined( self._doorbreach_model2object ) ) + { + self._doorbreach_model2object doorbreach_SetupCoords(); + } + if( IsDefined( self._doorbreach_model3object ) ) + { + self._doorbreach_model3object doorbreach_SetupCoords(); + } + + self._doorbreach_action = ""; + self._doorbreach_bombside = "back"; + self._doorbreach_count = 0; + + self._doorbreach_state = ""; // none right now + + // make sure our "origin", "triggerfront" and "triggerback" objects are in SHOW() mode, so that triggers will work. + self show(); + if( IsDefined( self._doorbreach_triggerfrontobject ) ) + { + self._doorbreach_triggerfrontobject Show(); + } + if( IsDefined( self._doorbreach_triggerbackobject ) ) + { + self._doorbreach_triggerbackobject Show(); + } + + if( self._doorbreach_doortype == "wall" ) + { + if( !IsDefined( start_with_walls ) ) + { + start_with_walls = -1; // default + } + if( start_with_walls == -1 ) // default + { + start_with_walls = 1; // start with walls + } + if( start_with_walls == 0 ) + { + // start with no walls + // TagEM : For some reason, starting out in "no_door_ready" won't setup the triggers! + // So for now I'll use "no_door_wait", which appears to work just fine. + self doorbreach_GotoState( "no_door_wait" ); //"no_door_ready" ); + } + else + { + // start with walls in place + self doorbreach_GotoState( "new_door_ready" ); + } + } + else + { + if( !IsDefined( start_with_doors ) ) + { + start_with_doors = -1; // default + } + if( start_with_doors == -1 ) // default + { + start_with_doors = 0; // start with no doors + } + if( start_with_doors == 0 ) + { + // start with no doors + // TagEM : For some reason, starting out in "no_door_ready" won't setup the triggers! + // So for now I'll use "no_door_wait", which appears to work just fine. + self doorbreach_GotoState( "no_door_wait" ); //"no_door_ready" ); + } + else + { + // start with doors in place + self doorbreach_GotoState( "new_door_ready" ); + } + } + + + while( 1 ) + { + switch( self._doorbreach_state ) + { + case "no_door_ready": // Door doesn't exist, but you can build/rebuild it if you want + //wait for a player to activate the trigger + //self waittill ( "doorbreachinstall", player ); + msg = self waittill_any_return( "doorbreachinstall" ); + + self doorbreach_GotoState( "new_door_wait" ); // Door exist and is NOT breachable (yet) + if( self._doorbreach_doortype == "wall" ) + { + self PlaySound( level._doorbreach_soundfx_wall_created ); + } + else + { + self PlaySound( level._doorbreach_soundfx_door_created ); + } + + if( IsDefined( self._doorbreach_player ) ) + { + if( self._doorbreach_doortype == "wall" ) + { + if( self._doorbreach_count == 0 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_wall_installed ); + } + else + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_wall_repaired ); + } + } + else + { + if( self._doorbreach_count == 0 ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_door_installed ); + } + else + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_door_repaired ); + } + } + } + break; + + case "new_door_wait": // Door exist and is NOT breachable (yet) + wait level._doorbreach_wait_time_before_breachable; + self doorbreach_GotoState( "new_door_ready" ); // Door exist and is breachable + break; + + case "new_door_ready": // Door exist and is breachable + + //wait for a player to activate the trigger + //self waittill ( "trigger", player ); + //self._doorbreach_bombside = "back"; + + msg = self waittill_any_return( "doorbreachtriggerfront", "doorbreachtriggerback" ); + if( msg == "doorbreachtriggerback" ) + { + self._doorbreach_bombside = "back"; + } + else + { + self._doorbreach_bombside = "front"; + } + + self doorbreach_GotoState( "bomb_planted" ); // Door exist and bomb has been planted...waiting for it to explode! + self PlaySound( level._doorbreach_soundfx_bomb_placed ); + break; + + case "bomb_planted": // Door exist and bomb has been planted...waiting for it to explode! + + //wait level._doorbreach_wait_time_bomb_fuse; + counter = level._doorbreach_wait_time_bomb_fuse; + + while( counter > 0.0 ) + { + self doorbreach_CountdownMessage( counter ); + + self PlaySound( level._doorbreach_soundfx_bomb_beep ); + wait ( 1.0 ); + counter -= 1.0; + } + + self._doorbreach_count++; // increment this (so future messages will say "rebuild door", etc) + + self doorbreach_GotoState( "no_door_wait" ); // Door exploded! + + if( IsDefined( self._doorbreach_player ) ) + { + if( self._doorbreach_doortype == "wall" ) + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_wall_breached ); + } + else + { + self._doorbreach_player iPrintLnBold( level._doorbreach_text_door_breached ); + } + } + + self doorbreach_Explosion(); // Door exploded! + + + break; + + case "no_door_wait": // Door exploded! + wait level._doorbreach_wait_time_before_can_rebuild; + self doorbreach_GotoState( "no_door_ready" ); // Door doesn't exist, but you can build/rebuild it if you want + break; + + default: + self doorbreach_GotoState( "no_door_ready" ); // Door doesn't exist, but you can build/rebuild it if you want + break; + } + } + } \ No newline at end of file diff --git a/maps/mp/_doorswitch.gsc b/maps/mp/_doorswitch.gsc new file mode 100644 index 0000000..4dc1e44 --- /dev/null +++ b/maps/mp/_doorswitch.gsc @@ -0,0 +1,490 @@ + //**************************************************************************** + // ** + // Confidential - (C) Activision Publishing, Inc. 2010 ** + // ** + //**************************************************************************** + // ** + // Module: Phase 1 Check-In: The script is able to control multiple ** + // sets of door-switch pairs. It will work with the following ** + // required setups in Radiant: ** + // 2 models: ** + // script_model: "targetname" "door_switch" ** + // script_model: "targetname" "door_for_door_switch" ** + // 1 clips: ** + // script_brushmodel: "targetname" "clip_on_door" ** + // 5 triggers: ** + // trigger_use: "targetname" "door_trigger" ** + // trigger_multiple: "targetname" "trigger_on_door" ** + // trigger_multiple: "targetname" "trigger_under_door" ** + // trigger_multiple: "targetname" "trigger_on_floor" ** + // trigger_multiple: "targetname" "trigger_on_top" ** + // ** + // Created: June 9th, 2011 - James Chen ** + // ** + //***************************************************************************/ + + TARGETNAME_DOOR_SWITCH_MODEL = "door_switch"; //model for the door switch + TARGETNAME_DOOR_SWITCH_TRIGGER = "door_trigger"; //trigger_use placed with the door switch + TARGETNAME_DOOR_CLIP = "clip_on_door"; //clip around the door + TARGETNAME_DOOR = "door_for_door_switch"; //model for the door + TARGETNAME_TRIGGER_ON_DOOR = "trigger_on_door"; //trigger_multiple placed at the bottom of the door + TARGETNAME_TRIGGER_UNDER_DOOR = "trigger_under_door"; //trigger_multiple placed under the door to detect players passing by + TARGETNAME_TRIGGER_ON_FLOOR = "trigger_on_floor"; //trigger_multiple to represent the lowest point the door can go + TARGETNAME_TRIGGER_ON_TOP = "trigger_on_top"; //trigger_multiple to represent the highest point the door can go + TIME_OPEN_DOOR = 15; //Based on the UGV design doc + NOTIFY_MESSAGE_DOOR_OPENING = "door_opening"; //the notify message when the door is opening + NOTIFY_MESSAGE_DOOR_CLOSING = "door_closing"; //the notify message when the door is closing + NOTIFY_MESSAGE_DOOR_AT_TOP = "door_at_top"; //the notify message when the door is at the top + NOTIFY_MESSAGE_DOOR_AT_BOTTOM = "door_at_bottom"; //the notify message when the door is at the bottom + NOTIFY_MESSAGE_DISABLE_DOOR_SWITCH = "disable_door_switch"; //the notify message to disable the door switch + HINT_STRING_FOR_TRIGGER = &"MP_HINT_STRING_DOOR_SWITCH"; //the default hint string that will appear when players are close to the trigger + DOOR_STATE_COMPLETELY_CLOSED = "completely_closed"; //the flag message when the door is completely closed + DOOR_STATE_COMPLETELY_OPENED = "completely_opened"; //the flag message when the door is completely opened + DOOR_STATE_OPENING = "door_opening"; //the flag message when the door is opening + DOOR_STATE_CLOSING = "door_closing"; //the flag message when the door is closeing + + //tagJC: For demonstration, run mp_nx_switch + + //******************************************************************* + // * + // * + //******************************************************************* + main() + { + //tagJC: These two lines are to test the desired functionality for the UGV escort mode. Disable the following lines will + // result in the default behavior for the door switch, unless the new controlling logic and (or) the is defined + // in the game mode. + //level._canPlayerUseDoor = ::gameModeLogic; + //level._shouldTheObjectiveEnd = ::objectiveTerminationLogic; + //level._HintStringForDoorSwitch = "Testing string - Press ^3[{+activate}]^7 to use the door switch"; + + //tagJC: Getting all the entities into corresponding arrays + level._DoorSwitch = getentArray_and_assert( TARGETNAME_DOOR_SWITCH_MODEL ); + level._DoorSwitchTrigger = getentArray_and_assert( TARGETNAME_DOOR_SWITCH_TRIGGER ); + level._ClipOnDoor = getentArray_and_assert( TARGETNAME_DOOR_CLIP ); + level._DoorForDoorSwitch = getentArray_and_assert( TARGETNAME_DOOR ); + level._TriggerOnDoor = getentArray_and_assert( TARGETNAME_TRIGGER_ON_DOOR ); + level._TriggerUnderDoor = getentArray_and_assert( TARGETNAME_TRIGGER_UNDER_DOOR ); + level._TriggerOnFloor = getentArray_and_assert( TARGETNAME_TRIGGER_ON_FLOOR ); + level._TriggerOnTop = getentArray_and_assert( TARGETNAME_TRIGGER_ON_TOP ); + + //tagJC: Checking for the correct numbers of models, clips and triggers in order to make sure that the script will function + // correctly. + checking_setup(); + + //tagJC: Linking the door model and the trigger at the bottom of the door to the clip + linking( level._ClipOnDoor , level._DoorForDoorSwitch ); + linking( level._ClipOnDoor , level._TriggerOnDoor ); + + //tagJC: Based on proximity, pair up the trigger on the switch, the clip on the door and the 4 triggers around the door + pairing( level._DoorSwitchTrigger, level._ClipOnDoor, level._TriggerOnDoor, level._TriggerUnderDoor, level._TriggerOnFloor, level._TriggerOnTop ); + + println ( "In the main of DoorSwitch" ); + ////tagJC: Activate all the switch triggers around the level + for ( i = 0; i < level._DoorSwitchTrigger.size; i++) + { + level._DoorSwitchTrigger[i] thread ActivateDoorTrigger(); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: self is the trigger on top of the switch + ActivateDoorTrigger() + { + //tagJC: If the door reaches the highest point it can reach, disable the switch. Move the following logic to game logic side + self endon ( NOTIFY_MESSAGE_DISABLE_DOOR_SWITCH ); + + self usetriggerrequirelookat(); + + //tagJC: Use level defined hint string (possibly defined for the game mode) if it is defined + if ( isDefined( level._HintStringForDoorSwitch )) + { + hint_string = level._HintStringForDoorSwitch; + } + else + { + //tagJC: Else, use the default hint string + hint_string = HINT_STRING_FOR_TRIGGER; + } + + self SetHintString ( hint_string ); + + //tagJC: The door is at the initial completely closed state + self.state = DOOR_STATE_COMPLETELY_CLOSED; + self.isOpening = 0; + + //tagJC: Based on the distance that the door is able to move, calculate its speed + door_opening = distance (self.pairedTriggerTop.origin, self.pairedTriggerFloor.origin ); + door_speed = door_opening / TIME_OPEN_DOOR; + + while (1) + { + self waittill( "trigger", player ); + + if ( isDefined( level._canPlayerUseDoor )) + { + result = [[level._canPlayerUseDoor]]( player, self, self.state ); + } + else + { + result = defaultCanPlayerUseDoor( player, self, self.state ); + } + + if( result && isDefined( level._doorActivationSound )) + { + self [[level._doorActivationSound]]( player ); + } + + //println( "result is " + result); + //tagJC: If the door is currently not opening, open the door + if ( result && self.isOpening == 0) + { + //tagJC: Play the opening sound on the door if the desired sound is defined in the level + if ( isDefined ( level._doorOpeningSound )) + { + self [[level._doorOpeningSound]](); + + } + self.state = DOOR_STATE_OPENING; + self.isOpening = 1; + self notify( NOTIFY_MESSAGE_DOOR_OPENING ); + level notify( NOTIFY_MESSAGE_DOOR_OPENING ); + //tagJC: Stop the script to kill players who are stuck since the door is opening + self notify( "stop_killing_player" ); + //tagJC: Test whether the door is at the highest point that it can reach + if ( isDefined( level._shouldTheObjectiveEnd )) + { + self thread [[level._shouldTheObjectiveEnd]](); + } + else + { + self thread IsDoorAtTop(); + } + //tagJC: Move the door upward + distance_to_open = distance (self.pairedTriggerTop.origin, self.pairedTriggerOn.origin ); + time_to_open = distance_to_open / door_speed; + self.pairedClip notify( "movedone" ); + self.pairedClip MoveZ( distance_to_open, time_to_open, time_to_open * 0.5, time_to_open * 0.4); + } + else if ( result && self.isOpening == 1) + { + //tagJC: Play the closing sound on the door if the desired sound is defined in the level + if ( isDefined ( level._doorClosingSound )) + { + self [[level._doorClosingSound]](); + + } + self.state = DOOR_STATE_CLOSING; + self.isOpening = 0; + self notify( NOTIFY_MESSAGE_DOOR_CLOSING ); + //tagJC: Test whether the door is at the lowest point that it can reach + self thread IsDoorAtBottom(); + //tagJC: Kill any players who are stuck underneath the door + self thread KillPlayersUnder(); + //tagJC: Move the door downward + distance_to_close = distance( self.pairedTriggerFloor.origin, self.pairedTriggerOn.origin ); + time_to_close = distance_to_close / door_speed; + self.pairedClip notify( "movedone" ); + self.pairedClip MoveZ( distance_to_close * -1, time_to_close, time_to_close * 0.5, time_to_close * 0.4); + } + wait ( 1 ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: The default door behavior is that everyone (regardless of the team) can use the door + defaultCanPlayerUseDoor( player, trigger, door_state ) + { + return true; + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: self is the door switch + IsDoorAtBottom() + { + self endon ( NOTIFY_MESSAGE_DOOR_OPENING ); + self endon ( NOTIFY_MESSAGE_DISABLE_DOOR_SWITCH ); + + while ( 1 ) + { + if ( self.pairedTriggerOn.origin[2] == self.pairedTriggerFloor.origin[2] ) + { + if ( isDefined( level._doorCompletelyCloseSound ) && ( self.state != DOOR_STATE_COMPLETELY_CLOSED )) + { + self [[level._doorCompletelyCloseSound]](); + } + self notify ( NOTIFY_MESSAGE_DOOR_AT_BOTTOM ); + self.state = DOOR_STATE_COMPLETELY_CLOSED; + } + wait 0.5; + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: self is the door switch + IsDoorAtTop() + { + self endon ( NOTIFY_MESSAGE_DOOR_CLOSING ); + self endon ( NOTIFY_MESSAGE_DISABLE_DOOR_SWITCH ); + + while ( 1 ) + { + if ( self.pairedTriggerOn.origin[2] == self.pairedTriggerTop.origin[2] ) + { + if ( isDefined( level._doorCompletelyOpenSound ) && ( self.state != DOOR_STATE_COMPLETELY_OPENED )) + { + self [[level._doorCompletelyOpenSound]](); + } + //tagJC: Once the door reaches the top, make the proper notify and change the state + self notify ( NOTIFY_MESSAGE_DOOR_AT_TOP ); + self.state = DOOR_STATE_COMPLETELY_OPENED; + } + wait 0.5; + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: self is the trigger on top of the door switch + KillPlayersUnder() + { + self endon ( "stop_killing_player" ); + + while ( 1 ) + { + self.pairedTriggerUnder waittill( "trigger", player); + + if (( player IsTouching( self.pairedTriggerOn ))) // && ( player IsTouching( Trigger2 ))) + { + player thread [[level._callbackPlayerDamage]]( + player, // eInflictor The entity that causes the damage.(e.g. a turret) + player, // eAttacker The entity that is attacking. + 500, // iDamage Integer specifying the amount of damage done + 0, // iDFlags Integer specifying flags that are to be applied to the damage + "MOD_SUICIDE", // sMeansOfDeath Integer specifying the method of death MOD_RIFLE_BULLET + player.primaryweapon, // sWeapon The weapon number of the weapon used to inflict the damage + player.origin, // vPoint The point the damage is from? + (0, 0, 0), // vDir The direction of the damage + "none", // sHitLoc The location of the hit + 0 // psOffsetTime The time offset for the damage + ); + } + wait .05; + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Linking entities in object_list_2 to that in object_list_1 based on proximity + linking( object_list_1 , object_list_2 ) + { + for ( i = 0; i < object_list_1.size; i++ ) + { + //tagJC: Use an arbitrary distance as the base for comparision + paired_object2 = find_closest( object_list_1[i], object_list_2 ); + + //tagJC: Link the paired objects to that in object_list_1 + paired_object2 LinkTo( object_list_1[i] ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: This function pairs up the clips with each other as well as the corresponding triggers + pairing( trigger_list, clip_list, trigger_on_list, trigger_under_list, trigger_floor_list, trigger_top_list ) + { + for ( i = 0; i < trigger_list.size; i++ ) + { + //tagJC: Determine the door clip, and the four triggers around the door that are the closest to the current + // switch trigger under examination + paired_clip = find_closest( trigger_list[i], clip_list ); + paired_trigger_on = find_closest( trigger_list[i], trigger_on_list ); + paired_trigger_under = find_closest( trigger_list[i], trigger_under_list ); + paired_trigger_floor = find_closest( trigger_list[i], trigger_floor_list ); + paired_trigger_top = find_closest( trigger_list[i], trigger_top_list ); + + //tagJC: Putting those closest entities as the member data for the switch trigger + trigger_list[i].pairedClip = paired_clip; + trigger_list[i].pairedTriggerOn = paired_trigger_on; + trigger_list[i].pairedTriggerUnder = paired_trigger_under; + trigger_list[i].pairedTriggerFloor = paired_trigger_floor; + trigger_list[i].pairedTriggerTop = paired_trigger_top; + + //tagJC: Useful debugging message + //IPrintLnBold( "clip at " + paired_clip.origin + " is paired with switch trigger at " + trigger_list[i].origin); + //IPrintLnBold( "Trigger_on at " + paired_trigger_on.origin + " is paired with switch trigger at " + trigger_list[i].origin); + //IPrintLnBold( "Trigger_under at " + paired_trigger_under.origin + " is paired with switch trigger at " + trigger_list[i].origin); + //IPrintLnBold( "Trigger_floor at " + paired_trigger_floor.origin + " is paired with switch trigger at " + trigger_list[i].origin); + //IPrintLnBold( "Trigger_top at " + paired_trigger_top.origin + " is paired with switch trigger at " + trigger_list[i].origin); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + find_closest( entity, entity_list ) + { + //tagJC: Use an arbitrary distance as the base for comparision + closest_distance = distance( entity.origin , entity_list[0].origin ); + closest_entity = entity_list[0]; + for ( i = 1; i < entity_list.size; i++ ) + { + //tagJC: If another entity on the list results in a shorter distance, update the results accordingly + if ( distance( entity.origin , entity_list[i].origin ) < closest_distance ) + { + closest_distance = distance( entity.origin , entity_list[i].origin ); + closest_entity = entity_list[i]; + } + } + return closest_entity; + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Check for matching numbers of entities for door models, clips and triggers + checking_setup () + { + set_count = level._DoorSwitch.size; + if ( level._DoorSwitchTrigger.size != set_count ) + { + AssertEX( false , "The number of switch trigger needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._DoorSwitchTrigger.size + " switch trigger in the level." ); + } + if ( level._ClipOnDoor.size != set_count ) + { + AssertEX( false , "The number of door clip needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._ClipOnDoor.size + " door clips in the level." ); + } + if ( level._DoorForDoorSwitch.size != set_count ) + { + AssertEX( false , "The number of door models needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._DoorForDoorSwitch.size + " door models in the level." ); + } + if ( level._TriggerOnDoor.size != set_count ) + { + AssertEX( false , "The number of triggers on door needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._TriggerOnDoor.size + " triggers on door." ); + } + if ( level._TriggerUnderDoor.size != set_count ) + { + AssertEX( false , "The number of triggers under door needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._TriggerUnderDoor.size + " triggers under door." ); + } + if ( level._TriggerOnFloor.size != set_count ) + { + AssertEX( false , "The number of triggers on floor needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._TriggerOnFloor.size + " triggers on floor." ); + } + if ( level._TriggerOnTop.size != set_count ) + { + AssertEX( false , "The number of triggers on top of the door needs to equal to the number of switch. There are " + set_count + " switch in the level. However, there are " + level._TriggerOnTop.size + " triggers on top of the door." ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Useful helper function to get the requested entity and check for any errors + getentArray_and_assert( ent_name ) + { + object = getEntArray( ent_name, "targetname" ); + AssertEX( object.size > 0 , "There is no entity for " + ent_name ); + return object; + } + + +maps/mp/_compass.gsc setupMiniMap(material) + { + // use 0 for no required map aspect ratio. + requiredMapAspectRatio = level._requiredMapAspectRatio; + + corners = getentarray("minimap_corner", "targetname"); + if (corners.size != 2) + { + println("^1Error: There are not exactly two \"minimap_corner\" entities in the map. Could not set up minimap."); + return; + } + + corner0 = (corners[0].origin[0], corners[0].origin[1], 0); + corner1 = (corners[1].origin[0], corners[1].origin[1], 0); + + cornerdiff = corner1 - corner0; + + north = (cos(getnorthyaw()), sin(getnorthyaw()), 0); + west = (0 - north[1], north[0], 0); + + // we need the northwest and southeast corners. all we know is that corner0 is opposite of corner1. + if (vectordot(cornerdiff, west) > 0) { + // corner1 is further west than corner0 + if (vectordot(cornerdiff, north) > 0) { + // corner1 is northwest, corner0 is southeast + northwest = corner1; + southeast = corner0; + } + else { + // corner1 is southwest, corner0 is northeast + side = vecscale(north, vectordot(cornerdiff, north)); + northwest = corner1 - side; + southeast = corner0 + side; + } + } + else { + // corner1 is further east than corner0 + if (vectordot(cornerdiff, north) > 0) { + // corner1 is northeast, corner0 is southwest + side = vecscale(north, vectordot(cornerdiff, north)); + northwest = corner0 + side; + southeast = corner1 - side; + } + else { + // corner1 is southeast, corner0 is northwest + northwest = corner0; + southeast = corner1; + } + } + + // expand map area to fit required aspect ratio + if ( requiredMapAspectRatio > 0 ) + { + northportion = vectordot(northwest - southeast, north); + westportion = vectordot(northwest - southeast, west); + mapAspectRatio = westportion / northportion; + if ( mapAspectRatio < requiredMapAspectRatio ) + { + incr = requiredMapAspectRatio / mapAspectRatio; + addvec = vecscale( west, westportion * (incr - 1) * 0.5 ); + } + else + { + incr = mapAspectRatio / requiredMapAspectRatio; + addvec = vecscale( north, northportion * (incr - 1) * 0.5 ); + } + northwest += addvec; + southeast -= addvec; + } + + level._mapSize = vectordot(northwest - southeast, north); + + setMiniMap(material, northwest[0], northwest[1], southeast[0], southeast[1]); + } + + vecscale(vec, scalar) + { + return (vec[0]*scalar, vec[1]*scalar, vec[2]*scalar); + } \ No newline at end of file diff --git a/maps/mp/_entityheadicons.gsc b/maps/mp/_entityheadicons.gsc new file mode 100644 index 0000000..aaedce1 --- /dev/null +++ b/maps/mp/_entityheadicons.gsc @@ -0,0 +1,342 @@ +#include maps\mp\_utility; +#include common_scripts\utility; +#include maps\mp\gametypes\_hud_util; + +init() +{ + if (isdefined(level._initedEntityHeadIcons)) + return; + level._initedEntityHeadIcons = true; + + game["entity_headicon_allies"] = maps\mp\gametypes\_teams::getTeamHeadIcon( "allies" ); + game["entity_headicon_axis"] = maps\mp\gametypes\_teams::getTeamHeadIcon( "axis" ); + + precacheShader( game["entity_headicon_allies"] ); + precacheShader( game["entity_headicon_axis"] ); + + if( level._multiTeamBased ) + { + for( i = 0; i < level._teamNameList.size; i++ ) + { + str_team_headicon = "entity_headicon_" + level._teamNameList[i]; + game[ str_team_headicon ] = maps\mp\gametypes\_teams::MTDM_getTeamHeadIcon( level._teamNameList[i] ); + precacheShader( game[ str_team_headicon ] ); + } + } + + if (!level._teamBased) + return; +} + +// This can show to single players or to teams. Showing to a single player destroys instances of +// the icon that are shown to their team. Showing to a team destroys instances of the icon that +// are shown to players on that team +setHeadIcon( showTo, icon, offset, width, height, archived, delay, constantSize, pinToScreenEdge, fadeOutPinnedIcon, is3D ) +{ + if ( !isDefined( self.entityHeadIcons ) ) + self.entityHeadIcons = []; + + if( !IsDefined( archived ) ) + archived = true; + + if( !IsDefined( delay ) ) + delay = 0.05; + + if( !IsDefined( constantSize ) ) + constantSize = true; + + if( !IsDefined( pinToScreenEdge ) ) + pinToScreenEdge = true; + + if( !IsDefined( fadeOutPinnedIcon ) ) + fadeOutPinnedIcon = false; + + if( !IsDefined( is3D ) ) + is3D = true; + + if ( !isPlayer( showTo ) && showTo == "none" ) + { + foreach ( key, headIcon in self.entityHeadIcons ) + { + // TODO: remove and fix properly after ship + if ( isDefined( headIcon ) ) + headIcon destroy(); + + self.entityHeadIcons[ key ] = undefined; + } + + return; + } + + if ( isPlayer( showTo ) ) + { + if ( isDefined( self.entityHeadIcons[ showTo.guid ] ) ) + { + self.entityHeadIcons[ showTo.guid ] destroy(); + self.entityHeadIcons[ showTo.guid ] = undefined; + } + + if ( icon == "" ) + return; + + // remove from team or we'd have two icons + if ( isDefined( self.entityHeadIcons[ showTo.team ] ) ) + { + self.entityHeadIcons[ showTo.team ] destroy(); + self.entityHeadIcons[ showTo.team ] = undefined; + } + + headIcon = newClientHudElem( showTo ); + self.entityHeadIcons[ showTo.guid ] = headIcon; + } + else + { + if( !level._multiteambased ) + { + assert( showTo == "axis" || showTo == "allies" ); + assert( level._teamBased ); + } + + if ( isDefined( self.entityHeadIcons[ showTo ] ) ) + { + self.entityHeadIcons[ showTo ] destroy(); + self.entityHeadIcons[ showTo ] = undefined; + } + + if ( icon == "" ) + return; + + foreach ( key, hudIcon in self.entityHeadIcons ) + { + if ( key == "axis" || key == "allies" ) + continue; + + if( level._multiTeamBased ) + { + if( isSubStr( key, "team_" )) + { + continue; + } + } + + player = getPlayerForGuid( key ); + if ( isDefined( player ) && player.team == showTo ) + { + if ( isDefined( self.entityHeadIcons[ key ] ) ) + { + self.entityHeadIcons[ key ] destroy(); + self.entityHeadIcons[ key ] = undefined; + } + } + } + + headIcon = newTeamHudElem( showTo ); + self.entityHeadIcons[ showTo ] = headIcon; + } + + if ( !isDefined( width ) || !isDefined( height ) ) + { + width = 10; + height = 10; + } + + headIcon.archived = archived; + headIcon.x = self.origin[0] + offset[0]; + headIcon.y = self.origin[1] + offset[1]; + headIcon.z = self.origin[2] + offset[2]; + headIcon.alpha = 0.85; + headIcon setShader( icon, width, height ); + headIcon setWaypoint( constantSize, pinToScreenEdge, fadeOutPinnedIcon, is3D ); + + headIcon thread keepPositioned( self, offset, delay ); + self thread destroyIconsOnDeath(); + if ( isPlayer( showTo ) ) + headIcon thread destroyOnOwnerDisconnect( showTo ); + if ( isPlayer( self ) ) + headIcon thread destroyOnOwnerDisconnect( self ); + + return headIcon; +} + + +destroyOnOwnerDisconnect( owner ) +{ + self endon ( "death" ); + + owner waittill ( "disconnect" ); + + self destroy(); +} + + +destroyIconsOnDeath() +{ + self notify ( "destroyIconsOnDeath" ); + self endon ( "destroyIconsOnDeath" ); + + self waittill ( "death" ); + + foreach ( key, headIcon in self.entityHeadIcons ) + { + // TODO: remove and fix properly after ship + if( !isDefined(headIcon) ) //needed for FFA host migration (when host has active head icons) + continue; + + headIcon destroy(); + } +} + + +keepPositioned( owner, offset, delay ) +{ + self endon ( "death" ); + owner endon ( "death" ); + owner endon ( "disconnect" ); + + pos = owner.origin; + + for ( ;; ) + { + if( !IsDefined( owner ) ) + return; + if ( pos != owner.origin ) + { + pos = owner.origin; + + self.x = pos[0] + offset[0]; + self.y = pos[1] + offset[1]; + self.z = pos[2] + offset[2]; + } + self.alpha = 1; + self FadeOverTime( delay ); + self.alpha = 0; + + wait delay; + } +} + + + +setTeamHeadIcon( team, offset ) // "allies", "axis", "all", "none" +{ + if ( !level._teamBased ) + return; + + if ( !isDefined( self.entityHeadIconTeam ) ) + { + self.entityHeadIconTeam = "none"; + self.entityHeadIcon = undefined; + } + + shader = game["entity_headicon_" + team]; + + self.entityHeadIconTeam = team; + + if ( isDefined( offset ) ) + self.entityHeadIconOffset = offset; + else + self.entityHeadIconOffset = (0,0,0); + + self notify( "kill_entity_headicon_thread" ); + + if ( team == "none" ) + { + if ( isDefined( self.entityHeadIcon ) ) + self.entityHeadIcon destroy(); + return; + } + + headIcon = newTeamHudElem( team ); + headIcon.archived = true; + headIcon.x = self.origin[0] + self.entityHeadIconOffset[0]; + headIcon.y = self.origin[1] + self.entityHeadIconOffset[1]; + headIcon.z = self.origin[2] + self.entityHeadIconOffset[2]; + headIcon.alpha = .8; + headIcon setShader( shader, 10, 10 ); + headIcon setWaypoint( false, false, false, true ); + self.entityHeadIcon = headIcon; + + self thread keepIconPositioned(); + self thread destroyHeadIconsOnDeath(); +} + +setPlayerHeadIcon( player, offset ) // "allies", "axis", "all", "none" +{ + if ( level._teamBased ) + return; + + if ( !isDefined( self.entityHeadIconTeam ) ) + { + self.entityHeadIconTeam = "none"; + self.entityHeadIcon = undefined; + } + + self notify( "kill_entity_headicon_thread" ); + + if ( !isDefined( player ) ) + { + if ( isDefined( self.entityHeadIcon ) ) + self.entityHeadIcon destroy(); + return; + } + + team = player.team; + self.entityHeadIconTeam = team; + + if ( isDefined( offset ) ) + self.entityHeadIconOffset = offset; + else + self.entityHeadIconOffset = (0,0,0); + + shader = game["entity_headicon_" + team]; + + headIcon = newClientHudElem( player ); + headIcon.archived = true; + headIcon.x = self.origin[0] + self.entityHeadIconOffset[0]; + headIcon.y = self.origin[1] + self.entityHeadIconOffset[1]; + headIcon.z = self.origin[2] + self.entityHeadIconOffset[2]; + headIcon.alpha = .8; + headIcon setShader( shader, 10, 10 ); + headIcon setWaypoint( false, false, false, true ); + self.entityHeadIcon = headIcon; + + self thread keepIconPositioned(); + self thread destroyHeadIconsOnDeath(); +} + +keepIconPositioned() +{ + self endon( "kill_entity_headicon_thread" ); + self endon( "death" ); + + pos = self.origin; + while(1) + { + if ( pos != self.origin ) + { + self updateHeadIconOrigin(); + pos = self.origin; + } + wait .05; + } +} + +destroyHeadIconsOnDeath() +{ + self endon( "kill_entity_headicon_thread" ); + self waittill ( "death" ); + + // TODO: remove and fix properly after ship + if( !isDefined(self.entityHeadIcon) ) + return; + + self.entityHeadIcon destroy(); +} + + +updateHeadIconOrigin() +{ + self.entityHeadIcon.x = self.origin[0] + self.entityHeadIconOffset[0]; + self.entityHeadIcon.y = self.origin[1] + self.entityHeadIconOffset[1]; + self.entityHeadIcon.z = self.origin[2] + self.entityHeadIconOffset[2]; +} \ No newline at end of file diff --git a/maps/mp/_events.gsc b/maps/mp/_events.gsc new file mode 100644 index 0000000..e83c53c --- /dev/null +++ b/maps/mp/_events.gsc @@ -0,0 +1,730 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +init() +{ + maps\mp\gametypes\_rank::registerScoreInfo( "headshot", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "execution", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "avenger", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "defender", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "posthumous", 25 ); + maps\mp\gametypes\_rank::registerScoreInfo( "revenge", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "double", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "triple", 75 ); + maps\mp\gametypes\_rank::registerScoreInfo( "multi", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "buzzkill", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "firstblood", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "comeback", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "longshot", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "assistedsuicide", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "knifethrow", 100 ); + + registerAdrenalineInfo( "damage", 10 ); + registerAdrenalineInfo( "damaged", 20 ); + registerAdrenalineInfo( "kill", 50 ); + registerAdrenalineInfo( "killed", 20 ); + + registerAdrenalineInfo( "headshot", 20 ); + registerAdrenalineInfo( "melee", 10 ); + registerAdrenalineInfo( "backstab", 20 ); + registerAdrenalineInfo( "longshot", 10 ); + registerAdrenalineInfo( "assistedsuicide", 10); + registerAdrenalineInfo( "defender", 10 ); + registerAdrenalineInfo( "avenger", 10 ); + registerAdrenalineInfo( "execution", 10 ); + registerAdrenalineInfo( "comeback", 50 ); + registerAdrenalineInfo( "revenge", 20 ); + registerAdrenalineInfo( "buzzkill", 20 ); + registerAdrenalineInfo( "double", 10 ); + registerAdrenalineInfo( "triple", 20 ); + registerAdrenalineInfo( "multi", 30 ); + registerAdrenalineInfo( "assist", 20 ); + + registerAdrenalineInfo( "3streak", 30 ); + registerAdrenalineInfo( "5streak", 30 ); + registerAdrenalineInfo( "7streak", 30 ); + registerAdrenalineInfo( "10streak", 30 ); + registerAdrenalineInfo( "regen", 30 ); + + precacheShader( "crosshair_red" ); + + level._effect["money"] = loadfx ("props/cash_player_drop"); + + level._numKills = 0; + + level thread onPlayerConnect(); +} + + +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + player.killedPlayers = []; + player.killedPlayersCurrent = []; + player.killedBy = []; + player.lastKilledBy = undefined; + player.greatestUniquePlayerKills = 0; + + player.recentKillCount = 0; + player.lastKillTime = 0; + player.damagedPlayers = []; + + player.adrenaline = 0; + player setAdrenaline( 0 ); + player thread monitorCrateJacking(); + player thread monitorObjectives(); + } +} + + +damagedPlayer( victim, damage, weapon ) +{ +// self giveAdrenaline( "damage" ); +// victim giveAdrenaline( "damaged" ); +} + + +killedPlayer( killId, victim, weapon, meansOfDeath ) +{ + victimGuid = victim.guid; + myGuid = self.guid; + curTime = getTime(); + + self thread updateRecentKills( killId ); + self.lastKillTime = getTime(); + self.lastKilledPlayer = victim; + + self.modifiers = []; + + level._numKills++; + + // a player is either damaged, or killed; never both + self.damagedPlayers[victimGuid] = undefined; + + self giveAdrenaline( "kill" ); + victim giveAdrenaline( "killed" ); + + if ( !isKillstreakWeapon( weapon ) ) + { + if ( weapon == "none" ) + return false; + + //if ( isSubStr( weapon, "ranger" ) && isDefined( self.bothBarrels ) ) This wont work because this is called before weapons self.bothbarrels would be set + // self.modifiers["bothbarrels"] = true; + + if ( isDefined( self.pers["copyCatLoadout"] ) && isDefined( self.pers["copyCatLoadout"]["owner"] ) ) + { + if ( victim == self.pers["copyCatLoadout"]["owner"] ) + self.modifiers["clonekill"] = true; + } + + if ( victim.attackers.size == 1 ) + { + /# + if ( !isDefined( victim.attackers[self.guid] ) ) + { + println("Weapon: "+ weapon ); + println("Attacker GUID:" + self.guid ); + + foreach ( key,value in victim.attackers ) + println( "Victim Attacker list GUID: " + key ); + } + #/ + assertEx( isDefined( victim.attackers[self.guid] ), "See console log for details" ); + + weaponClass = getWeaponClass( weapon ); + + if ( getTime() == victim.attackerData[self.guid].firstTimeDamaged && meansOfDeath != "MOD_MELEE" && ( /*weaponClass == "weapon_shotgun" ||*/ weaponClass == "weapon_sniper" ) ) + { + self.modifiers["oneshotkill"] = true; + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "one_shot_kill" ); + } + } + + if ( isDefined( victim.throwingGrenade ) && victim.throwingGrenade == "frag_grenade_mp" ) + self.modifiers["cooking"] = true; + + if ( isDefined(self.assistedSuicide) && self.assistedSuicide ) + self assistedSuicide( killId ); + + if ( level._numKills == 1 ) + self firstBlood( killId ); + + if ( self.pers["cur_death_streak"] > 3 ) + self comeBack( killId ); + + if ( meansOfDeath == "MOD_HEAD_SHOT" ) + { + if ( isDefined( victim.lastStand ) ) + execution( killId ); + else + headShot( killId ); + } + + if ( isDefined(self.wasti) && self.wasti && getTime() - self.spawnTime <= 5000 ) + self.modifiers["jackintheboxkill"] = true; + + if ( !isAlive( self ) && self.deathtime + 800 < getTime() ) + postDeathKill( killId ); + + fakeAvenge = false; + if ( level._teamBased && curTime - victim.lastKillTime < 500 ) + { + if ( victim.lastkilledplayer != self ) + self avengedPlayer( killId ); + } + + foreach ( guid, damageTime in victim.damagedPlayers ) + { + if ( guid == self.guid ) + continue; + + if ( level._teamBased && curTime - damageTime < 500 ) + { + p = getPlayerForGuid(guid); + if( p.team == self.team ) + { + self defendedPlayer( killId ); + } + } + } + + if ( isDefined( victim.attackerPosition ) ) + attackerPosition = victim.attackerPosition; + else + attackerPosition = self.origin; + + if ( isAlive( self ) && !self isUsingRemote() && (meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_HEAD_SHOT") && distance( attackerPosition, victim.origin ) > 1536 && !isKillstreakWeapon( weapon ) && !isDefined( self.assistedSuicide ) ) + self thread longshot( killId ); + + //if ( isAlive( self ) && self.health < 20 && isDefined( self.attackers ) && self.attackers.size == 1 && self.attackers[0] == victim ) + // victim thread consolation( killId ); + + if ( isDefined( victim.killstreaks[ victim.pers["cur_kill_streak"] + 1 ] ) ) + { + // playercard splash for the killstreak stopped + self buzzKill( killId, victim ); + } + + self maps\mp\_adrenaline::adrenalineTrySplash( victim ); + + self thread checkMatchDataKills( killId, victim, weapon, meansOfDeath); + + } + + if ( !isDefined( self.killedPlayers[victimGuid] ) ) + self.killedPlayers[victimGuid] = 0; + + if ( !isDefined( self.killedPlayersCurrent[victimGuid] ) ) + self.killedPlayersCurrent[victimGuid] = 0; + + if ( !isDefined( victim.killedBy[myGuid] ) ) + victim.killedBy[myGuid] = 0; + + self.killedPlayers[victimGuid]++; + + //this sets player stat for routine customer award + if ( self.killedPlayers[victimGuid] > self.greatestUniquePlayerKills ) + self setPlayerStat( "killedsameplayer", self.killedPlayers[victimGuid] ); + + self.killedPlayersCurrent[victimGuid]++; + victim.killedBy[myGuid]++; + + victim.lastKilledBy = self; +} + + +checkMatchDataKills( killId, victim, weapon, meansOfDeath ) +{ + weaponClass = getWeaponClass( weapon ); + alreadyUsed = false; + + self thread camperCheck(); + + if ( isDefined( self.lastKilledBy ) && self.lastKilledBy == victim ) + { + self.lastKilledBy = undefined; + self revenge( killId ); + + playFx( level._effect["money"], victim getTagOrigin( "j_spine4" ) ); + } + + if ( victim.iDFlags & level._iDFLAGS_PENETRATION ) + self incPlayerStat( "bulletpenkills", 1 ); + + if ( self.pers["rank"] < victim.pers["rank"] ) + self incPlayerStat( "higherrankkills", 1 ); + + if ( self.pers["rank"] > victim.pers["rank"] ) + self incPlayerStat( "lowerrankkills", 1 ); + + if ( isDefined( self.laststand ) && self.laststand ) + self incPlayerStat( "laststandkills", 1 ); + + if ( isDefined( victim.laststand ) && victim.laststand ) + self incPlayerStat( "laststanderkills", 1 ); + + if ( self getCurrentWeapon() != self.loadoutPrimary + "_mp" && self getCurrentWeapon() != self.loadoutSecondary + "_mp" ) + self incPlayerStat( "otherweaponkills", 1 ); + + if ( getBaseWeaponName( weapon ) == "m79" ) + self incPlayerStat( "thumperkills", 1 ); + + timeAlive = getTime() - victim.spawnTime ; + + if( !matchMakingGame() ) + victim setPlayerStatIfLower( "shortestlife", timeAlive ); + + victim setPlayerStatIfGreater( "longestlife", timeAlive ); + + switch( weaponClass ) + { + case "weapon_pistol": + case "weapon_machine_pistol": + case "weapon_smg": + case "weapon_assault": + case "weapon_projectile": + case "weapon_sniper": + case "weapon_shotgun": + case "weapon_lmg": + if ( self GetStance() == "crouch" ) + { + self incPlayerStat( "crouchkills", 1 ); + } + if ( self GetStance() == "prone" ) + { + self incPlayerStat( "pronekills", 1 ); + } + self checkMatchDataWeaponKills( victim, weapon, meansOfDeath, weaponClass ); + break; + case "weapon_grenade": + case "weapon_explosive": + self checkMatchDataEquipmentKills( victim, weapon, meansOfDeath ); + break; + default: + break; + } +} + +// Need to make sure these only apply to kills of an enemy, not friendlies or yourself +checkMatchDataWeaponKills( victim, weapon, meansOfDeath, weaponType ) +{ + attacker = self; + kill_ref = undefined; + headshot_ref = undefined; + death_ref = undefined; + + switch( weaponType ) + { + case "weapon_pistol": + kill_ref = "pistolkills"; + headshot_ref = "pistolheadshots"; + break; + case "weapon_machine_pistol": + kill_ref = "machinepistolkills"; + headshot_ref = "machinepistolheadshots"; + break; + case "weapon_smg": + kill_ref = "smgkills"; + headshot_ref = "smgheadshots"; + break; + case "weapon_assault": + kill_ref = "arkills"; + headshot_ref = "arheadshots"; + break; + case "weapon_projectile": + if ( weaponClass( weapon ) == "rocketlauncher" ) + kill_ref = "rocketkills"; + break; + case "weapon_sniper": + kill_ref = "sniperkills"; + headshot_ref = "sniperheadshots"; + break; + case "weapon_shotgun": + kill_ref = "shotgunkills"; + headshot_ref = "shotgunheadshots"; + death_ref = "shotgundeaths"; + break; + case "weapon_lmg": + kill_ref = "lmgkills"; + headshot_ref = "lmgheadshots"; + break; + default: + break; + } + + if ( isDefined ( kill_ref ) ) + attacker incPlayerStat( kill_ref, 1 ); + + if ( isDefined ( headshot_ref ) && meansOfDeath == "MOD_HEAD_SHOT" ) + attacker incPlayerStat( headshot_ref, 1 ); + + if ( isDefined ( death_ref ) && !matchMakingGame() ) + victim incPlayerStat( death_ref, 1 ); + + if ( attacker PlayerAds() > 0.5 ) + { + attacker incPlayerStat( "adskills", 1 ); + + if ( weaponType == "weapon_sniper" || isSubStr( weapon, "acog" ) ) + attacker incPlayerStat( "scopedkills", 1 ); + + if ( isSubStr( weapon, "thermal" ) ) + attacker incPlayerStat( "thermalkills", 1 ); + } + else + { + attacker incPlayerStat( "hipfirekills", 1 ); + } +} + +// Need to make sure these only apply to kills of an enemy, not friendlies or yourself +checkMatchDataEquipmentKills( victim, weapon, meansOfDeath ) +{ + attacker = self; + + // equipment kills + switch( weapon ) + { + case "frag_grenade_mp": + if ( attacker != victim ) + { + attacker incPlayerStat( "fragkills", 1 ); + attacker incPlayerStat( "grenadekills", 1 ); + } + isEquipment = true; + break; + case "c4_mp": + if ( attacker != victim ) + { + attacker incPlayerStat( "c4kills", 1 ); + } + isEquipment = true; + break; + case "semtex_mp": + if ( attacker != victim ) + { + attacker incPlayerStat( "semtexkills", 1 ); + attacker incPlayerStat( "grenadekills", 1 ); + } + isEquipment = true; + break; + case "claymore_mp": + if ( attacker != victim ) + { + attacker incPlayerStat( "claymorekills", 1 ); + } + isEquipment = true; + break; + case "throwingknife_mp": + attacker incPlayerStat( "throwingknifekills", 1 ); + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "knifethrow", maps\mp\gametypes\_rank::getScoreInfoValue( "knifethrow" ) ); + isEquipment = true; + break; + default: + isEquipment = false; + break; + } + + if ( isEquipment ) + attacker incPlayerStat( "equipmentkills", 1 ); +} + +camperCheck() +{ + if ( !isDefined ( self.lastKillLocation ) ) + { + self.lastKillLocation = self.origin; + self.lastCampKillTime = getTime(); + return; + } + + if ( Distance( self.lastKillLocation, self.origin ) < 512 && getTime() - self.lastCampKillTime > 5000 ) + { + self incPlayerStat( "mostcamperkills", 1 ); + } + + self.lastKillLocation = self.origin; + self.lastCampKillTime = getTime(); +} + +consolation( killId ) +{ + /* + value = int( maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 0.25 ); + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "consolation", value ); + self thread maps\mp\gametypes\_rank::giveRankXP( "consolation", value ); + */ +} + + +longshot( killId ) +{ + self.modifiers["longshot"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "longshot", maps\mp\gametypes\_rank::getScoreInfoValue( "longshot" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "longshot" ); + self thread giveAdrenaline( "longshot" ); + self incPlayerStat( "longshots", 1 ); + self thread maps\mp\_matchdata::logKillEvent( killId, "longshot" ); +} + + +execution( killId ) +{ + self.modifiers["execution"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "execution", maps\mp\gametypes\_rank::getScoreInfoValue( "execution" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "execution" ); + self thread giveAdrenaline( "execution" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "execution" ); +} + + +headShot( killId ) +{ + self.modifiers["headshot"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "headshot", maps\mp\gametypes\_rank::getScoreInfoValue( "headshot" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "headshot" ); + self thread giveAdrenaline( "headshot" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "headshot" ); +} + + +avengedPlayer( killId ) +{ + self.modifiers["avenger"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "avenger", maps\mp\gametypes\_rank::getScoreInfoValue( "avenger" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "avenger" ); + self thread giveAdrenaline( "avenger" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "avenger" ); + + self incPlayerStat( "avengekills", 1 ); +} + +assistedSuicide( killId ) +{ + self.modifiers["assistedsuicide"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "assistedsuicide", maps\mp\gametypes\_rank::getScoreInfoValue( "assistedsuicide" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "assistedsuicide" ); + self thread giveAdrenaline( "assistedsuicide" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "assistedsuicide" ); +} + +defendedPlayer( killId ) +{ + self.modifiers["defender"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "defender", maps\mp\gametypes\_rank::getScoreInfoValue( "defender" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "defender" ); + self thread giveAdrenaline( "defender" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "defender" ); + + self incPlayerStat( "rescues", 1 ); +} + + +postDeathKill( killId ) +{ + self.modifiers["posthumous"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "posthumous", maps\mp\gametypes\_rank::getScoreInfoValue( "posthumous" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "posthumous" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "posthumous" ); +} + + +backStab( killId ) +{ + self iPrintLnBold( "backstab" ); +} + + +revenge( killId ) +{ + self.modifiers["revenge"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "revenge", maps\mp\gametypes\_rank::getScoreInfoValue( "revenge" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "revenge" ); + self thread giveAdrenaline( "revenge" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "revenge" ); + + self incPlayerStat( "revengekills", 1 ); +} + + +multiKill( killId, killCount ) +{ + assert( killCount > 1 ); + + if ( killCount == 2 ) + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "doublekill", maps\mp\gametypes\_rank::getScoreInfoValue( "double" ) ); + self thread giveAdrenaline( "double" ); + } + else if ( killCount == 3 ) + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "triplekill", maps\mp\gametypes\_rank::getScoreInfoValue( "triple" ) ); + self thread giveAdrenaline( "triple" ); + thread teamPlayerCardSplash( "callout_3xkill", self ); + } + else + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "multikill", maps\mp\gametypes\_rank::getScoreInfoValue( "multi" ) ); + self thread giveAdrenaline( "multi" ); + thread teamPlayerCardSplash( "callout_3xpluskill", self ); + } + + self thread maps\mp\_matchdata::logMultiKill( killId, killCount ); + + // update player multikill record + self setPlayerStatIfGreater( "multikill", killCount ); + + // update player multikill count + self incPlayerStat( "mostmultikills", 1 ); +} + + +firstBlood( killId ) +{ + self.modifiers["firstblood"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "firstblood", maps\mp\gametypes\_rank::getScoreInfoValue( "firstblood" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "firstblood" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "firstblood" ); + self incPlayerStat( "firstblood", 1 ); + + thread teamPlayerCardSplash( "callout_firstblood", self ); +} + + +winningShot( killId ) +{ +} + + +buzzKill( killId, victim ) +{ + self.modifiers["buzzkill"] = victim.pers["cur_kill_streak"]; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "buzzkill", maps\mp\gametypes\_rank::getScoreInfoValue( "buzzkill" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "buzzkill" ); + self thread giveAdrenaline( "buzzkill" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "buzzkill" ); + + self.buzzkillcount++; +} + + +comeBack( killId ) +{ + self.modifiers["comeback"] = true; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "comeback", maps\mp\gametypes\_rank::getScoreInfoValue( "comeback" ) ); + self thread maps\mp\gametypes\_rank::giveRankXP( "comeback" ); + self thread giveAdrenaline( "comeback" ); + self thread maps\mp\_matchdata::logKillEvent( killId, "comeback" ); + + self incPlayerStat( "comebacks", 1 ); +} + + +disconnected() +{ + myGuid = self.guid; + + for ( entry = 0; entry < level._players.size; entry++ ) + { + if ( isDefined( level._players[entry].killedPlayers[myGuid] ) ) + level._players[entry].killedPlayers[myGuid] = undefined; + + if ( isDefined( level._players[entry].killedPlayersCurrent[myGuid] ) ) + level._players[entry].killedPlayersCurrent[myGuid] = undefined; + + if ( isDefined( level._players[entry].killedBy[myGuid] ) ) + level._players[entry].killedBy[myGuid] = undefined; + } +} + + +updateRecentKills( killId ) +{ + self endon ( "disconnect" ); + level endon ( "game_ended" ); + + self notify ( "updateRecentKills" ); + self endon ( "updateRecentKills" ); + + self.recentKillCount++; + + wait ( 1.0 ); + + if ( self.recentKillCount > 1 ) + self multiKill( killId, self.recentKillCount ); + + self.recentKillCount = 0; +} + +monitorCrateJacking() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + + for( ;; ) + { + self waittill( "hijacker", crateType, owner ); + + if( crateType == "sentry" ) + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "hijacker", 100 ); + self thread maps\mp\gametypes\_rank::giveRankXP( "hijacker", 100 ); + if ( isDefined( owner ) ) + owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( "hijacked_sentry", self ); + self notify( "process", "ch_hijacker" ); + } + else if( crateType == "mega" || crateType == "emergency_airdrop" ) + { + if ( self.team == owner.team ) + continue; + + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "hijacker", 100 ); + self thread maps\mp\gametypes\_rank::giveRankXP( "hijacker", 100 ); + if ( isDefined( owner ) ) + owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( "hijacked_emergency_airdrop", self ); + self notify( "process", "ch_newjack" ); + } + else + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "hijacker", 100 ); + self thread maps\mp\gametypes\_rank::giveRankXP( "hijacker", 100 ); + if ( isDefined( owner ) ) + owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( "hijacked_airdrop", self ); + self notify( "process", "ch_hijacker" ); + } + } +} + +monitorObjectives() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + + self waittill( "objective", objType ); + + if ( objType == "captured" ) + { + if ( isDefined( self.lastStand ) && self.lastStand ) + { + self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "heroic", 100 ); + self thread maps\mp\gametypes\_rank::giveRankXP( "reviver", 100 ); + } + } +} diff --git a/maps/mp/_fantasystats.gsc b/maps/mp/_fantasystats.gsc new file mode 100644 index 0000000..332eae9 --- /dev/null +++ b/maps/mp/_fantasystats.gsc @@ -0,0 +1,177 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +MIN_TIME_IN_GAME = 0.25; //Min % of total match's length for which the player has to be in the match in order for his stats to be recorded +MIN_NUM_PLAYERS = 5; //Minimum number of players that need to be at the end of the match in order for the fantasy stats to be tracked + +processFantasyStats() +{ + if( ( matchMakingGame() ) + && ( level._players.size >= MIN_NUM_PLAYERS ) + && ( getDvarInt( "fantasyStatTracking" ) == 1 ) ) + { + topscore = 0; + topPlayer = []; + foreach ( player in level._players ) + { + if ( player.score >= topscore ) + { + topscore = player.score; + topPlayer [ topPlayer.size ] = player; + } + } + + foreach ( player in topPlayer ) + { + player incPlayerStat ( "topscore", 1 ); + } + + localPlayerStatsInt = [ + "kills", + "deaths", + "killstreak", + "headshots", + "grenadekills", + "uavs", + "mostmultikills", + "multikill", + "knifekills", + "flankkills", + "laststandkills", + "assists", + "c4kills", + "claymorekills", + "fragkills", + "semtexkills", + "explosionssurvived", + "adskills", + "hipfirekills", + "revengekills", + "longestlife", + "throwbacks", + "mostcamperkills", + "fbhits", + "stunhits", + "scopedkills", + "arkills", + "arheadshots", + "lmgkills", + "lmgheadshots", + "sniperkills", + "sniperheadshots", + "shieldblocks", + "shieldkills", + "smgkills", + "smgheadshots", + "shotgunkills", + "shotgunheadshots", + "pistolkills", + "pistolheadshots", + "rocketkills", + "equipmentkills", + "intelCompleted", + "explosivehits", + "machinepistolkills", + "machinepistolheadshots", + "rescues", + "throwingknifekills", + "killswhilepushingugv", + "killsenemywhopushesugv", + "crouchkills", + "pronekills", + "firstblood", + "backstabber", + "flagscaptured", + "flagsreturned", + "flagscarried", + "bombsplanted", + "bombsdefused", + "bombsdefender", + "targetsdestroyed", + "pointscaptured", + "bulletpenkills", + "killstunnedenemy", + "killcookedgrenade", + "killwithstolenweapons", + "gamewinningkill", + "killwithkillstreaks", + "checkpoints", + "killstreakdestroyed", + "killduringenemyairkillstreak", + "topscore", + "dompointscapturedsingular", + "domdefendwithequipment" + ]; + localPlayerStatsFloat = [ "kdratio" ]; + // matchPlayerStatsInt = [ + // "scoreXp", + // "matchXp" ]; + // "hits", + // "misses", + // "totalShots", + // "accuracy" ]; + + gameLength = getTimePassed() / 1000; //getTimePassed returns the time in millisecond + + foreach ( player in level._players ) + { + if ( player.timePlayed["total"] > ( gameLength * MIN_TIME_IN_GAME )) + { + plat = "win"; + if( level._xenon ) + { + plat = "xen"; + } + if( level._ps3 ) + { + plat = "ps3"; + } + bbString = "fantasy_cod: username %s plat %s "; + actualString = "fantasy_cod: username " + player.gamertag + " plat " + plat + " "; + bbData = [ player.gamertag, plat ]; + println( "Fantasy Ints:" ); + foreach( stat in localPlayerStatsInt ) + { + if( player doesPlayerStatExist ( stat )) + { + data = player getPlayerStat( stat ); + } + else + { + data = "0"; + } + bbString += stat + " %d "; + actualString += stat + " " + data + " "; + bbData[ bbData.size ] = data; + println( stat + ": " + data ); + } + println( "Fantasy floats:" ); + foreach( stat in localPlayerStatsFloat ) + { + if( player doesPlayerStatExist ( stat )) + { + data = player getPlayerStat( stat ); + } + else + { + data = "0"; + } + bbString += stat + " %f "; + actualString += stat + " " + data + " "; + bbData[ bbData.size ] = data; + println( stat + ": " + data ); + } + // foreach( stat in matchPlayerStatsInt ) + // { + // data = player getPlayerData( "round", stat ); + // bbString += stat + " %d "; + // bbData[ bbData.size ] = data; + // } + println( bbString ); + println( actualString ); + bbprint( bbString, bbData, "uid" ); + } + } + } +} \ No newline at end of file diff --git a/maps/mp/_flashgrenades.gsc b/maps/mp/_flashgrenades.gsc new file mode 100644 index 0000000..16dd070 --- /dev/null +++ b/maps/mp/_flashgrenades.gsc @@ -0,0 +1,137 @@ +main() +{ + precacheShellshock("flashbang_mp"); +} + + +startMonitoringFlash() +{ + self thread monitorFlash(); +} + + +stopMonitoringFlash(disconnected) +{ + self notify("stop_monitoring_flash"); +} + + +flashRumbleLoop( duration ) +{ + self endon("stop_monitoring_flash"); + + self endon("flash_rumble_loop"); + self notify("flash_rumble_loop"); + + goalTime = getTime() + duration * 1000; + + while ( getTime() < goalTime ) + { + self PlayRumbleOnEntity( "damage_heavy" ); + wait( 0.05 ); + } +} + + +monitorFlash() +{ + self endon("disconnect"); + self.flashEndTime = 0; + while(1) + { + self waittill( "flashbang", origin, amount_distance, amount_angle, attacker ); + + if ( !isalive( self ) ) + continue; + + if ( isDefined( self.usingRemote ) ) + continue; + + hurtattacker = false; + hurtvictim = true; + + if ( amount_angle < 0.25 ) + amount_angle = 0.25; + else if ( amount_angle > 0.8 ) + amount_angle = 1; + + duration = amount_distance * amount_angle * 5.5; + + //NX1 flash resistance perk + if ( isDefined( self.flashScaler ) ) + duration = duration * self.flashScaler; + + if ( duration < 0.25 ) + continue; + + rumbleduration = undefined; + if ( duration > 2 ) + rumbleduration = 0.75; + else + rumbleduration = 0.25; + + assert(isdefined(self.pers["team"])); + if (level._teamBased && isdefined(attacker) && isdefined(attacker.pers["team"]) && attacker.pers["team"] == self.pers["team"] && attacker != self) + { + if(level._friendlyfire == 0) // no FF + { + continue; + } + else if(level._friendlyfire == 1) // FF + { + } + else if(level._friendlyfire == 2) // reflect + { + duration = duration * .5; + rumbleduration = rumbleduration * .5; + hurtvictim = false; + hurtattacker = true; + } + else if(level._friendlyfire == 3) // share + { + duration = duration * .5; + rumbleduration = rumbleduration * .5; + hurtattacker = true; + } + } + else + { + attacker notify( "flash_hit" ); + } + + if (hurtvictim) + self thread applyFlash(duration, rumbleduration); + if (hurtattacker) + attacker thread applyFlash(duration, rumbleduration); + } +} + +applyFlash(duration, rumbleduration) +{ + // wait for the highest flash duration this frame, + // and apply it in the following frame + + if (!isdefined(self.flashDuration) || duration > self.flashDuration) + self.flashDuration = duration; + if (!isdefined(self.flashRumbleDuration) || rumbleduration > self.flashRumbleDuration) + self.flashRumbleDuration = rumbleduration; + + wait .05; + + if (isdefined(self.flashDuration)) { + self shellshock( "flashbang_mp", self.flashDuration ); // TODO: avoid shellshock overlap + self.flashEndTime = getTime() + (self.flashDuration * 1000); + } + if (isdefined(self.flashRumbleDuration)) { + self thread flashRumbleLoop( self.flashRumbleDuration ); //TODO: Non-hacky rumble. + } + + self.flashDuration = undefined; + self.flashRumbleDuration = undefined; +} + + +isFlashbanged() +{ + return isDefined( self.flashEndTime ) && gettime() < self.flashEndTime; +} \ No newline at end of file diff --git a/maps/mp/_gasgrenades.gsc b/maps/mp/_gasgrenades.gsc new file mode 100644 index 0000000..47da8f1 --- /dev/null +++ b/maps/mp/_gasgrenades.gsc @@ -0,0 +1,482 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +init() +{ + + level._empInitialBlastTime = getDvarInt( "scr_empInitialEffectDuration", "10"); + level._empCloudTickTime = getDvarInt( "scr_empTickEffectDuration", "3"); + + level._gasCloudDuration = getDvarInt( "scr_gasCloudDuration", "9"); + level._gasCloudRadius = getDvarInt( "scr_gasCloudRadius", "185"); + level._gasCloudHeight = getDvarInt( "scr_gasCloudHeight", "20"); + level._gasCloudTickDamage = getDvarInt( "scr_gasCloudTickDamage", "13"); + level._gasCloudTickDamageHardcore = getDvarInt( "scr_gasCloudTickDamageHardcore", "5"); + + level._empCloudDuration = getDvarInt( "scr_empCloudDuration", "9"); + level._empCloudRadius = getDvarInt( "scr_empCloudRadius", "185"); + level._empCloudHeight = getDvarInt( "scr_empCloudHeight", "20"); + level._empCloudTickDamage = getDvarInt( "scr_empCloudTickDamage", "1"); + + level._gasCloudList = []; + level._empCloudList = []; +} + +increaseEmpCloudedTime( amount ) +{ + self.empCloudedTime += amount; +} + +watchEmpClouded() +{ + self endon ( "death" ); + self endon ( "disconnect" ); + + self.empCloudedTime = 0.0; + empCloudDeltaTime = 0.5; + + for(;;) + { + self waittill( "emp_cloud_update" ); + + self playLocalSound( "emp_activate" ); + + if ( self _hasPerk( "specialty_localjammer" )) + self RadarJamOff(); + + self setEMPJammed( true ); + + //wait for the decay to finish + while( self.empCloudedTime > 0 ) + { + wait( empCloudDeltaTime ); + self.empCloudedTime -= empCloudDeltaTime; + } + + if( self.empCLoudedTime < 0 ) + { + self.empCloudedTime = 0; + } + + //tagZP this should probably make sure that my team is not emp'd so that i do not turn off fx from the killstreak. + self setEMPJammed( false ); + + if ( self _hasPerk( "specialty_localjammer" )) + self RadarJamOn(); + } +} + +AddCloudToGasList( cloud ) +{ + list = level._gasCloudList; + list[ list.size ] = cloud; + level._gasCloudList = list; +} + +RemoveCloudFromGasList( cloud ) +{ + newArray = []; + for( i = 0; i < level._gasCloudList.size; i++ ) + { + if( level._gasCloudList[i] != cloud ) + { + newArray[ newArray.size ] = level._gasCloudList[i]; + } + } + level._gasCloudList = newArray; +} + +AddCloudToEMPList( cloud ) +{ + list = level._empCloudList; + list[ list.size ] = cloud; + level._empCloudList = list; +} + +RemoveCloudFromEMPList( cloud ) +{ + newArray = []; + for( i = 0; i < level._empCloudList.size; i++ ) + { + if( level._empCloudList[i] != cloud ) + { + newArray[ newArray.size ] = level._empCLoudList[i]; + } + } + level._empCloudList = newArray; +} + +//used by spawnlogic to determine the safty of this spawn point. +getCloudDanger( spawner ) +{ + cloudCount = 0; + + triggers = level._gasCloudList; + + foreach( trigger in triggers ) + { + if( spawner isTouching( trigger )) + { + cloudCount++; + } + } + + triggers = level._empCloudList; + + foreach( trigger in triggers ) + { + if( spawner isTouching( trigger )) + { + cloudCount++; + } + } + + return cloudCount; +} + +//returns true if the entity passed in is in any enemy clouds. Team should be passed in as my team. anyteam that doesnt match what is passed +//in is considered enemy. If team is not passed in all clouds are checked. +checkIsInCloud( entity, list, team ) +{ + foreach( cloud in list ) + { + if( entity isTouching( cloud )) + { + if( isDefined( team )) + { + assert( isDefined( cloud.owner )); + assert( isplayer( cloud.owner )); + + if( cloud.owner.pers["team"] != team ) + { + return true; + } + } + else + { + return true; + } + } + } + + return false; +} + +gasGrenadeExplodeWaiter( type ) +{ + self endon( "end_explode" ); + team = self.owner.team; + + self waittill( "explode", position ); + + cloudObj = Spawn( "script_origin", position ); + + cloudObj.owner = self.owner; + cloudObj.team = team; + + if( type == "gas" ) + { + cloudObj thread gasCloudMonitor( level._gasCloudDuration ); + } + else if( type == "emp" ) + { + cloudObj thread empCloudMonitor( level._empCloudDuration ); + } +} + +gasCloudMonitor( duration ) +{ + //self endon( "death" ); + position = self.origin; + + gasCloudRadius = level._gasCloudRadius; + gasCloudHeight = level._gasCloudHeight; + gasCloudTickDamage = level._gasCloudTickDamage; + + if ( level._hardcoreMode ) + { + gasCloudTickDamage = level._gasCloudTickDamageHardcore; + } + + // spawn trigger radius for the effect areas + gasEffectArea = spawn( "trigger_radius", position, 0, gasCloudRadius, gasCloudHeight ); + gasEffectArea.owner = self.owner; + AddCloudToGasList( gasEffectArea ); + + gasTotalTime = 0.0; // keeps track of the total time the gas cloud has been "alive" + gasTickTime = 1.0; // gas cloud ticks damage every second + gasInitialWait = 1.5; // wait this long before the cloud starts ticking for damage + gasTickCounter = 0; // just an internal counter to count gas damage ticks + + wait( gasInitialWait ); + gasTotalTime += gasInitialWait; + + for( ;; ) + { + if( gasTotalTime >= duration ) + { + break; + } + + //send out some radial damage + //RadiusDamage( self.origin, gasCloudRadius, gasCloudTickDamageMax, gasCloudTickDamageMin, self.owner ); + + //apply shellshock/damage fx to players in the gas cloud + foreach( player in level._players ) + { + if( level._teamBased ) + { + if( !isDefined( player.team )) + { + continue; + } + + if( !isDefined( self.owner )) + { + continue; + } + + if( player.team == self.team && player != self.owner ) + { + continue; + } + } + + if( player istouching( gasEffectArea ) && player.sessionstate == "playing" ) + { + if( ! ( player _hasPerk( "specialty_gasmask" ))) + { + trace = bullettrace( position, player.origin, false, player ); + if ( trace["fraction"] == 1 ) + { + // NOTE: DoDamage( , , , , , , , ) + //player DoDamgae( gasCloudTickDamageMin, position, self.owner, self, 0, "MOD_GAS", 0, "gas_grenade_mp" ); + + player shellShock( "gas_grenade_mp", 2 ); // Long enough... + RadiusDamage( player.origin, 16, gasCloudTickDamage, gasCloudTickDamage, self.owner); // "MOD_GAS", "gas_grenade_mp" ); + + //play coughing noise + player PlaySoundToPlayer( "breathing_gas_hurt", player ); + } + } + } + } + + wait( gasTickTime ); + gasTotalTime += gasTickTime; + gasTickCounter += 1; + } + + //clean up + RemoveCloudFromGasList( gasEffectArea ); + gasEffectArea delete(); + + self delete(); +} + +empCloudMonitor( duration ) +{ + //self endon( "death" ); + + assert( isDefined( self.owner )); + + empEffectArea = spawn( "trigger_radius", self.origin, 0, level._empCloudRadius, level._empCloudHeight ); + empEffectArea.owner = self.owner; + AddCloudToEMPList( empEffectArea ); + + empCloudGrenadeInitialBlast( empEffectArea, self.owner ); + + //println( "added emp cloud to list, size = " + level._empCloudList.size ); + + empTotalTime = 0.0; // keeps track of the total time the emp cloud has been "alive" + empTickTime = 1.0; // emp cloud ticks damage every second + empInitialWait = 1.5; // wait this long before the cloud starts ticking for damage + empTickCounter = 0; // just an internal counter to count gas damage ticks + + wait( empInitialWait ); + empTotalTime += empInitialWait; + + for( ;; ) + { + if( empTotalTime >= duration ) + { + break; + } + + //apply emp fx to players in the emp cloud + foreach( player in level._players ) + { + if( level._teamBased ) + { + if( !isDefined( player.team )) + { + continue; + } + + if( !isDefined( self.owner )) + { + continue; + } + + if( player.team == self.team && player != self.owner ) + { + continue; + } + } + + if( player istouching( empEffectArea ) && player.sessionstate == "playing" ) + { + //player thread maps\mp\killstreaks\_emp::EMPGrenade_JamPlayer( level._empCloudTickTime ); + player increaseEmpCloudedTime( level._empCloudTickTime ); + + player notify( "emp_cloud_update" ); + + if( level._empCloudTickDamage > 0 ) + { + RadiusDamage( player.origin, 16, level._empCloudTickDamage, level._empCloudTickDamage, self.owner); + } + } + } + + wait( empTickTime ); + empTotalTime += empTickTime; + empTickCounter += 1; + } + + //clean up + RemoveCloudFromEMPList( empEffectArea ); + + //println( "removed emp cloud from list, size = " + level._empCloudList.size ); + + empEffectArea delete(); + + self delete(); +} + +//Apply initial damage to world ents on explosion +empCloudGrenadeInitialBlast( trigger, attacker ) +{ + assert( isDefined( trigger )); + assert( isDefined( attacker )); + + //hit players with the initial blast + foreach( player in level._players ) + { + if( level._teamBased ) + { + if( !isDefined( player.pers["team"] )) + { + continue; + } + + if( !isDefined( attacker )) + { + continue; + } + + if( player.pers["team"] == attacker.pers["team"] && player != attacker ) + { + continue; + } + } + + if( player istouching( trigger ) && player.sessionstate == "playing" ) + { + //player thread maps\mp\killstreaks\_emp::EMPGrenade_JamPlayer( level._empInitialBlastTime ); + player increaseEmpCloudedTime( level._empInitialBlastTime ); + player notify( "emp_cloud_update" ); + } + } + + //take out enemy c4 in the initial blast + destroyEnemyC4( attacker, trigger ); + + //take down any helis it hits + foreach ( heli in level._helis ) + { + if( heli isTouching( trigger )) + { + radiusDamage( heli.origin, 384, 5000, 5000, attacker ); + } + } + + //take down any little birds + foreach ( littleBird in level._littleBird ) + { + if( littleBird isTouching( trigger )) + { + radiusDamage( littleBird.origin, 384, 5000, 5000, attacker ); + } + } + + /* + foreach ( turret in level._turrets ) + radiusDamage( turret.origin, 16, 5000, 5000, attacker ); + + foreach ( rocket in level._rockets ) + rocket notify ( "death" ); + */ + + //take down any uavs it hits + if ( level._teamBased ) + { + foreach ( uav in level._uavModels["allies"] ) + { + if( uav isTouching( trigger )) + { + radiusDamage( uav.origin, 384, 5000, 5000, attacker ); + } + } + + foreach ( uav in level._uavModels["axis"] ) + { + if( uav isTouching( trigger )) + { + radiusDamage( uav.origin, 384, 5000, 5000, attacker ); + } + } + } + else + { + foreach ( uav in level._uavModels ) + { + if( uav isTouching( trigger )) + { + radiusDamage( uav.origin, 384, 5000, 5000, attacker ); + } + } + } + + //take down any ac130's it hits + if ( isDefined( level._ac130player ) ) + { + if( level._ac130player isTouching( trigger )) + { + radiusDamage( level._ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000, attacker ); + } + } +} + +destroyEnemyC4( attacker, trigger ) +{ + foreach ( player in level._players ) + { + if ( player.pers["team"] != attacker.pers["team"] || ! level._teambased ) + { + if( isDefined( player.c4array )) + { + if ( player.c4Array.size > 0 ) + { + for( i = 0; i < player.c4Array.size; i++ ) + { + if( player.c4Array[i] isTouching( trigger )) + { + player notify( "alt_detonate" ); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/maps/mp/_global_fx.gsc b/maps/mp/_global_fx.gsc new file mode 100644 index 0000000..9936767 --- /dev/null +++ b/maps/mp/_global_fx.gsc @@ -0,0 +1,147 @@ +#include common_scripts\utility; +#include maps\mp\_utility; + + // This script automaticly plays a users specified oneshot effect on all prefabs that have the + // specified "script_struct" and "targetname" It also excepts angles from the "script_struct" + // but will set a default angle of ( 0, 0, 0 ) if none is defined. + // + // example of the syntax: + // global_FX( "targetname", "fxIDname", "fxFile", "delay" + +main() +{ + + randomStartDelay = randomfloatrange( -20, -15 ); + + // prefabs/misc_models/com_barrel_fire.map + global_FX( "barrel_fireFX_origin", "global_barrel_fire", "fire/firelp_barrel_pm", randomStartDelay, "fire_barrel_small" ); + + // prefabs/misc_models/ch_street_light_02_on.map + // prefabs/misc_models/ch_street_wall_light_01_on.map + global_FX( "ch_streetlight_02_FX_origin", "ch_streetlight_02_FX", "misc/lighthaze", randomStartDelay ); + + // prefabs/misc_models/me_streetlight_on.map + // prefabs/misc_models/me_streetlight_on_scaleddown80.map + global_FX( "me_streetlight_01_FX_origin", "me_streetlight_01_FX", "misc/lighthaze_bog_a", randomStartDelay ); + + // prefabs\village_assault\misc\lamp_post.map + // prefabs\misc_models\ch_street_light_01_on.map + global_FX( "ch_street_light_01_on", "lamp_glow_FX", "misc/light_glow_white", randomStartDelay ); + + // prefabs\dcburning\lamp_post_globe_on.map + global_FX( "lamp_post_globe_on", "lamp_glow_FX", "misc/light_glow_white", randomStartDelay ); + + // prefabs\village_assault\misc\highway_lamp_post.map + global_FX( "highway_lamp_post", "ch_streetlight_02_FX", "misc/lighthaze_villassault", randomStartDelay ); + + // prefabs/misc_models/cs_cargoship_spotlight_on.map + global_FX( "cs_cargoship_spotlight_on_FX_origin", "cs_cargoship_spotlight_on_FX", "misc/lighthaze", randomStartDelay ); + + // prefabs/misc_models/me_dumpster_fire.map + global_FX( "me_dumpster_fire_FX_origin", "me_dumpster_fire_FX", "fire/firelp_med_pm", randomStartDelay, "fire_dumpster_medium" ); + + // prefabs/misc_models/com_tires01_burning.map + global_FX( "com_tires_burning01_FX_origin", "com_tires_burning01_FX", "fire/tire_fire_med", randomStartDelay ); + + // prefabs/icbm/icbm_powerlinetower02.map + global_FX( "icbm_powerlinetower_FX_origin", "icbm_powerlinetower_FX", "misc/power_tower_light_red_blink", randomStartDelay ); + + // prefabs/icbm/icbm_powerlinetower02.map + global_FX( "icbm_mainframe_FX_origin", "icbm_mainframe_FX", "props/icbm_mainframe_lightblink", randomStartDelay ); + + // prefabs/misc_model/cs_cargoship_wall_light_red_pulse.map + global_FX( "light_pulse_red_FX_origin", "light_pulse_red_FX", "misc/light_glow_red_generic_pulse", -2 ); + + // prefabs/misc_model/cs_cargoship_wall_light_red_pulse.map + global_FX( "light_pulse_red_FX_origin", "light_pulse_red_FX", "misc/light_glow_red_generic_pulse", -2 ); + + // prefabs/misc_model/cs_cargoship_wall_light_orange_pulse.map + global_FX( "light_pulse_orange_FX_origin", "light_pulse_orange_FX", "misc/light_glow_orange_generic_pulse", -2 ); + + // prefabs/oilrig/lights/light_corner_01.map + // prefabs/oilrig/helipad/helipad_light.map + global_FX( "light_red_blink_FX_origin", "light_red_blink", "misc/power_tower_light_red_blink", -2 ); + + // prefabs/misc_models/ch_industrial_light_01_on.map + global_FX( "lighthaze_oilrig_FX_origin", "lighthaze_oilrig", "misc/lighthaze_oilrig", randomStartDelay ); + + // prefabs/misc_models/ch_industrial_light_01_on_white.map + global_FX( "lighthaze_white_FX_origin", "lighthaze_white", "misc/lighthaze_white", randomStartDelay ); + + // prefabs/misc_models/cs_cargoship_wall_light_on.map + global_FX( "light_glow_walllight_white_FX_origin", "light_glow_walllight_white", "misc/light_glow_walllight_white", randomStartDelay ); + + // prefabs/misc_models/me_lightfluohang_on.map + global_FX( "fluorescent_glow_FX_origin", "fluorescent_glow", "misc/fluorescent_glow", randomStartDelay ); + + // prefabs/misc_models/ch_industrial_light_02_on.map + global_FX( "light_glow_industrial_FX_origin", "light_glow_industrial", "misc/light_glow_industrial", randomStartDelay ); + + // prefabs/cliffhanger/red_light1.map + // prefabs/misc_model/com_emergencylightcase_on.map + global_FX( "light_red_steady_FX_origin", "light_red_steady", "misc/tower_light_red_steady", -2 ); + + // prefabs/cliffhanger/blue_light1.map + // prefabs/oilrig/helipad/helipad_light.map + // prefabs/misc_model/com_emergencylightcase_blue_on.map + global_FX( "light_blue_steady_FX_origin", "light_blue_steady", "misc/tower_light_blue_steady", -2 ); + + // prefabs/misc_models/com_emergencylightcase_orange.map + global_FX( "light_orange_steady_FX_origin", "light_orange_steady", "misc/tower_light_orange_steady", -2 ); + + // prefabs/misc_models/mil_lightstick_pile_on.map + global_FX( "glow_stick_pile_FX_origin", "glow_stick_pile", "misc/glow_stick_glow_pile", -2 ); + + // prefabs/misc_models/mil_lightstick_pile_on_orange.map + global_FX( "glow_stick_orange_pile_FX_origin", "glow_stick_pile_orange", "misc/glow_stick_glow_pile_orange", -2 ); + + // prefabs/plaza/blinky_tower.map + global_FX( "highrise_blinky_tower", "highrise_blinky_tower_FX", "misc/power_tower_light_red_blink_large", randomStartDelay ); + + // prefabs/mil_emergency_flare.map + global_FX( "flare_ambient_FX_origin", "flare_ambient_FX", "misc/flare_ambient", randomStartDelay, "emt_road_flare_burn" ); + + // prefabs/misc_models/dt_light_on.map + // prefabs/misc_models/com_utility_light_on.map + // prefabs/misc_models/utility_lightbulb_bare_on.map + global_FX( "light_glow_white_bulb_FX_origin", "light_glow_white_bulb_FX", "misc/light_glow_white_bulb", randomStartDelay); + + // prefabs/misc_models/com_restaurantceilinglamp_on.map + global_FX( "light_glow_white_lamp_FX_origin", "light_glow_white_lamp_FX", "misc/light_glow_white_lamp", randomStartDelay); + +} + +global_FX( targetname, fxName, fxFile, delay, soundalias ) +{ + // script_structs + ents = getstructarray(targetname,"targetname"); + if ( !isdefined( ents ) ) + return; + if ( ents.size <= 0 ) + return; + + for ( i = 0 ; i < ents.size ; i++ ) + ents[i] global_FX_create( fxName, fxFile, delay, soundalias ); +} + +global_FX_create( fxName, fxFile, delay, soundalias ) +{ + if ( !isdefined( level._effect ) ) + level._effect = []; + if ( !isdefined( level._effect[ fxName ] ) ) + level._effect[ fxName ] = loadfx( fxFile ); + + // default effect angles if they dont exist + if ( !isdefined( self.angles ) ) + self.angles = ( 0, 0, 0 ); + + ent = createOneshotEffect( fxName ); + ent.v[ "origin" ] = ( self.origin ); + ent.v[ "angles" ] = ( self.angles ); + ent.v[ "fxid" ] = fxName; + ent.v[ "delay" ] = delay; + if ( isdefined( soundalias ) ) + { + ent.v[ "soundalias" ] = soundalias; + } +} \ No newline at end of file diff --git a/maps/mp/_highlights.gsc b/maps/mp/_highlights.gsc new file mode 100644 index 0000000..b9bdf8c --- /dev/null +++ b/maps/mp/_highlights.gsc @@ -0,0 +1,16 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +giveHighlight( ref, value ) +{ + highlightCount = getClientMatchData( "highlightCount" ); + if ( highlightCount < 18 ) // must match MaxHighlights in clientmatchdata definition + { + setClientMatchData( "highlights", highlightCount, "award", ref ); + setClientMatchData( "highlights", highlightCount, "clientId", self.clientMatchDataId ); + setClientMatchData( "highlights", highlightCount, "value", value ); + + highlightCount++; + setClientMatchData( "highlightCount", highlightCount ); + } +} \ No newline at end of file diff --git a/maps/mp/_intel.gsc b/maps/mp/_intel.gsc new file mode 100644 index 0000000..4e738e3 --- /dev/null +++ b/maps/mp/_intel.gsc @@ -0,0 +1,791 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +INTEL_OFFSET = (0, 0, 24); +INTEL_OFFSET_TOP = (0, 0, 36); +INTEL_ICON_PULSE_SCALE = 1.2; +INTEL_ICON_PULSE_WAIT_SEC = 5; +INTEL_ICON_COLOR = (1,1,1); + +//******************************************************************* +// * +// * +//******************************************************************* + +init() +{ + if( getDvarInt( "prototype_intel_enabled" ) == 1 ) + { + println( "Intel enabled" ); + + intelGamePercentage = getDvarInt( "prototype_intel_percentage" ); + + if( intelGamePercentage >= randomInt( 100 )) + { + println( "Intel: This will be an intel game" ); + initIntel(); + level thread onPlayerConnect(); + + level thread addIntelToGame(); + + //tempGetStarted(); + } + else + { + println( "Intel: This is not going to be an intel game" ); + } + } + else + { + println( "Intel not inited ", getDvarInt( "prototype_intel_enabled" )); + } +} + +tempGetStarted() +{ + level waittill("connected", player); + + player thread tempGetStartedSpawned(); +} + +tempGetStartedSpawned() +{ + wait 3; + // setup the team, close the menu, then set our class and wait for our player to spawn + self [[level._onTeamSelection]]( "allies" ); + self closepopupMenu(); + self closeInGameMenu(); + self.selectedClass = true; + self [[level._class]]("class0"); + players = getentarray("player", "classname"); + while( players.size == 0 ) + { + wait 1; + players = getentarray("player", "classname"); + } +} + +intelDebugging() +{ + return false; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +initIntel() +{ + // setup the models and stuff we need for intel + //precacheShader("waypoint_bomb"); + precacheModel( "prop_suitcase_intel" ); + precacheString(&"MP_AQUIRING_INTEL"); + precacheString(&"MP_INTEL_HEADER"); + + level._intelHUDIcon = "hud_suitcase_bomb"; + precacheShader( level._intelHUDIcon ); + + level._intel = undefined; + // we need to setup our array of intel types + intelInitData = []; + intelInitData["replenish"] = "ammo_primary"; + intelKillsEvalData = []; + intelKillsEvalData["kills"]["count"] = 3; + intelKillsEvalData["kills"]["string"] = &"MP_INTEL_KILLS_DESC"; + intelKillsAwardData = []; + intelKillsAwardData["experience"] = 1000; + addIntelType( "intel_kills", 0, 15, ::initLifeStats, intelInitData, ::evalLifeStats, intelKillsEvalData, ::intelAward, intelKillsAwardData ); + + intelInitData = []; + intelInitData["replenish"] = "ammo_primary"; + intelKillsEvalData = []; + intelKillsEvalData["headshots"]["count"] = 1; + intelKillsEvalData["headshots"]["string"] = &"MP_INTEL_HEADSHOT_DESC"; + intelKillsAwardData = []; + intelKillsAwardData["experience"] = 1000; + addIntelType( "intel_headshot", 0, 15, ::initLifeStats, intelInitData, ::evalLifeStats, intelKillsEvalData, ::intelAward, intelKillsAwardData ); + + intelInitData = []; + intelInitData["replenish"] = "ammo_primary"; + intelKillsEvalData = []; + intelKillsEvalData["mostmultikills"]["count"] = 1; + intelKillsEvalData["mostmultikills"]["string"] = &"MP_INTEL_MULTIKILL_DESC"; + intelKillsAwardData = []; + intelKillsAwardData["experience"] = 1000; + addIntelType( "intel_multikills", 0, 15, ::initLifeStats, intelInitData, ::evalLifeStats, intelKillsEvalData, ::intelAward, intelKillsAwardData ); + + intelInitData = []; + intelInitData["replenish"] = "equipment"; + intelKillsEvalData = []; + intelKillsEvalData["equipmentkills"]["count"] = 1; + intelKillsEvalData["equipmentkills"]["string"] = &"MP_INTEL_EQUIPMENT_DESC"; + intelKillsAwardData = []; + intelKillsAwardData["experience"] = 1000; + addIntelType( "intel_equipmentkills", 0, 15, ::initLifeStats, intelInitData, ::evalLifeStats, intelKillsEvalData, ::intelAward, intelKillsAwardData ); + + // generate the max weighted value + level._intelMaxWeight = 0; + foreach ( intelName, intelDef in level._intelDefs ) + { + if ( intelDef["weight"] > 0 ) + { + level._intelMaxWeight += intelDef["weight"]; + level._intelDefs[intelName]["weight"] = level._intelMaxWeight; +// println( "Adding intel " + intelName + " with weight value " + intelDef["weight"] + " max weight is " + level._intelMaxWeight ); + } + else + { + println( "Warning: Intel def with 0 weight! name = ", intelName ); + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +addIntelType( name, intelLevel, weight, initFunc, initData, evalFunc, evalData, awardFunc, awardData ) +{ + evalData["name"] = name; + awardData["name"] = name; + level._intelDefs[name]["weight"] = weight; + level._intelDefs[name]["intelLevel"] = intelLevel; + level._intelDefs[name]["initFunc"] = initFunc; + level._intelDefs[name]["initData"] = initData; + level._intelDefs[name]["evalFunc"] = evalFunc; + level._intelDefs[name]["evalData"] = evalData; + level._intelDefs[name]["awardFunc"] = awardFunc; + level._intelDefs[name]["awardData"] = awardData; + + foreach( evalPiece, evalDataList in evalData ) + { + println( evalPiece ); + if( evalPiece != "name" && isDefined( evalDataList["string"] )) + { + PreCacheString( evalDataList["string"] ); + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +getRandomIntel() +{ + value = randomInt( level._intelMaxWeight ); + + selectedIntelName = undefined; + foreach ( intelName, intelDef in level._intelDefs ) + { + if( intelDef["weight"] > 0 ) + { + selectedIntelName = intelName; + + if ( intelDef["weight"] > value ) + { + break; + } + } + } + + return( selectedIntelName ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +initIntelOnPlayer( player ) +{ + process = level._intelDefs[ level._intel ][ "initFunc" ]; + processInitData = level._intelDefs[ level._intel ][ "initData" ]; + processEvalData = level._intelDefs[ level._intel ][ "evalData" ]; + + return [[ process ]]( player, processInitData, processEvalData ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +evalIntelOnPlayer( player ) +{ + process = level._intelDefs[ level._intel ][ "evalFunc" ]; + processData = level._intelDefs[ level._intel ][ "evalData" ]; + + return [[ process ]]( player, processData ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +awardIntelOnPlayer( player ) +{ + process = level._intelDefs[ level._intel ][ "awardFunc" ]; + processData = level._intelDefs[ level._intel ][ "awardData" ]; + + [[ process ]]( player, processData ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +addIntelToGame() +{ + level._intel = getRandomIntel(); + + println( "Intel added to the game ", level._intel ); + + // wait till we have some player connected + level waittill( "connected", player ); + + while( level._players.size == 0 ) + { + wait 0.05; + } + + // find a intel spawn location + spawnPoint = findIntelSpawnLocation(); + + assert( isDefined( spawnPoint )); + + // create the use objects + level._intelEnt = createIntelBreifcase( spawnPoint ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +findIntelSpawnLocation() +{ + // for now, just grab a random dom point +// randomPlayer = level._players[ randomInt( level._players.size ) ]; + +// randomPlayer waittill( "spawned_player" ); + +// return randomPlayer [[ level._getSpawnPoint ]](); + + while( 1 ) + { + wait 0.5; + if( isDefined( level._spawnpoints )) + { + if( level._spawnpoints.size > 0 ) + { + break; + } + } + } + + return level._spawnpoints[ randomInt( level._spawnpoints.size ) ]; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +createIntelBreifcase( entity ) +{ + visuals[0] = spawn( "script_model", entity.origin ); + visuals[0].angles = entity.angles; + visuals[0] setModel( "prop_suitcase_intel" ); + + cloneTrigger = spawn( "trigger_radius", entity.origin, 0, 96, 60 ); + intelEnt = cloneTrigger; + + intelZone = maps\mp\gametypes\_gameobjects::createCarryObject( "friendly", intelEnt, visuals, INTEL_OFFSET ); + intelZone maps\mp\gametypes\_gameobjects::setUseTime( 0.5 ); + intelZone maps\mp\gametypes\_gameobjects::setUseText( &"MP_AQUIRING_INTEL" ); + intelZone maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" ); +// intelZone maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_bomb" ); +// intelZone maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_bomb" ); +// intelZone maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_bomb" ); +// intelZone maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_bomb" ); + intelZone maps\mp\gametypes\_gameobjects::allowCarry( "any" ); + intelZone maps\mp\gametypes\_gameobjects::setCarrierVisible( false ); + + intelZone thread intelSpinAnimate(); + + intelZone.onPickup = ::onPickupIntel; + intelZone.onDrop = ::onDropIntel; + intelZone.allowWeapons = true; + intelZone.oldRadius = intelEnt.radius; + + return intelZone; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +intelSpinAnimate() +{ + level endon( "game_ended" ); + self endon( "reset" ); + self endon( "pickup_object" ); + + bottomPos = self.curOrigin + INTEL_OFFSET; + topPos = self.curOrigin + INTEL_OFFSET_TOP; + + while( true ) + { + self.visuals[0] moveTo( topPos, 0.5, 0.15, 0.15 ); + self.visuals[0] rotateYaw( 180, 0.5 ); + + wait( 0.5 ); + + self.visuals[0] moveTo( bottomPos, 0.5, 0.15, 0.15 ); + self.visuals[0] rotateYaw( 180, 0.5 ); + + wait( 0.5 ); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onPickupIntel( player ) +{ +// level._intelEnt maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", undefined ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", undefined ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", undefined ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", undefined ); + + player thread onIntelAquired(); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onDropIntel( player ) +{ +// level._intelEnt maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_bomb" ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_bomb" ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_bomb" ); +// level._intelEnt maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_bomb" ); + + level._intelEnt thread intelSpinAnimate(); + intelCardSplashEveryone( "intel_dropped_callout", player ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + player thread notifyIntelGame(); + player thread onPlayerSpawned(); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onPlayerSpawned() +{ + self endon( "disconnect" ); + + if( intelDebugging()) + println( "Intel: onPlayerSpawned" ); + + for(;;) + { + self waittill( "spawned_player" ); + if( intelDebugging()) + println( "Intel: Player spawned" ); + self._intelHasIntel = 0; +// self thread intelWaitDeath(); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +intelWaitDeath() +{ + self endon( "intel_cleanup" ); + self waittill( "death" ); + self notify( "intel_cleanup" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +intelWaitCleanup() +{ + self waittill( "intel_cleanup" ); + wait 1; + self destroyIntelHud(); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +onIntelAquired() +{ + self endon( "disconnect" ); + self endon( "death" ); + + //intelCardSplashEveryone( "intel_pickup_callout", self ); + + self._intelHasIntel = 1; + self createIntelHud(); + self thread intelWaitDeath(); + self thread intelWaitCleanup(); + + println( "Intel: intel aquired by ", self.name ); + + initIntelOnPlayer( self ); + + while( 1 ) + { + if( evalIntelOnPlayer( self ) == 1 ) + { + println( "Intel: Awarding intel to player" ); + + intelCardSplashEveryone( "intel_completed_callout", self ); + + self incPlayerStat( "intelCompleted", 1 ); + + awardIntelOnPlayer( self ); + // get rid of the intel, it's served it's purpose + //level._intelEnt thread maps\mp\gametypes\_gameobjects::deleteUseObject(); + level._intelEnt maps\mp\gametypes\_gameobjects::disableObject(); + + break; + } + wait 0.05; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +// Evaluation and Award funcs + +//******************************************************************* +// * +// * +//******************************************************************* + +initLifeStats( player, initData, evalData ) +{ + if( intelDebugging()) + println( "Initing Intel on ", player.name ); + i = 0; + foreach( intelStat, intelStatValue in evalData ) + { + if( intelStat != "name" ) + { + player._intelInitValues[intelStat] = getPlayerStat( intelStat ); + player._intelHud["lines"][i]["item"] SetText( intelStatValue["string"] ); + i += 1; + } + } + if( isDefined( initData["replenish"] )) + { + weaponList = player GetWeaponsListAll(); + switch( initData["replenish"] ) + { + case "ammo_primary": + foreach ( weaponName in weaponList ) + { + if ( maps\mp\gametypes\_weapons::isPrimaryWeapon( weaponName ) ) + { + player giveMaxAmmo( weaponName ); + } + } + break; + + case "equipment": + foreach ( weaponName in weaponList ) + { + if ( maps\mp\gametypes\_weapons::isEquipment( weaponName ) ) + { + player giveMaxAmmo( weaponName ); + } + } + break; + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +evalLifeStats( player, evalData ) +{ + ret = 0; + allStatsSatisfied = 1; + if( intelDebugging()) + println( "Evaluating Intel on ", player.name ); + if( isDefined( evalData )) + { + i = 0; + foreach( intelStat, intelDef in evalData ) + { + if( intelStat != "name" ) + { + intelStatValue = intelDef["count"]; + currStatValue = ( getPlayerStat( intelStat ) - player._intelInitValues[intelStat] ); + + if( intelDebugging()) + println( "Checking ", intelStat, " value ", intelStatValue ); + if( currStatValue < intelStatValue ) + { + allStatsSatisfied = 0; + } + else + { + currStatValue = intelStatValue; + } + + // hud text + hudText = currStatValue + "/" + intelStatValue; + if( player._intelHud["lines"][i]["text"] != hudText ) + { + player._intelHud["lines"][i]["text"] = hudText; + player._intelHud["lines"][i]["status"] SetText( hudText ); + } + + i = i + 1; + } + } + if( allStatsSatisfied == 1 ) + { + ret = 1; + } + } + else + { + println( "Could not find evaluation data!\n" ); + } + return ret; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +intelAward( player, awardData ) +{ + println( "Giving Intel Award to ", player.name ); + if( isDefined( awardData )) + { + player thread maps\mp\gametypes\_hud_message::SplashNotify( "intel_completed", awardData["experience"] ); + + foreach( award, value in awardData ) + { + if( award != "name" ) + { + println( award, " ", value ); + switch( award ) + { + case "experience": + self thread awardIntelXp( value, awardData ); + break; + + default: + println( "Didn't understand how to deal with award type ", award ); + } + } + } + } + else + { + println( "No awards found!" ); + } + + player notify( "intel_cleanup" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +// Hud Notificaiton Scripts + +//******************************************************************* +// * +// * +//******************************************************************* + +awardIntelXp( value, awardData ) +{ + self endon ( "disconnect" ); + + wait( 0.25 ); + self maps\mp\gametypes\_rank::giveRankXP( "challenge", value ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +notifyIntelGame() +{ + self waittill( "spawned_player" ); + if( intelDebugging()) + println( "We are playing a game with Intel!" ); + + self thread maps\mp\gametypes\_hud_message::SplashNotify( "intel_ingame", 0 ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +intelCardSplashEveryone( splash, owner ) +{ + if ( level._hardCoreMode ) + return; + + foreach ( player in level._players ) + { + player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( splash, owner ); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +hudIconPulse() +{ + self endon( "intel_cleanup" ); + origWidth = self._intelHud["icon"].width; + origHeight = self._intelHud["icon"].height; + for(;;) + { + self._intelHud["icon"] scaleOverTime( 0.05, int( origWidth * INTEL_ICON_PULSE_SCALE ), int( origHeight * INTEL_ICON_PULSE_SCALE ) ); + wait 0.05; + self._intelHud["icon"] scaleOverTime( 0.3, origWidth, origHeight ); + wait 0.3; + wait INTEL_ICON_PULSE_WAIT_SEC; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +createIntelHud() +{ + self._intelHud["icon"] = createIcon( level._intelHUDIcon, 40, 40 ); + self._intelHud["icon"].horzAlign = "left"; + self._intelHud["icon"].alignX = "left"; + self._intelHud["icon"].y = 110; + self._intelHud["icon"].sort = -10; + self._intelHud["icon"].color = INTEL_ICON_COLOR; + self thread hudIconPulse(); + + currY = 130; + self._intelHud["header"] = CreateFontString( "objective", 1.3 ); + self._intelHud["header"].horzAlign = "left"; + self._intelHud["header"].alignX = "left"; + self._intelHud["header"] SetText( &"MP_INTEL_HEADER" ); + self._intelHud["header"].y = currY; + self._intelHud["header"].x = 42; + currY += 20; + + xIndent = 20; + xOffset = 40; + + self._intelHud["lines"][0]["item"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][0]["item"].horizAlign = "left"; + self._intelHud["lines"][0]["item"].alignX = "left"; + self._intelHud["lines"][0]["item"].y = currY; + self._intelHud["lines"][0]["item"].x = xIndent + xOffset; + self._intelHud["lines"][0]["status"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][0]["status"].horizAlign = "left"; + self._intelHud["lines"][0]["status"].alignX = "left"; + self._intelHud["lines"][0]["status"].y = currY; + self._intelHud["lines"][0]["status"].x = xIndent; + self._intelHud["lines"][0]["text"] = ""; + currY += 20; + + self._intelHud["lines"][1]["item"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][1]["item"].horizAlign = "left"; + self._intelHud["lines"][1]["item"].alignX = "left"; + self._intelHud["lines"][1]["item"].y = currY; + self._intelHud["lines"][1]["item"].x = xIndent + xOffset; + self._intelHud["lines"][1]["status"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][1]["status"].horizAlign = "left"; + self._intelHud["lines"][1]["status"].alignX = "left"; + self._intelHud["lines"][1]["status"].y = currY; + self._intelHud["lines"][1]["status"].x = xIndent; + self._intelHud["lines"][1]["text"] = ""; + currY += 20; + + self._intelHud["lines"][2]["item"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][2]["item"].horizAlign = "left"; + self._intelHud["lines"][2]["item"].alignX = "left"; + self._intelHud["lines"][2]["item"].y = currY; + self._intelHud["lines"][2]["item"].x = xIndent + xOffset; + self._intelHud["lines"][2]["status"] = CreateFontString( "objective", 1.25 ); + self._intelHud["lines"][2]["status"].horizAlign = "left"; + self._intelHud["lines"][2]["status"].alignX = "left"; + self._intelHud["lines"][2]["status"].y = currY; + self._intelHud["lines"][2]["status"].x = xIndent; + self._intelHud["lines"][2]["text"] = ""; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +destroyIntelHud() +{ + self._intelHud["icon"] destroy(); + self._intelHud["header"] destroy(); + self._intelHud["lines"][0]["item"] destroy(); + self._intelHud["lines"][0]["status"] destroy(); + self._intelHud["lines"][1]["item"] destroy(); + self._intelHud["lines"][1]["status"] destroy(); + self._intelHud["lines"][2]["item"] destroy(); + self._intelHud["lines"][2]["status"] destroy(); +} diff --git a/maps/mp/_javelin.gsc b/maps/mp/_javelin.gsc new file mode 100644 index 0000000..bb3306e --- /dev/null +++ b/maps/mp/_javelin.gsc @@ -0,0 +1,615 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +InitJavelinUsage() +{ + self.javelinStage = undefined; + self.javelinPoints = undefined; + self.javelinNormals = undefined; + self.javelinLockMisses = undefined; + self.javelinTargetPoint = undefined; + self.javelinTargetNormal = undefined; + self.javelinLockStartTime = undefined; +} + + +ResetJavelinLocking() +{ + if ( !IsDefined( self.javelinUseEntered ) ) + return; + self.javelinUseEntered = undefined; + + self notify( "stop_lockon_sound" ); + + self WeaponLockFree(); + self WeaponLockTargetTooClose( false ); + self WeaponLockNoClearance( false ); + self.currentlyLocking = false; + self.currentlyLocked = false; + self.javelinTarget = undefined; + + self StopLocalSound( "javelin_clu_lock" ); + self StopLocalSound( "javelin_clu_aquiring_lock" ); + + InitJavelinUsage(); +} + + +/# +DrawStar( point, color ) +{ + Line( point + (10,0,0), point - (10,0,0), color ); + Line( point + (0,10,0), point - (0,10,0), color ); + Line( point + (0,0,10), point - (0,0,10), color ); +} +#/ + + +EyeTraceForward() +{ + origin = self GetEye(); + angles = self GetPlayerAngles(); + forward = AnglesToForward( angles ); + endpoint = origin + forward * 15000; + + res = BulletTrace( origin, endpoint, false, undefined ); + + if ( res["surfacetype"] == "none" ) + return undefined; + if ( res["surfacetype"] == "default" ) + return undefined; + + ent = res["entity"]; + if ( IsDefined( ent ) ) + { + if ( ent == level._ac130.planeModel ) + return undefined; + } + + results = []; + results[0] = res["position"]; + results[1] = res["normal"]; + return results; +} + + +LockMissesReset() +{ + self.javelinLockMisses = undefined; +} + + +LockMissesIncr() +{ + if ( !IsDefined( self.javelinLockMisses ) ) + self.javelinLockMisses = 1; + else + self.javelinLockMisses++; +} + + +LockMissesPassedThreshold() +{ + MAX_MISSES = 4; + + if ( IsDefined( self.javelinLockMisses ) && (self.javelinLockMisses >= MAX_MISSES) ) + return true; + return false; +} + + +TargetPointTooClose( targetPoint ) +{ + // changed by NS JKU was 1100. since this is no longer a secondary, we can be a little more liberal with the targeting. + MY_MIN_DIST = 700; + + dist = Distance( self.origin, targetPoint ); + if ( dist < MY_MIN_DIST ) + return true; + + return false; +} + + +LoopLocalSeekSound( alias, interval ) +{ + self endon ( "death" ); + self endon ( "disconnect" ); + self endon ( "stop_lockon_sound" ); + + for ( ;; ) + { + self PlayLocalSound( alias ); + wait interval; + } +} + + +TopAttackPasses( targPoint, targNormal ) +{ + origin = targPoint + (targNormal * 10.0); + endpoint = origin + (0,0,2000); + + result = BulletTrace( origin, endpoint, false, undefined ); + + if ( BulletTracePassed( origin, endpoint, false, undefined ) ) + return true; + return false; +} + + +JavelinUsageLoop() +{ + self endon("death"); + self endon("disconnect"); + + LOCK_LENGTH = 1150; + GATHER_DELAY = 25; + ADS_DELAY = 100; + MAX_POINT_PEER_DIST = 400; + POINTS_NEEDED_TO_START_LOCK = 12; + + lastGatherTime = 0; + lastOutOfADS = 0; + self.javelinTarget = undefined; + + InitJavelinUsage(); + + for( ;; ) + { + wait 0.05; + + debugDraw = false; + if ( GetDVar( "missileDebugDraw" ) == "1" ) + debugDraw = true; + + debugText = false; + if ( GetDVar( "missileDebugText" ) == "1" ) + debugText = true; + + weapon = self getCurrentWeapon(); + if ( !isSubStr( weapon, "javelin" ) || self isEMPed() ) + { + ResetJavelinLocking(); + continue; + } + if ( self PlayerADS() < 0.95 ) + { + lastOutOfADS = GetTime(); + + ResetJavelinLocking(); + continue; + } + + self.javelinUseEntered = true; + if ( !IsDefined( self.javelinStage ) ) + self.javelinStage = 1; + + if ( self.javelinStage == 1 ) // SCANNING: try to find a good point to lock to + { + + targets = GetTargetList(); + if ( targets.size != 0 ) + { + + targetsInReticle = []; + foreach ( target in targets ) + { + insideReticle = self WorldPointInReticle_Circle( target.origin, 65, 40 ); + if ( insideReticle ) + targetsInReticle[targetsInReticle.size] = target; + } + + if ( targetsInReticle.size != 0 ) + { + + sortedTargets = SortByDistance( targetsInReticle, self.origin ); + + if ( !( self VehicleLockSightTest( sortedTargets[0] ) ) ) + continue; + + if ( debugText ) + PrintLn( "Javeling found a vehicle target to lock to." ); + + self.javelinTarget = sortedTargets[0]; + + if ( !isDefined( self.javelinLockStartTime ) ) + self.javelinLockStartTime = GetTime(); + + self.javelinStage = 2; + self.javelinLostSightlineTime = 0; + + self javelinLockVehicle( LOCK_LENGTH ); + self.javelinStage = 1; + continue; + } + + } + + if ( LockMissesPassedThreshold() ) + { + ResetJavelinLocking(); + continue; + } + + timePassed = GetTime() - lastOutOfADS; + if ( timePassed < ADS_DELAY ) + continue; + + /# + if ( debugDraw && IsDefined( self.javelinPoints ) ) + { + foreach( javPoint in self.javelinPoints ) + DrawStar( javPoint, (0.8, 1.0, 0.8) ); + DrawStar( self.javelinPoints[self.javelinPoints.size - 1], (1, 1, 0.2) ); + DrawStar( AveragePoint( self.javelinPoints ), (0.2, 0.2, 1) ); + } + #/ + + timePassed = GetTime() - lastGatherTime; + if ( timePassed < GATHER_DELAY ) + continue; + lastGatherTime = GetTime(); + + traceRes = (self EyeTraceForward()); + if ( !IsDefined( traceRes ) ) + { + self LockMissesIncr(); + continue; + } + + if ( self TargetPointTooClose( traceRes[0] ) ) + { + self WeaponLockTargetTooClose( true ); + continue; + } + else + { + self WeaponLockTargetTooClose( false ); + } + + // make sure we haven't strayed too far + if ( IsDefined( self.javelinPoints ) ) + { + prevAvgPoint = AveragePoint( self.javelinPoints ); + dist = Distance( prevAvgPoint, traceRes[0] ); + //PrintLn( "[", self.javelinPoints.size, "] - Dist: ", dist ); + + if ( dist > MAX_POINT_PEER_DIST ) + { + LockMissesIncr(); + continue; + } + } + else + { + self.javelinPoints = []; + self.javelinNormals = []; + } + + self.javelinPoints[self.javelinPoints.size] = traceRes[0]; + self.javelinNormals[self.javelinNormals.size] = traceRes[1]; + + self LockMissesReset(); + if ( self.javelinPoints.size < POINTS_NEEDED_TO_START_LOCK ) + continue; + + // Go to stage 2: + self.javelinTargetPoint = AveragePoint( self.javelinPoints );; + self.javelinTargetNormal = AverageNormal( self.javelinNormals );; + self.javelinLockMisses = undefined; + self.javelinPoints = undefined; + self.javelinNormals = undefined; + self.javelinLockStartTime = GetTime(); + + self WeaponLockStart( self.javelinTargetPoint ); + self thread LoopLocalSeekSound( "javelin_clu_aquiring_lock", 0.6 ); + + self.javelinStage = 2; + } + + if ( self.javelinStage == 2 ) // LOCKING: complete lockon to point + { + /# + if ( debugDraw ) + DrawStar( self.javelinTargetPoint, (0.5, 1.0, 0.6) ); + #/ + + insideReticle = self WorldPointInReticle_Circle( self.javelinTargetPoint, 65, 45 ); + if ( !insideReticle ) + { + ResetJavelinLocking(); + continue; + } + + if ( self TargetPointTooClose( self.javelinTargetPoint ) ) + self WeaponLockTargetTooClose( true ); + else + self WeaponLockTargetTooClose( false ); + + timePassed = getTime() - self.javelinLockStartTime; + //PrintLn( "Locking [", timePassed, "]..." ); + if ( timePassed < LOCK_LENGTH ) + continue; + + self WeaponLockFinalize( self.javelinTargetPoint, (0,0,0), true ); + self notify( "stop_lockon_sound" ); + self PlayLocalSound( "javelin_clu_lock" ); + self.javelinStage = 3; + } + + if ( self.javelinStage == 3 ) // LOCKED: try and hold it + { + /# + if ( debugDraw ) + DrawStar( self.javelinTargetPoint, (0.1, 0.15, 1.0) ); + #/ + + insideReticle = self WorldPointInReticle_Circle( self.javelinTargetPoint, 65, 45 ); + if ( !insideReticle ) + { + ResetJavelinLocking(); + continue; + } + + if ( self TargetPointTooClose( self.javelinTargetPoint ) ) + self WeaponLockTargetTooClose( true ); + else + self WeaponLockTargetTooClose( false ); + + continue; + } + } +} + +GetTargetList() +{ + targets = []; + + if ( level._teamBased ) + { + if ( IsDefined( level._chopper ) && ( level._chopper.team != self.team || level._chopper.owner == self ) ) ///check for teams + targets[targets.size] = level._chopper; + + if ( IsDefined( level._raven ) && ( level._raven.team != self.team || level._raven.owner == self ) ) ///check for teams + targets[targets.size] = level._raven; + + if ( isDefined( level._harriers) ) + { + foreach( harrier in level._harriers ) + { + if ( isDefined( harrier ) && ( harrier.team != self.team || ( isDefined( harrier.owner ) && harrier.owner == self ) ) ) + targets[targets.size] = harrier; + } + } + + foreach( target_player in level._players ) + { + if (( target_player.team != self.team ) && (target_player _hasPerk("specialty_juggersuit"))) + { + targets[targets.size] = target_player; + } + } + + if( level._multiTeamBased ) + { + //for all teams + for( i = 0; i < level._teamNameList.size; i++ ) + { + //that are not our team + if( self.team != level._teamNameList[i] ) + { + //does that team have any uav's + if( level._UAVModels[level._teamNameList[i]].size ) + { + //add each uav to the target list + foreach ( UAV in level._UAVModels[level._teamNameList[i]] ) + { + targets[targets.size] = UAV; + } + } + } + } + } + else if ( level._UAVModels[level._otherTeam[self.team]].size ) + { + foreach ( UAV in level._UAVModels[level._otherTeam[self.team]] ) + targets[targets.size] = UAV; + } + + if ( isDefined(level._ac130player) && ( level._ac130player.team != self.team ) ) + targets[targets.size] = level._ac130.planeModel; + } + else + { + if ( IsDefined( level._chopper ) && ( level._chopper.owner != self ) ) ///check for teams + targets[targets.size] = level._chopper; + + if ( isDefined(level._ac130player) ) + targets[targets.size] = level._ac130; + + if ( isDefined( level._harriers) ) + { + foreach( harrier in level._harriers ) + { + if ( isDefined( harrier ) ) + targets[targets.size] = harrier; + } + } + + foreach( target_player in level._players ) + { + if (( target_player != self ) && (target_player _hasPerk("specialty_juggersuit"))) + { + targets[targets.size] = target_player; + } + } + + if ( level._UAVModels.size ) + { + foreach ( ownerGuid, UAV in level._UAVModels ) + { + if ( isDefined( UAV.owner ) && UAV.owner == self ) + continue; + + targets[targets.size] = UAV; + } + } + } + + return targets; +} + + +DebugSightLine( start, end, passed ) +{ + /# + if ( GetDVar( "missileDebugDraw" ) != "1" ) + return; + + if ( passed ) + color = ( 0.3, 1.0, 0.3 ); + else + color = ( 1.0, 0.2, 0.2 ); + + MY_OFFSET = ( 0, 0, 5 ); + + Line( start + MY_OFFSET, end, color ); + #/ +} + +VehicleLockSightTest( target ) +{ + eyePos = self GetEye(); + + center = target GetPointInBounds( 0, 0, 0 ); + passed = BulletTracePassed( eyePos, center, false, target ); + DebugSightLine( eyePos, center, passed ); + if ( passed ) + return true; + + front = target GetPointInBounds( 1, 0, 0 ); + passed = BulletTracePassed( eyePos, front, false, target ); + DebugSightLine( eyePos, front, passed ); + if ( passed ) + return true; + + back = target GetPointInBounds( -1, 0, 0 ); + passed = BulletTracePassed( eyePos, back, false, target ); + DebugSightLine( eyePos, back, passed ); + if ( passed ) + return true; + + return false; +} + +javelinLockVehicle( lockLength ) +{ + if ( self.javelinStage == 2 ) // locking on to a target + { + self WeaponLockStart( self.javelinTarget ); + + if ( !(self StillValidJavelinLock( self.javelinTarget ) ) ) + { + ResetJavelinLocking(); + self.javelinLockStartTime = undefined; + return; + } + + passed = SoftSightTest(); + if ( !passed ) + { + self.javelinLockStartTime = undefined; + return; + } + + if ( !isDefined( self.currentlyLocking ) || !self.currentlyLocking ) + { + self thread LoopLocalSeekSound( "javelin_clu_aquiring_lock", 0.6 ); + self.currentlyLocking = true; + } + + timePassed = getTime() - self.javelinLockStartTime; + + if ( timePassed < lockLength ) + return; + + //strangely buggy with the moving target... + //javTarg = eyeTraceForward(); + //if ( !isDefined( javTarg ) ) + // return; + + //topAttack = TopAttackPasses( javTarg[0], javTarg[1] ); + + if( isPlayer( self.javelinTarget )) + { + self WeaponLockFinalize( self.javelinTarget, (0,0,32), false ); + } + else + { + self WeaponLockFinalize( self.javelinTarget, (0,0,0), false ); + } + + + self notify( "stop_lockon_sound" ); + + if ( !isDefined( self.currentlyLocked ) || !self.currentlyLocked ) + { + self PlayLocalSound( "javelin_clu_lock" ); + self.currentlyLocked = true; + } + + self.javelinStage = 3; + } + + if ( self.javelinStage == 3 ) // target locked + { + passed = SoftSightTest(); + if ( !passed ) + return; + + if ( !(self StillValidJavelinLock( self.javelinTarget ) ) ) + { + ResetJavelinLocking(); + return; + } + } +} + + +StillValidJavelinLock( ent ) +{ + assert( IsDefined( self ) ); + + if ( !IsDefined( ent ) ) + return false; + if ( !(self WorldPointInReticle_Circle( ent.origin, 65, 85 )) ) + return false; + + return true; +} + + +SoftSightTest() +{ + LOST_SIGHT_LIMIT = 500; + + if ( self VehicleLockSightTest( self.javelinTarget ) ) + { + self.javelinLostSightlineTime = 0; + return true; + } + + if ( self.javelinLostSightlineTime == 0 ) + self.javelinLostSightlineTime = getTime(); + + timePassed = GetTime() - self.javelinLostSightlineTime; + + if ( timePassed >= LOST_SIGHT_LIMIT ) + { + ResetJavelinLocking(); + return false; + } + + return true; +} \ No newline at end of file diff --git a/maps/mp/_killingdoor.gsc b/maps/mp/_killingdoor.gsc new file mode 100644 index 0000000..089f44f --- /dev/null +++ b/maps/mp/_killingdoor.gsc @@ -0,0 +1,318 @@ +//**************************************************************************** + // ** + // Confidential - (C) Activision Publishing, Inc. 2010 ** + // ** + //**************************************************************************** + // ** + // Module: Phase 3 Check-In: Script controlling multiple sets of two ** + // moving doors that will kill players who are stuck in between ** + // This script works for the following setups for each door set ** + // in Radiant: ** + // 2 door models: ** + // script_model: "targetname" "killing_door_1" ** + // script_model: "targetname" "killing_door_2" ** + // 2 clips: ** + // script_brushmodel: "targetname" "killing_clip_1" ** + // script_brushmodel: "targetname" "killing_clip_2" ** + // 3 triggers: ** + // trigger_multiple: "targetname" "killing_trigger_1" ** + // trigger_multiple: "targetname" "killing_trigger_2" ** + // trigger_multiple: "targetname" "killing_trigger_center"** + // ** + // Created: May 17th, 2011 - James Chen ** + // ** + //***************************************************************************/ + + + //tagJC: For demonstration, please run mp_nx_killtest. + //tagJC: Custom key values are added into the Radiant key table. Their impact on Radiant will need to be assessed over time + //tagJC: Like in phase1, the doors will not kill if multiple players are stuck in between the doors. + // A potential solution will be to introduce a delay time before the trigger in the center start to conduct the killings. + // However, the delay-time solution needs to be assessed in terms of its impact on gameplay (delay etc.). + //tagJC: Because of the double doors setup, it is not practical nor realistic to move the doors vertically along the 'z' direction + main() + { + //tagJC: Getting all the entities into corresponding arrays and do basic error checking + level._killingDoor1 = getentArray_and_assert( "killing_door_1" ); + level._killingDoor2 = getentArray_and_assert( "killing_door_2" ); + level._killingClip1 = getentArray_and_assert( "killing_clip_1" ); + level._killingClip2 = getentArray_and_assert( "killing_clip_2" ); + level._killingTrigger1 = getentArray_and_assert( "killing_trigger_1" ); + level._killingTrigger2 = getentArray_and_assert( "killing_trigger_2" ); + level._killingTriggerCenter = getentArray_and_assert( "killing_trigger_center" ); + + //tagJC: Checking for the correct numbers of models, clips and triggers in order to make sure that the script will function + // correctly. + checking_setup(); + + //tagJC: Linking the door models and triggers to the clips + linking( level._killingClip1 , level._killingDoor1 ); + linking( level._killingClip1 , level._killingTrigger1 ); + linking( level._killingClip2 , level._killingDoor2 ); + linking( level._killingClip2 , level._killingTrigger2 ); + + //tagJC: Based on proximity, pair up clip1, clip2, and all the three corresponding triggers into sets + pairing( level._killingClip1, level._killingClip2, level._killingTriggerCenter, level._killingTrigger1, level._killingTrigger2 ); + + //tagJC: Make the doors move + move_doors(); + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Linking entities in object_list_2 to that in object_list_1 based on proximity + linking( object_list_1 , object_list_2 ) + { + for ( i = 0; i < object_list_1.size; i++ ) + { + //tagJC: Use an arbitrary distance as the base for comparision + paired_object2 = find_closest( object_list_1[i], object_list_2 ); + + //tagJC: Link the paired objects to that in object_list_1 + paired_object2 LinkTo( object_list_1[i] ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: This function pairs up the clips with each other as well as the corresponding triggers + pairing( clip1_list , clip2_list, cTrigger_list, Trigger1_list, Trigger2_list ) + { + for ( i = 0; i < clip1_list.size; i++ ) + { + //tagJC: Determine the clip2 that is the closest to the current clip1 under examination + paired_clip2 = find_closest( clip1_list[i], clip2_list ); + //tagJC: Determine the center trigger that is the closest to the current clip1 under examination + paired_cTrigger = find_closest( clip1_list[i], cTrigger_list ); + //tagJC: Determine the trigger1 that is the closest to the current clip1 under examination + paired_Trigger1 = find_closest( clip1_list[i], Trigger1_list ); + //tagJC: Determine the trigger2 that is the closest to the current clip1 under examination + paired_Trigger2 = find_closest( clip1_list[i], Trigger2_list ); + //tagJC: Putting the set into a level array + level._killingSet[i][ "clip1" ] = clip1_list[i]; + level._killingSet[i][ "clip2" ] = paired_clip2; + level._killingSet[i][ "cTrigger" ] = paired_cTrigger; + level._killingSet[i][ "Trigger1" ] = paired_Trigger1; + level._killingSet[i][ "Trigger2" ] = paired_Trigger2; + //tagJC: Useful debugging message + //IPrintLnBold( "clip1 at " + level._killingSet[i][ "clip1" ].origin + " is paired with clip2 at " + level._killingSet[i][ "clip2" ].origin + " and Center Trigger at " + level._killingSet[i][ "cTrigger" ].origin + " and Trigger1 at " + level._killingSet[i][ "Trigger1" ].origin + " and Trigger2 at " + level._killingSet[i][ "Trigger2" ].origin); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + find_closest( entity, entity_list ) + { + //tagJC: Use an arbitrary distance as the base for comparision + closest_distance = distance( entity.origin , entity_list[0].origin ); + closest_entity = entity_list[0]; + for ( i = 1; i < entity_list.size; i++ ) + { + //tagJC: If another entity on the list results in a shorter distance, update the results accordingly + if ( distance( entity.origin , entity_list[i].origin ) < closest_distance ) + { + closest_distance = distance( entity.origin , entity_list[i].origin ); + closest_entity = entity_list[i]; + } + } + return closest_entity; + } + //******************************************************************* + // * + // * + //******************************************************************* + move_doors() + { + for ( i = 0; i < level._killingSet.size ; i++ ) + { + //tagJC: Starting moving the clips + level thread moving_doors( level._killingSet[i][ "clip1" ], level._killingSet[i][ "clip2" ] ); + //tagJC: Starting to spawn the triggers and detect players' contact + level._killingSet[i][ "cTrigger" ] thread kill_stuck_players( level._killingSet[i][ "Trigger1" ], level._killingSet[i][ "Trigger2" ]); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + moving_doors( clip1, clip2 ) + { + //tagJC: Determine the distance and the vector of which the doors will move + dis = distance( clip1.origin, clip2.origin ); + moving_vector = clip1.origin - clip2.origin; + //tagJC: Start to move the two clips in opposite directions + if ( isDefined ( level.KillingDoorControllingLogic )) + { + if ( ! isDefined ( level.escortPlusKillingDoorClosed ) ) + { + level.escortPlusKillingDoorClosed = 0; + } + clip1 thread [[level.KillingDoorControllingLogic]]( moving_vector * -1/3, ( dis/clip1.speed ), clip1.door_time_remain_open, clip1.door_time_remain_close ); + clip2 thread [[level.KillingDoorControllingLogic]]( moving_vector * 1/3, ( dis/clip1.speed ), clip1.door_time_remain_open, clip1.door_time_remain_close ); + } + else + { + clip1 thread move_one_door( moving_vector, ( dis/clip1.speed ), clip1.door_time_remain_open, clip1.door_time_remain_close ); + clip2 thread move_one_door( moving_vector * -1, ( dis/clip1.speed ), clip1.door_time_remain_open, clip1.door_time_remain_close ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Moving one door back and forth according to the values sspecified by the designer + move_one_door( moving_vector, moving_time, door_time_remain_open, door_time_remain_close ) + { + while ( 1 ) + { + self moveTo( self.origin + moving_vector, moving_time, moving_time * 0.5, moving_time * 0.5 ); + self waittill( "movedone" ); + wait door_time_remain_open; + + self moveTo( self.origin - moving_vector, moving_time, moving_time * 0.5, moving_time * 0.5 ); + self waittill( "movedone" ); + wait door_time_remain_close; + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + kill_stuck_players( Trigger1, Trigger2 ) + { + while ( 1 ) + { + //tagJC: Detecting whether death_trig has been touched + self waittill( "trigger", player); + //tagJC: Depending on how death_trig is setup in Radiant, this might be a useful debug message + //IPrintLnBold( "death_trig has been touched!" ); + + + //tagJC: Depending on the setup in Radiant, the following two are useful debugging functions + //Trigger1 thread testing1(); + //Trigger2 thread testing2(); + + //tagJC: If a player is inside death_trig and is touching both death_trig1 and death_trig2 at the same time, + // kill the player + if (( player IsTouching( Trigger1 )) && ( player IsTouching( Trigger2 ))) + { + player thread [[level._callbackPlayerDamage]]( + player, // eInflictor The entity that causes the damage.(e.g. a turret) + player, // eAttacker The entity that is attacking. + 500, // iDamage Integer specifying the amount of damage done + 0, // iDFlags Integer specifying flags that are to be applied to the damage + "MOD_SUICIDE", // sMeansOfDeath Integer specifying the method of death MOD_RIFLE_BULLET + player.primaryweapon, // sWeapon The weapon number of the weapon used to inflict the damage + player.origin, // vPoint The point the damage is from? + (0, 0, 0), // vDir The direction of the damage + "none", // sHitLoc The location of the hit + 0 // psOffsetTime The time offset for the damage + ); + } + else + { + wait .05; + } + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Check for matching numbers of entities for door models, clips and triggers + checking_setup () + { + set_count = level._killingDoor1.size; + if ( level._killingDoor2.size != set_count ) + { + AssertEX( false , "The number of door 2 needs to equal to the number of door 1" ); + } + if ( level._killingClip1.size != set_count ) + { + AssertEX( false , "The number of clip 1 needs to equal to the number of door 1" ); + } + if ( level._killingClip2.size != set_count ) + { + AssertEX( false , "The number of clip 2 needs to equal to the number of door 1" ); + } + if ( level._killingTrigger1.size != set_count ) + { + AssertEX( false , "The number of trigger 1 needs to equal to the number of door 1" ); + } + if ( level._killingTrigger2.size != set_count ) + { + AssertEX( false , "The number of trigger 2 needs to equal to the number of door 1" ); + } + if ( level._killingTriggerCenter.size != set_count ) + { + AssertEX( false , "The number of center trigger needs to equal to the number of door 1" ); + } + for ( i = 0; i < level._killingClip1.size; i++ ) + { + AssertEX( isDefined( level._killingClip1[i].speed ), "Clip1 located at " + level._killingClip1[i].origin + " does not have the speed specified." ); + } + for ( i = 0; i < level._killingClip1.size; i++ ) + { + AssertEX( isDefined( level._killingClip1[i].door_time_remain_open ), "Clip1 located at " + level._killingClip1[i].origin + " does not have the door_time_remain_open specified." ); + } + for ( i = 0; i < level._killingClip1.size; i++ ) + { + AssertEX( isDefined( level._killingClip1[i].door_time_remain_close ), "Clip1 located at " + level._killingClip1[i].origin + " does not have the door_time_remain_close specified." ); + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Useful helper function to get the requested entity and check for any errors + getentArray_and_assert( ent_name ) + { + object = getEntArray( ent_name, "targetname" ); + AssertEX( object.size > 0 , "There is no entity for " + ent_name ); + return object; + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Useful debugging function to test killing_trigger_1 + testing1() + { + while ( 1 ) + { + self waittill( "trigger", player); + + IPrintLnBold( "killing_trigger_1 has been touched!" ); + + wait 0.05; + } + } + + //******************************************************************* + // * + // * + //******************************************************************* + //tagJC: Useful debugging function to test killing_trigger_2 + testing2() + { + while ( 1 ) + { + self waittill( "trigger", player); + + IPrintLnBold( "killing_trigger_2 has been touched!" ); + + wait 0.05; + } + } \ No newline at end of file diff --git a/maps/mp/_load.gsc b/maps/mp/_load.gsc new file mode 100644 index 0000000..85c27e6 --- /dev/null +++ b/maps/mp/_load.gsc @@ -0,0 +1,351 @@ +#include common_scripts\utility; +#include common_scripts\_fx; +#include maps\mp\_utility; + +main() +{ + if ( isDefined( level._loadStarted ) ) + { + //println( "level loading has already started returning out!!!!" ); + return; + } + + level._loadStarted = true; + level._createFX_enabled = ( getdvar( "createfx" ) == "on" ); + + struct_class_init(); + + initGameFlags(); + initLevelFlags(); + + level._generic_index = 0; + // flag_struct is used as a placeholder when a flag is set without an entity + + level._flag_struct = spawnstruct(); + level._flag_struct assign_unique_id(); + if ( !isdefined( level._flag ) ) + { + level._flag = []; + level._flags_lock = []; + } + + level._requiredMapAspectRatio = getDvarFloat( "scr_RequiredMapAspectratio", 1 ); + level._createClientFontString_func = maps\mp\gametypes\_hud_util::createFontString; + level._HUDsetPoint_func = maps\mp\gametypes\_hud_util::setPoint; + level._leaderDialogOnPlayer_func = maps\mp\_utility::leaderDialogOnPlayer; + + thread maps\mp\gametypes\_tweakables::init(); + + + if ( !isdefined( level._func ) ) + level._func = []; + level._func[ "precacheMpAnim" ] = ::precacheMpAnim; + level._func[ "scriptModelPlayAnim" ] = ::scriptModelPlayAnim; + level._func[ "scriptModelClearAnim" ] = ::scriptModelClearAnim; + + // dodge this stuff for createfx tool. + if( !level._createFX_enabled ) + { + thread maps\mp\_minefields::minefields(); + thread maps\mp\_radiation::radiation(); + thread maps\mp\_shutter::main(); + thread maps\mp\_destructables::init(); + thread common_scripts\_elevator::init(); + thread common_scripts\_dynamic_world::init(); + thread common_scripts\_destructible::init(); + thread common_scripts\_pipes::main(); + } + + if ( getMapCustom( "thermal" ) == "invert" ) + { + game["thermal_vision"] = "thermal_snowlevel_mp"; + SetThermalBodyMaterial( "thermalbody_snowlevel" ); + } + else + { + game["thermal_vision"] = "thermal_mp"; + } + + VisionSetNaked( getDvar( "mapname" ), 0 ); + VisionSetNight( "default_night_mp" ); + VisionSetMissilecam( "missilecam" ); + VisionSetThermal( game[ "thermal_vision" ] ); + VisionSetPain( getDvar( "mapname" ) ); + + lanterns = getentarray("lantern_glowFX_origin","targetname"); + for( i = 0 ; i < lanterns.size ; i++ ) + lanterns[i] thread lanterns(); + + maps\mp\_art::main(); + thread common_scripts\_painter::main("painter_mp"); + + setupExploders(); + + thread common_scripts\_fx::initFX(); + + if ( level._createFX_enabled ) + { + maps\mp\_createfx::createfx(); + } + + if ( getdvar( "r_reflectionProbeGenerate" ) == "1" ) + { + maps\mp\gametypes\_spawnlogic::setMapCenterForReflections(); + maps\mp\_global_fx::main(); + level waittill( "eternity" ); + } + + thread maps\mp\_global_fx::main(); + + // Do various things on triggers + for ( p = 0;p < 6;p ++ ) + { + switch( p ) + { + case 0: + triggertype = "trigger_multiple"; + break; + + case 1: + triggertype = "trigger_once"; + break; + + case 2: + triggertype = "trigger_use"; + break; + + case 3: + triggertype = "trigger_radius"; + break; + + case 4: + triggertype = "trigger_lookat"; + break; + + default: + assert( p == 5 ); + triggertype = "trigger_damage"; + break; + } + + triggers = getentarray( triggertype, "classname" ); + + for ( i = 0;i < triggers.size;i ++ ) + { + if( isdefined( triggers[ i ].script_prefab_exploder) ) + triggers[i].script_exploder = triggers[ i ].script_prefab_exploder; + + if( isdefined( triggers[ i ].script_exploder) ) + level thread maps\mp\_load::exploder_load( triggers[ i ] ); + } + } + + hurtTriggers = getentarray( "trigger_hurt", "classname" ); + + foreach ( hurtTrigger in hurtTriggers ) + { + hurtTrigger thread hurtPlayersThink(); + } + + thread maps\mp\_animatedmodels::main(); + + // auto-sentry + level._func[ "damagefeedback" ] = maps\mp\gametypes\_damagefeedback::updateDamageFeedback; + level._func[ "setTeamHeadIcon" ] = maps\mp\_entityheadicons::setTeamHeadIcon; + level._laserOn_func = ::laserOn; + level._laserOff_func = ::laserOff; + + // defaults + setDvar( "sm_sunShadowScale", 1 ); + setDvar( "r_specularcolorscale", 2.5 ); + setDvar( "r_diffusecolorscale", 1 ); + setDvar( "r_lightGridEnableTweaks", 0 ); + setDvar( "r_lightGridIntensity", 1 ); + setDvar( "r_lightGridContrast", 0 ); + + level._use_moon_gravity = false; + + //println( "!!!!!Loading Level Resetting Gravity to Earth !!!!!!!!!!!!" ); + setdvar( "phys_global_gravity_scale", 1.0 ); + setdvar( "aim_scale_turn_rate", 1.0 ); + + /# + show_level_notes( true ); + #/ +} + +exploder_load( trigger ) +{ + level endon( "killexplodertridgers" + trigger.script_exploder ); + trigger waittill( "trigger" ); + if ( isdefined( trigger.script_chance ) && randomfloat( 1 ) > trigger.script_chance ) + { + if ( isdefined( trigger.script_delay ) ) + wait trigger.script_delay; + else + wait 4; + level thread exploder_load( trigger ); + return; + } + exploder( trigger.script_exploder ); + level notify( "killexplodertridgers" + trigger.script_exploder ); +} + + +setupExploders() +{ + // Hide exploder models. + ents = getentarray( "script_brushmodel", "classname" ); + smodels = getentarray( "script_model", "classname" ); + for ( i = 0;i < smodels.size;i ++ ) + ents[ ents.size ] = smodels[ i ]; + + for ( i = 0;i < ents.size;i ++ ) + { + if ( isdefined( ents[ i ].script_prefab_exploder ) ) + ents[ i ].script_exploder = ents[ i ].script_prefab_exploder; + + if ( isdefined( ents[ i ].script_exploder ) ) + { + if ( ( ents[ i ].model == "fx" ) && ( ( !isdefined( ents[ i ].targetname ) ) || ( ents[ i ].targetname != "exploderchunk" ) ) ) + ents[ i ] hide(); + else if ( ( isdefined( ents[ i ].targetname ) ) && ( ents[ i ].targetname == "exploder" ) ) + { + ents[ i ] hide(); + ents[ i ] notsolid(); + //if ( isdefined( ents[ i ].script_disconnectpaths ) ) + //ents[ i ] connectpaths(); + } + else if ( ( isdefined( ents[ i ].targetname ) ) && ( ents[ i ].targetname == "exploderchunk" ) ) + { + ents[ i ] hide(); + ents[ i ] notsolid(); + //if ( isdefined( ents[ i ].spawnflags ) && ( ents[ i ].spawnflags & 1 ) ) + //ents[ i ] connectpaths(); + } + } + } + + script_exploders = []; + + potentialExploders = getentarray( "script_brushmodel", "classname" ); + for ( i = 0;i < potentialExploders.size;i ++ ) + { + if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) ) + potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder; + + if ( isdefined( potentialExploders[ i ].script_exploder ) ) + script_exploders[ script_exploders.size ] = potentialExploders[ i ]; + } + + potentialExploders = getentarray( "script_model", "classname" ); + for ( i = 0;i < potentialExploders.size;i ++ ) + { + if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) ) + potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder; + + if ( isdefined( potentialExploders[ i ].script_exploder ) ) + script_exploders[ script_exploders.size ] = potentialExploders[ i ]; + } + + potentialExploders = getentarray( "item_health", "classname" ); + for ( i = 0;i < potentialExploders.size;i ++ ) + { + if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) ) + potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder; + + if ( isdefined( potentialExploders[ i ].script_exploder ) ) + script_exploders[ script_exploders.size ] = potentialExploders[ i ]; + } + + if ( !isdefined( level._createFXent ) ) + level._createFXent = []; + + acceptableTargetnames = []; + acceptableTargetnames[ "exploderchunk visible" ] = true; + acceptableTargetnames[ "exploderchunk" ] = true; + acceptableTargetnames[ "exploder" ] = true; + + for ( i = 0; i < script_exploders.size; i ++ ) + { + exploder = script_exploders[ i ]; + ent = createExploder( exploder.script_fxid ); + ent.v = []; + ent.v[ "origin" ] = exploder.origin; + ent.v[ "angles" ] = exploder.angles; + ent.v[ "delay" ] = exploder.script_delay; + ent.v[ "firefx" ] = exploder.script_firefx; + ent.v[ "firefxdelay" ] = exploder.script_firefxdelay; + ent.v[ "firefxsound" ] = exploder.script_firefxsound; + ent.v[ "firefxtimeout" ] = exploder.script_firefxtimeout; + ent.v[ "earthquake" ] = exploder.script_earthquake; + ent.v[ "damage" ] = exploder.script_damage; + ent.v[ "damage_radius" ] = exploder.script_radius; + ent.v[ "soundalias" ] = exploder.script_soundalias; + ent.v[ "repeat" ] = exploder.script_repeat; + ent.v[ "delay_min" ] = exploder.script_delay_min; + ent.v[ "delay_max" ] = exploder.script_delay_max; + ent.v[ "target" ] = exploder.target; + ent.v[ "ender" ] = exploder.script_ender; + ent.v[ "type" ] = "exploder"; +// ent.v[ "worldfx" ] = true; + if ( !isdefined( exploder.script_fxid ) ) + ent.v[ "fxid" ] = "No FX"; + else + ent.v[ "fxid" ] = exploder.script_fxid; + ent.v[ "exploder" ] = exploder.script_exploder; + assertEx( isdefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" ); + + if ( !isdefined( ent.v[ "delay" ] ) ) + ent.v[ "delay" ] = 0; + + if ( isdefined( exploder.target ) ) + { + org = getent( ent.v[ "target" ], "targetname" ).origin; + ent.v[ "angles" ] = vectortoangles( org - ent.v[ "origin" ] ); +// forward = anglestoforward( angles ); +// up = anglestoup( angles ); + } + + // this basically determines if its a brush / model exploder or not + if ( exploder.classname == "script_brushmodel" || isdefined( exploder.model ) ) + { + ent.model = exploder; + ent.model.disconnect_paths = exploder.script_disconnectpaths; + } + + if ( isdefined( exploder.targetname ) && isdefined( acceptableTargetnames[ exploder.targetname ] ) ) + ent.v[ "exploder_type" ] = exploder.targetname; + else + ent.v[ "exploder_type" ] = "normal"; + + ent common_scripts\_createfx::post_entity_creation_function(); + } +} + +lanterns() +{ + if (!isdefined(level._effect["lantern_light"])) + level._effect["lantern_light"] = loadfx("props/glow_latern"); + + loopfx("lantern_light", self.origin, 0.3, self.origin + (0,0,1)); +} + + +hurtPlayersThink() +{ + level endon ( "game_ended" ); + + wait ( randomFloat( 1.0 ) ); + + for ( ;; ) + { + foreach ( player in level._players ) + { + if ( player isTouching( self ) && isReallyAlive( player ) ) + player _suicide(); + } + + wait ( 0.5 ); + } +} \ No newline at end of file diff --git a/maps/mp/_matchdata.gsc b/maps/mp/_matchdata.gsc new file mode 100644 index 0000000..91277f9 --- /dev/null +++ b/maps/mp/_matchdata.gsc @@ -0,0 +1,374 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +init() +{ + if ( !isDefined( game["gamestarted"] ) ) + { + //setMatchDataDef( "mp/matchdata_" + level.gametype + ".def" ); + setMatchDataDef( "mp/matchdata.def" ); + setMatchData( "map", level._script ); + setMatchData( "gametype", level._gametype ); + setMatchData( "buildVersion", getBuildVersion() ); + setMatchData( "buildNumber", getBuildNumber() ); + setMatchData( "dateTime", getSystemTime() ); + } + + level._MaxLives = 250; // must match MaxKills in matchdata definition + level._MaxNameLength = 21; // must match Player xuid size in clientmatchdata definition + level._MaxEvents = 150; + level._MaxKillstreaks = 125; + level._MaxLogClients = 128; + + level thread gameEndListener(); +} + + +logKillstreakEvent( event, position ) +{ + assertEx( isPlayer( self ), "self is not a player: " + self.code_classname ); + + if ( !matchMakingGame() || !canLogClient( self ) || !canLogKillstreak() ) + return; + + eventId = getMatchData( "killstreakCount" ); + setMatchData( "killstreakCount", eventId+1 ); + + setMatchData( "killstreaks", eventId, "eventType", event ); + setMatchData( "killstreaks", eventId, "player", self.clientid ); + setMatchData( "killstreaks", eventId, "eventTime", getTime() ); + setMatchData( "killstreaks", eventId, "eventPos", 0, int( position[0] ) ); + setMatchData( "killstreaks", eventId, "eventPos", 1, int( position[1] ) ); + setMatchData( "killstreaks", eventId, "eventPos", 2, int( position[2] ) ); +} + + +logGameEvent( event, position ) +{ + assertEx( isPlayer( self ), "self is not a player: " + self.code_classname ); + + if ( !matchMakingGame() || !canLogClient( self ) || !canLogEvent() ) + return; + + eventId = getMatchData( "eventCount" ); + setMatchData( "eventCount", eventId+1 ); + + setMatchData( "events", eventId, "eventType", event ); + setMatchData( "events", eventId, "player", self.clientid ); + setMatchData( "events", eventId, "eventTime", getTime() ); + setMatchData( "events", eventId, "eventPos", 0, int( position[0] ) ); + setMatchData( "events", eventId, "eventPos", 1, int( position[1] ) ); + setMatchData( "events", eventId, "eventPos", 2, int( position[2] ) ); +} + + +logKillEvent( lifeId, eventRef ) +{ + if ( !matchMakingGame() || !canLogLife( lifeId ) ) + return; + + setMatchData( "lives", lifeId, "modifiers", eventRef, true ); +} + + +logMultiKill( lifeId, multikillCount ) +{ + if ( !matchMakingGame() || !canLogLife( lifeId ) ) + return; + + setMatchData( "lives", lifeId, "multikill", multikillCount ); +} + + +logPlayerLife( lifeId ) +{ + if ( !matchMakingGame() || !canLogClient( self ) || !canLogLife( lifeId ) ) + return; + + setMatchData( "lives", lifeId, "player", self.clientid ); + setMatchData( "lives", lifeId, "spawnPos", 0, int( self.spawnPos[0] ) ); + setMatchData( "lives", lifeId, "spawnPos", 1, int( self.spawnPos[1] ) ); + setMatchData( "lives", lifeId, "spawnPos", 2, int( self.spawnPos[2] ) ); + setMatchData( "lives", lifeId, "wasTacticalInsertion", self.wasTI ); + setMatchData( "lives", lifeId, "team", self.team ); + setMatchData( "lives", lifeId, "spawnTime", self.spawnTime ); + setMatchData( "lives", lifeId, "duration", getTime() - self.spawnTime ); + + self logLoadout( lifeId ); +} + + +logLoadout( lifeId ) +{ + if ( !matchMakingGame() || !canLogClient( self ) || !canLogLife( lifeId ) ) + return; + + class = self.curClass; + + if ( class == "copycat" ) + { + clonedLoadout = self.pers["copyCatLoadout"]; + + loadoutPrimary = clonedLoadout["loadoutPrimary"]; + loadoutPrimaryAttachment = clonedLoadout["loadoutPrimaryAttachment"]; + loadoutPrimaryAttachment2 = clonedLoadout["loadoutPrimaryAttachment2"] ; + loadoutPrimaryCamo = clonedLoadout["loadoutPrimaryCamo"]; + loadoutSecondary = clonedLoadout["loadoutSecondary"]; + loadoutSecondaryAttachment = clonedLoadout["loadoutSecondaryAttachment"]; + loadoutSecondaryAttachment2 = clonedLoadout["loadoutSecondaryAttachment2"]; + loadoutSecondaryCamo = clonedLoadout["loadoutSecondaryCamo"]; + loadoutLethal = clonedLoadout["loadoutLethal"]; + loadoutEquipment = clonedLoadout["loadoutEquipment"]; + loadoutPerk1 = clonedLoadout["loadoutPerk1"]; + loadoutPerk2 = clonedLoadout["loadoutPerk2"]; + loadoutPerk3 = clonedLoadout["loadoutPerk3"]; + loadoutOffhand = clonedLoadout["loadoutOffhand"]; + loadoutDeathStreak = "specialty_copycat"; + } + else if( isSubstr( class, "custom" ) ) + { + class_num = maps\mp\gametypes\_class::getClassIndex( class ); + + loadoutPrimary = maps\mp\gametypes\_class::cac_getWeapon( class_num, 0 ); + loadoutPrimaryAttachment = maps\mp\gametypes\_class::cac_getWeaponAttachment( class_num, 0 ); + loadoutPrimaryAttachment2 = maps\mp\gametypes\_class::cac_getWeaponAttachmentTwo( class_num, 0 ); + + loadoutSecondary = maps\mp\gametypes\_class::cac_getWeapon( class_num, 1 ); + loadoutSecondaryAttachment = maps\mp\gametypes\_class::cac_getWeaponAttachment( class_num, 1 ); + loadoutSecondaryAttachment2 = maps\mp\gametypes\_class::cac_getWeaponAttachmentTwo( class_num, 1 ); + + loadoutOffhand = maps\mp\gametypes\_class::cac_getOffhand( class_num ); + + loadoutLethal = maps\mp\gametypes\_class::cac_getPerk( class_num, 0 ); + loadoutEquipment = maps\mp\gametypes\_class::cac_getPerk( class_num, 7 ); + loadoutPerk1 = maps\mp\gametypes\_class::cac_getPerk( class_num, 1 ); + loadoutPerk2 = maps\mp\gametypes\_class::cac_getPerk( class_num, 2 ); + loadoutPerk3 = maps\mp\gametypes\_class::cac_getPerk( class_num, 3 ); + } + else + { + class_num = maps\mp\gametypes\_class::getClassIndex( class ); + + loadoutPrimary = maps\mp\gametypes\_class::table_getWeapon( level._classTableName, class_num, 0 ); + loadoutPrimaryAttachment = maps\mp\gametypes\_class::table_getWeaponAttachment( level._classTableName, class_num, 0 , 0); + loadoutPrimaryAttachment2 = maps\mp\gametypes\_class::table_getWeaponAttachment( level._classTableName, class_num, 0, 1 ); + + loadoutSecondary = maps\mp\gametypes\_class::table_getWeapon( level._classTableName, class_num, 1 ); + loadoutSecondaryAttachment = maps\mp\gametypes\_class::table_getWeaponAttachment( level._classTableName, class_num, 1 , 0); + loadoutSecondaryAttachment2 = maps\mp\gametypes\_class::table_getWeaponAttachment( level._classTableName, class_num, 1, 1 );; + + loadoutOffhand = maps\mp\gametypes\_class::table_getOffhand( level._classTableName, class_num ); + + loadoutLethal = maps\mp\gametypes\_class::table_getLethal( level._classTableName, class_num, 0 ); + loadoutEquipment = maps\mp\gametypes\_class::table_getEquipment( level._classTableName, class_num, 7 ); + loadoutPerk1 = maps\mp\gametypes\_class::table_getPerk( level._classTableName, class_num, 1 ); + loadoutPerk2 = maps\mp\gametypes\_class::table_getPerk( level._classTableName, class_num, 2 ); + loadoutPerk3 = maps\mp\gametypes\_class::table_getPerk( level._classTableName, class_num, 3 ); + } + + setMatchData( "lives", lifeId, "primaryWeapon", loadoutPrimary ); + setMatchData( "lives", lifeId, "primaryAttachments", 0, loadoutPrimaryAttachment ); + setMatchData( "lives", lifeId, "primaryAttachments", 1, loadoutPrimaryAttachment2 ); + + setMatchData( "lives", lifeId, "secondaryWeapon", loadoutSecondary ); + setMatchData( "lives", lifeId, "secondaryAttachments", 0, loadoutSecondaryAttachment ); + setMatchData( "lives", lifeId, "secondaryAttachments", 1, loadoutSecondaryAttachment ); + + setMatchData( "lives", lifeId, "offhandWeapon", loadoutOffhand ); + + setMatchData( "lives", lifeId, "equipment", loadoutEquipment ); + setMatchData( "lives", lifeId, "lethal", loadoutLethal ); + setMatchData( "lives", lifeId, "perks", 0, loadoutPerk1 ); + setMatchData( "lives", lifeId, "perks", 1, loadoutPerk2 ); + setMatchData( "lives", lifeId, "perks", 2, loadoutPerk3 ); +} + + +logPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc ) +{ + if ( !matchMakingGame() || !canLogClient( self ) || ( isPlayer( attacker ) && !canLogClient( attacker ) ) || !canLogLife( lifeId ) ) + return; + + if ( lifeId >= level._MaxLives ) + return; + + if( !isDefined( sWeapon )) + { + sWeapon = "none"; + } + + if ( sWeapon == "none" ) + { + sWeaponType = "none"; + sWeaponClass = "none"; + } + else + { + sWeaponType = weaponInventoryType( sWeapon ); + sWeaponClass = weaponClass( sWeapon ); + } + + if ( isDefined( sWeaponType ) && (sWeaponType == "primary" || sWeaponType == "altmode") && (sWeaponClass == "pistol" || sWeaponClass == "smg" || sWeaponClass == "rifle" || sWeaponClass == "spread" || sWeaponClass == "mg" || sWeaponClass == "grenade" || sWeaponClass == "rocketlauncher" || sWeaponClass == "sniper") ) + { + sWeaponOriginal = undefined; + + if ( sWeaponType == "altmode" ) + { + sWeaponOriginal = sWeapon; + sWeapon = sPrimaryWeapon; + + setMatchData( "lives", lifeId, "altMode", true ); + } + + weaponTokens = strTok( sWeapon, "_" ); + + /# + if ( !(weaponTokens.size > 1 && weaponTokens.size <= 4) ) + { + PrintLn( "attacker: ", attacker ); + PrintLn( "iDamage: ", iDamage ); + PrintLn( "sMeansOfDeath: ", sMeansOfDeath ); + + if ( isDefined( sWeaponOriginal ) ) + PrintLn( "sWeaponOriginal: ", sWeaponOriginal ); + + PrintLn( "sWeapon: ", sWeapon ); + PrintLn( "sPrimaryWeapon: ", sPrimaryWeapon ); + PrintLn( "--------------------------------" ); + PrintLn( "sWeaponType: ", sWeaponType ); + PrintLn( "sWeaponClass: ", sWeaponClass ); + PrintLn( "--------------------------------" ); + PrintLn( "weaponTokens.size: ", weaponTokens.size ); + + tokenCount = 0; + foreach ( token in weaponTokens ) + { + PrintLn( "weaponTokens[", tokenCount, "]: ", weaponTokens[tokenCount] ); + tokenCount++; + } + } + #/ + assert( weaponTokens.size > 1 && weaponTokens.size <= 4 ); + + assertEx( weaponTokens[weaponTokens.size - 1] == "mp", "weaponTokens[weaponTokens.size - 1]: " + weaponTokens[weaponTokens.size - 1] ); + weaponTokens[weaponTokens.size - 1] = undefined; // remove the trailing "mp" + + setMatchData( "lives", lifeId, "weapon", weaponTokens[0] ); + + //TagZP weapon sharing between mp and sp is looking more and more like a bad idea. atbr_detonate as a primary tries to pass + //"detonate" as the attachmant name... + if( weaponTokens[0] != "atbr" && weaponTokens[0] != "miniuav" ) + { + if ( isDefined( weaponTokens[1] ) ) + setMatchData( "lives", lifeId, "attachments", 0, weaponTokens[1] ); + + if ( isDefined( weaponTokens[2] ) ) + setMatchData( "lives", lifeId, "attachments", 1, weaponTokens[2] ); + } + } + else if ( sWeaponType == "item" || sWeaponType == "offhand" ) + { + weaponName = strip_suffix( sWeapon, "_mp" ); + setMatchData( "lives", lifeId, "weapon", weaponName ); + } + else + { + setMatchData( "lives", lifeId, "weapon", sWeapon ); + } + + if ( isKillstreakWeapon( sWeapon ) ) + setMatchData( "lives", lifeId, "modifiers", "killstreak", true ); + + setMatchData( "lives", lifeId, "mod", sMeansOfDeath ); + if ( isPlayer( attacker ) ) + { + setMatchData( "lives", lifeId, "attacker", attacker.clientid ); + setMatchData( "lives", lifeId, "attackerPos", 0, int( attacker.origin[0] ) ); + setMatchData( "lives", lifeId, "attackerPos", 1, int( attacker.origin[1] ) ); + setMatchData( "lives", lifeId, "attackerPos", 2, int( attacker.origin[2] ) ); + + victimForward = anglesToForward( (0,self.angles[1],0) ); + attackDirection = (self.origin - attacker.origin); + attackDirection = VectorNormalize( (attackDirection[0], attackDirection[1], 0) ); + setMatchData( "lives", lifeId, "dotOfDeath", VectorDot( victimForward, attackDirection ) ); + } + else + { + // 255 is world + setMatchData( "lives", lifeId, "attacker", 255 ); + setMatchData( "lives", lifeId, "attackerPos", 0, int( self.origin[0] ) ); + setMatchData( "lives", lifeId, "attackerPos", 1, int( self.origin[1] ) ); + setMatchData( "lives", lifeId, "attackerPos", 2, int( self.origin[2] ) ); + } + + setMatchData( "lives", lifeId, "player", self.clientid ); + setMatchData( "lives", lifeId, "deathPos", 0, int( self.origin[0] ) ); + setMatchData( "lives", lifeId, "deathPos", 1, int( self.origin[1] ) ); + setMatchData( "lives", lifeId, "deathPos", 2, int( self.origin[2] ) ); + + setMatchData( "lives", lifeId, "deathAngles", 0, int( self.angles[0] ) ); + setMatchData( "lives", lifeId, "deathAngles", 1, int( self.angles[1] ) ); + setMatchData( "lives", lifeId, "deathAngles", 2, int( self.angles[2] ) ); +} + + +logPlayerData() +{ + if ( !matchMakingGame() || !canLogClient( self ) ) + return; + + setMatchData( "players", self.clientid, "score", self getPersStat( "score" ) ); + setMatchData( "players", self.clientid, "assists", self getPersStat( "assists" ) ); + setMatchData( "players", self.clientid, "checkpoints", self getPersStat( "checkpoints" ) ); + setMatchData( "players", self.clientid, "longestStreak", self getPersStat( "longestStreak" ) ); +} + + +// log the lives of players who are still alive at match end. +gameEndListener() +{ + if ( !matchMakingGame() ) + return; + + level waittill ( "game_ended" ); + + setMatchData( "gameLength", int( getTimePassed() ) ); + + foreach ( player in level._players ) + { + if ( player.team != "allies" && player.team != "axis" ) + continue; + + player logPlayerData(); + + if ( !isAlive( player ) ) + continue; + + lifeId = getNextLifeId(); + player logPlayerLife( lifeId ); + } +} + + + +canLogClient( client ) +{ + assertEx( isPlayer( client ) , "Client is not a player: " + client.code_classname ); + return ( client.clientid < level._MaxLogClients ); +} + +canLogEvent() +{ + return ( getMatchData( "eventCount" ) < level._MaxEvents ); +} + +canLogKillstreak() +{ + return ( getMatchData( "killstreakCount" ) < level._MaxKillstreaks ); +} + +canLogLife( lifeId ) +{ + return ( getMatchData( "lifeCount" ) < level._MaxLives ); +} \ No newline at end of file diff --git a/maps/mp/_minefields.gsc b/maps/mp/_minefields.gsc new file mode 100644 index 0000000..35159de --- /dev/null +++ b/maps/mp/_minefields.gsc @@ -0,0 +1,50 @@ +minefields() +{ + minefields = getentarray("minefield", "targetname"); + if (minefields.size > 0) + { + level._effect["mine_explosion"] = loadfx ("explosions/grenadeExp_dirt"); + } + + for(i = 0; i < minefields.size; i++) + { + minefields[i] thread minefield_think(); + } +} + +minefield_think() +{ + while (1) + { + self waittill ("trigger",other); + + if(isPlayer(other)) + other thread minefield_kill(self); + } +} + +minefield_kill(trigger) +{ + if(isDefined(self.minefield)) + return; + + self.minefield = true; + self playsound ("minefield_click"); + + wait(.5); + wait(randomFloat(.5)); + + if(isdefined(self) && self istouching(trigger)) + { + origin = self getorigin(); + range = 300; + maxdamage = 2000; + mindamage = 50; + + self playsound("explo_mine"); + playfx(level._effect["mine_explosion"], origin); + radiusDamage(origin, range, maxdamage, mindamage); + } + + self.minefield = undefined; +} diff --git a/maps/mp/_moon_mp.gsc b/maps/mp/_moon_mp.gsc new file mode 100644 index 0000000..eac9597 --- /dev/null +++ b/maps/mp/_moon_mp.gsc @@ -0,0 +1,70 @@ +//TagZP We want this to do the same thing that the sp setup does. If any of these commented out +//tweak values are changed move them into constatns so both sp and mp has access. + +main() +{ + //gravity_scale = common_scripts\_moon::getMoonGlobalGravityScale(); + turn_scale = 1.0; //common_scripts\_moon::getMoonGlobalTurnRateScale(); + ads_yaw = common_scripts\_moon::getMoonGlobalADSYaw(); + ads_pitch = common_scripts\_moon::getMoonGlobalADSPitch(); + //moongrav = getdvarint( "player_moon_grav_scale" ); + + //println( "!!!!!setting global gravity scale!!!!!!!!!!!!" ); + setdvar( "phys_global_gravity_scale", 0.25 ); + setdvar( "aim_scale_turn_rate", turn_scale ); + setdvar( "aim_turnrate_pitch_ads", ads_pitch); + setdvar( "aim_turnrate_yaw_ads", ads_yaw); + + level._use_moon_gravity = true; + + //these values can be changed to effect the way in which the player behaves in gravity. + //Setting values to 1.0 will make them behave like on earth. I've given them values here + //of their defaults, ones that seemed correct for me. They will have no effect without + //the below call to SetMoonGravity as they are only used in the player movement code. + //These shouldn't stay dvars, but become #define once we're happy with them. + //setdvar( "player_moon_grav_stop_scalar", "0.20"); + //setdvar( "player_moon_grav_start_scalar", "0.20"); + //setdvar( "player_moon_grav_speed_scalar", "0.65"); + + //These values effect the way in which the player rig behaves in moon gravity. + //Larger vertical bob amplitude will cause the player to bob higher in their steps. + //Larger horizontal bob amplitude will give the impression of more sway in the walk. + //Smaller bob speeds will decrease how quickly the player rig bob cycles, not the actual movement speed. + //They will have no effect without the below call to SetMoonGravity as they are + //only used in the player movement code. + //These shouldn't stay dvars, but become #define once we're happy with them. + //setdvar( "weapon_view_moon_vertical_bob_amp", "4.0" ); + //setdvar( "weapon_view_moon_horizontal_bob_amp", "1.5" ); + //setdvar( "weapon_view_moon_bob_speed", "0.5" ); + + //This value effects the overall height of the jump. Adding in variable jump height, I had to suppress some of + //jump height because it was getting too high. + //setdvar( "player_moon_grav_variable_jump_scalar", "0.2" ); +} + +init_moon_player() +{ + if( isDefined( level._use_moon_gravity )) + { + if( level._use_moon_gravity == true ) + { + //println( "!!!!!setting player moon gravity!!!!!!!!!!!!" ); + self SetMoonGravity( true ); + self EnableMoonHelmetHUD(); + + maps\mp\perks\_perks::givePerk( "specialty_moonsuit" ); + } + else + { + //println( "!!!!!setting player Earth gravity!!!!!!!!!!!!" ); + self SetMoonGravity( false ); + self DisableMoonHelmetHud(); + } + } + else + { + //println( "!!!!!setting player Earth gravity!!!!!!!!!!!!" ); + self SetMoonGravity( false ); + self DisableMoonHelmetHud(); + } +} \ No newline at end of file diff --git a/maps/mp/_mp_trophy_turret.gsc b/maps/mp/_mp_trophy_turret.gsc new file mode 100644 index 0000000..8c72cbd --- /dev/null +++ b/maps/mp/_mp_trophy_turret.gsc @@ -0,0 +1,226 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +//******************************************************************* +// * +// * +//******************************************************************* +// Min distance to start to track projectile. +CONST_TROPHY_MAX_TRACK_DISTANCE = 500; +CONST_MAX_TRACK_TIME_MS = 500; +TROPHY_SOUND_AFTER_COOLDOWN = "weap_recharge_stop"; +TROPHY_RELOAD_TIME_SEC = 3.0; +TROPHY_ACTIVE_RADIUS = 400.0; +TROPHY_INACTIVE_RADIUS = 200.0; +TROPHY_TABLE_FILE = "mp/trophyTable.csv"; + +//******************************************************************* +// * +// * +//******************************************************************* +find_closest_projectile( pos, current_projectile, friendlyTeam ) +{ + projectiles = GetEntArray( "grenade", "classname" ); + + // Is there a better way to do this? + rockets = GetEntArray( "rocket", "classname" ); + foreach ( ent in rockets ) + { + projectiles[ projectiles.size ] = ent; + } + + min_distance = 999999999999999.0; + return_obj = undefined; + + // First check for the current projectile. + if ( isdefined( current_projectile )) + { + foreach ( ent in projectiles ) + { + if ( current_projectile == ent ) + { + return_obj = ent; + break; + } + } + } + + // No dice, find a new one by range. + if ( !isdefined( return_obj )) + { + + foreach ( ent in projectiles ) + { + team = ent MissileGetTeam(); + if ( "invalid" == team ) + { + // projectiles from vehicles fall under "invalid", so we'll check the team of their owner + team = ent VehicleMissleGetTeam(); + } + + // team check + if( isDefined( friendlyTeam )) + { + if( team == friendlyTeam ) + { + continue; + } + } + + if( isDefined( ent.type )) + { + if( ent.type == "remote" ) + { + // remote missile, those are ok + continue; + } + } + + // Distance. + d = DistanceSquared( ent.origin, pos ); + if ( d < min_distance ) + { + min_distance = d; + return_obj = ent; + } + } + } + + return return_obj; +} + + + +//******************************************************************* +// * +// * +//******************************************************************* +trophy_turret_update() +{ + // Exit cases. + self endon( "death" ); + + // Locals. + soundEnt = self; + turret = self.trophy_turret; + if( isDefined( turret )) + { + soundEnt = turret; + } + + soundorg = Spawn( "script_origin", soundEnt.origin ); + soundorg LinkTo( soundEnt ); + + projectile = undefined; + + tracked_time = 0; + self.trophyLastFireTime = 0; + + // Think. + for( ;; ) + { + wait( 0.05 ); + //println( "update" ); + friendlyTeam = undefined; + // this is a escort plus check + if( isDefined( self.curr_owner )) + { + // if the current owner is neutral, trophy system is off + if( self.curr_owner == "neutral" ) + { + continue; + } + + if( isDefined( game[self.curr_owner] )) + { + friendlyTeam = game[self.curr_owner]; + } + } + else + { + friendlyTeam = self.owner.team; + } + + //println( "friendly team is ", friendlyTeam ); + + // Get target. + prev = projectile; + projectile = find_closest_projectile( self.origin, projectile, friendlyTeam ); + + if ( isdefined( projectile )) + { + //println( "got projectile" ); + distance_squared = DistanceSquared( projectile.origin, self.origin ); + if ( distance_squared < ( CONST_TROPHY_MAX_TRACK_DISTANCE * CONST_TROPHY_MAX_TRACK_DISTANCE )) + { + canFire = false; + if( TROPHY_RELOAD_TIME_SEC * 1000 < getTime() - self.trophyLastFireTime ) + { + canFire = true; + } + inRange = false; + if( distance_squared < TROPHY_ACTIVE_RADIUS * TROPHY_ACTIVE_RADIUS ) + { + if( distance_squared > TROPHY_INACTIVE_RADIUS * TROPHY_INACTIVE_RADIUS ) + { + inRange = true; + } + } + + if( canFire && inRange ) + { + weaponName = projectile getWeaponName(); + if( !canGoThroughTrophy ( weaponName, "ugv" )) + { + //projectile MissileTryTrophyExplode( self ); + self notify( "trophy_kill_projectile", TROPHY_RELOAD_TIME_SEC ); + self.trophyLastFireTime = getTime(); + PlayFX ( level._effect[ "trophy_explosion" ], projectile.origin ); + projectile delete(); + projectile = undefined; + self PlaySound( TROPHY_SOUND_AFTER_COOLDOWN ); + } + } + } + else + { +// println( "not close enough... dsqr ", distance_squared, " ", projectile.origin, " ", self.origin ); + } + } + else + { + if( isDefined( turret )) + { + turret ClearTargetEntity(); + } + } + } +} + +canGoThroughTrophy ( weaponName, type ) +{ + index = undefined; + switch ( type ) + { + case "suit": + index = 2; + break; + case "ugv": + index = 3; + break; + default: + assertMsg( "Invalid trophy type. Must be either 'suit' or 'ugv'" ); + } + + result = tablelookup( TROPHY_TABLE_FILE, 1, weaponName, index ); + + if ( result == "1") + { + return true; + } + else + { + return false; + } +} \ No newline at end of file diff --git a/maps/mp/_radiation.gsc b/maps/mp/_radiation.gsc new file mode 100644 index 0000000..4e63b9c --- /dev/null +++ b/maps/mp/_radiation.gsc @@ -0,0 +1,227 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +radiation() +{ + precacheString( &"SCRIPT_RADIATION_DEATH" ); + radiationFields = getentarray("radiation", "targetname"); + + if (radiationFields.size > 0) + { + + precacheshellshock( "mp_radiation_low" ); + precacheshellshock( "mp_radiation_med" ); + precacheshellshock( "mp_radiation_high" ); + + foreach ( trigger in radiationFields ) + trigger thread common_scripts\_dynamic_world::triggerTouchThink( ::playerEnterArea, ::playerLeaveArea ); + + thread onPlayerConnect(); + } + +} + +onPlayerConnect() +{ + for ( ;; ) + { + level waittill ( "connected", player ); + player.numAreas = 0; + } +} + +playerEnterArea( trigger ) +{ + self.numAreas++; + + if ( self.numAreas == 1 ) + self radiationEffect(); +} + + +playerLeaveArea( trigger ) +{ + self.numAreas--; + assert( self.numAreas >= 0 ); + + if ( self.numAreas != 0 ) + return; + + self.poison = 0; + self notify( "leftTrigger"); + + if ( isDefined( self.radiationOverlay ) ) + self.radiationOverlay fadeoutBlackOut( .10, 0 ); +} + +soundWatcher( soundOrg ) +{ + self waittill_any( "death", "leftTrigger" ); + + self stopLoopSound(); +} + +radiationEffect() +{ + self endon( "disconnect" ); + self endon( "game_ended" ); + self endon( "death" ); + self endon( "leftTrigger" ); + + self.poison = 0; + self thread soundWatcher( self ); + + while (1) + { + self.poison ++; + + switch( self.poison ) + { + case 1: + self.radiationSound = "item_geigercouner_level2"; + self playLoopSound( self.radiationSound ); + self ViewKick( 1, self.origin ); + break; + case 3: + self shellshock( "mp_radiation_low", 4); + self.radiationSound = "item_geigercouner_level3"; + self stopLoopSound(); + self playLoopSound( self.radiationSound ); + self ViewKick( 3, self.origin ); + self doRadiationDamage(15); + break; + case 4: + self shellshock( "mp_radiation_med", 5); + self.radiationSound = "item_geigercouner_level3"; + self stopLoopSound(); + self playLoopSound( self.radiationSound ); + self ViewKick( 15, self.origin ); + self thread blackout(); + self doRadiationDamage(25); + break; + case 6: + self shellshock( "mp_radiation_high", 5); + self.radiationSound = "item_geigercouner_level4"; + self stopLoopSound(); + self playLoopSound( self.radiationSound ); + self ViewKick( 75, self.origin ); + self doRadiationDamage(45); + break; + case 8: + self shellshock( "mp_radiation_high", 5); + self.radiationSound = "item_geigercouner_level4"; + self stopLoopSound(); + self playLoopSound( self.radiationSound ); + self ViewKick( 127, self.origin ); + self doRadiationDamage(175); + + break; + } + wait(1); + } + wait(5); +} +blackout( ) +{ + self endon( "disconnect" ); + self endon( "game_ended" ); + self endon( "death" ); + self endon( "leftTrigger" ); + + if ( !isDefined( self.radiationOverlay ) ) + { + self.radiationOverlay = newClientHudElem( self ); + self.radiationOverlay.x = 0; + self.radiationOverlay.y = 0; + self.radiationOverlay setshader( "black", 640, 480 ); + self.radiationOverlay.alignX = "left"; + self.radiationOverlay.alignY = "top"; + self.radiationOverlay.horzAlign = "fullscreen"; + self.radiationOverlay.vertAlign = "fullscreen"; + self.radiationOverlay.alpha = 0; + } + + min_length = 1; + max_length = 2; + min_alpha = .25; + max_alpha = 1; + + min_percent = 5; + max_percent = 100; + + fraction = 0; + + for ( ;; ) + { + while ( self.poison > 1 ) + { + percent_range = max_percent - min_percent; + fraction = ( self.poison - min_percent ) / percent_range; + + if ( fraction < 0 ) + fraction = 0; + else if ( fraction > 1 ) + fraction = 1; + + length_range = max_length - min_length; + length = min_length + ( length_range * ( 1 - fraction ) ); + + alpha_range = max_alpha - min_alpha; + alpha = min_alpha + ( alpha_range * fraction ); + + end_alpha = fraction * 0.5; + + if ( fraction == 1 ) + break; + + duration = length / 2; + + self.radiationOverlay fadeinBlackOut( duration, alpha ); + self.radiationOverlay fadeoutBlackOut( duration, end_alpha); + + // wait a variable amount based on self.radiation.totalpercent, this is the space in between pulses + //wait 1; + wait( fraction * 0.5 ); + } + + if ( fraction == 1 ) + break; + + if ( self.radiationOverlay.alpha != 0 ) + self.radiationOverlay fadeoutBlackOut( 1, 0); + + wait 0.05; + } + self.radiationOverlay fadeinBlackOut( 2, 0); +} + +doRadiationdamage( iDamage ) +{ + + self thread [[ level._callbackPlayerDamage ]]( + self,// eInflictor The entity that causes the damage.( e.g. a turret ) + self,// eAttacker The entity that is attacking. + iDamage,// iDamage Integer specifying the amount of damage done + 0,// iDFlags Integer specifying flags that are to be applied to the damage + "MOD_SUICIDE",// sMeansOfDeath Integer specifying the method of death + "claymore_mp",// sWeapon The weapon number of the weapon used to inflict the damage + self.origin,// vPoint The point the damage is from? + ( 0,0,0 ) - self.origin,// vDir The direction of the damage + "none",// sHitLoc The location of the hit + 0// psOffsetTime The time offset for the damage + ); +} + +fadeinBlackOut( duration, alpha ) +{ + self fadeOverTime( duration ); + self.alpha = alpha; + wait duration; +} + +fadeoutBlackOut( duration, alpha ) +{ + self fadeOverTime( duration ); + self.alpha = alpha; + wait duration; +} \ No newline at end of file diff --git a/maps/mp/_remotedog.gsc b/maps/mp/_remotedog.gsc new file mode 100644 index 0000000..7188ace --- /dev/null +++ b/maps/mp/_remotedog.gsc @@ -0,0 +1,770 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +DOG_TIMEOUT_SEC = 45; +DOG_HUD_TIMER_POS_X = 0; +DOG_HUD_TIMER_POS_Y = -35; +DOG_TURRET_MAX_TARGETING_RANGE = 600; // 45 feet +DOG_TURRET_SPAWN_GRACE_TIME = 3; // dog wont shoot any anyone who hasn't been spawned for 3 seconds +DOG_TURRET_MIN_SHOTS = 10; // minimum shots to fire at a player +DOG_TURRET_MAX_SHOTS = 20; // maximum shots to fire at a player +DOG_TURRET_FIRE_DELAY = .1; // how long to wait between shots at a target +DOG_TURRET_MIN_BARRAGE_DELAY = 0; // how long to wait between firing bursts of shots at a target +DOG_TURRET_MAX_BARRAGE_DELAY = .1; // how long between burts of shots +DOG_TURRET_MAX_YAW = 60; // how far the turret can turn from the dogs centerline + +//******************************************************************* +// * +// * +//******************************************************************* + +init() +{ + level._killstreakFuncs["remote_dog"] = ::tryRemoteDog; + level._remoteDogVehicleInfo = "PROTO_nx_remote_dog_play_mp"; + level._remoteDogVehicleModel = "prototype_vehicle_remotedog_vehicle"; // "defaultvehicle" + level._remoteDogScriptModel = "prototype_vehicle_remotedog"; + level._remoteDogMoveAnim = "german_shepherd_run"; + level._remoteDogIdleAnim = "german_shepherd_idle"; + level._remoteDogTranProp = "miniuav_transition_prop"; + level._remoteDogTurretInfo = "proto_robot_dog_turret_mp"; + level._remoteDogTurretModel = "proto_remotedog_turret"; + level._remoteDogFOV = 120; + level._remoteDogHealth = 200; + level._remoteDogAmmo = 100; + level._remoteDogFireRate = 1; // in tenths of a second, so 10 is fires once a second + level._remoteDogCrossHair = "ac130_overlay_25mm"; + + PreCacheItem( level._remoteDogTranProp ); + precacheString( &"NX_MINIUAV_USE_DRONE" ); + PreCacheShader( "ac130_overlay_grain" ); + PreCacheShader( level._remoteDogCrossHair ); + + precacheVehicle( level._remoteDogVehicleInfo ); + precacheModel( level._remoteDogVehicleModel ); + precacheMpAnim( level._remoteDogMoveAnim ); + precacheMpAnim( level._remoteDogIdleAnim ); + precacheModel( level._remoteDogScriptModel ); + precacheTurret( level._remoteDogTurretInfo ); + precacheModel( level._remoteDogTurretModel ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogDebugPrint( msg ) +{ + IPrintLnBold( msg ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +tryRemoteDog( lifeId ) +{ + self thread remoteDogStartup(); // Kick of main UAV loop. + msg = self waittill_any_return( "death", "cleanup_remote_dog" ); // Wait for death or timeout. + + if( msg == "cleanup_remote_dog" ) + { + // Wait for weapon transition to happen. + wait 2.0; + } + + return true; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogPlayerEventListenerThread() +{ + self waittill( "exit_remote_dog" ); + self.remotedog notify( "exit_remote_dog" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogStartup() +{ + self endon( "death" ); + self endon( "remote_dog_time_is_up" ); + self endon( "remote_dog_out_of_ammo" ); + +// self NotifyOnPlayerCommand( "switch_to_remote_dog", "+actionslot 4" ); + + self DisableOffhandWeapons(); + self._dogPlayerOrigin = self GetOrigin(); + self._dogPlayerAngles = self GetPlayerAngles(); + + // Wait for transition anim to finish. + wait 1.75; + + // Enter the Dawg. + pos = self._dogPlayerOrigin + ( 0, 0, 50 ); + + // setup vehicle + self.remotedog = spawnVehicle( level._remoteDogVehicleModel, "test_dog", level._remoteDogVehicleInfo, pos, self._dogPlayerAngles ); + self.remotedog.health = level._remoteDogHealth; + self.remotedog.maxhealth = self.remotedog.health; + self.remotedog setCanDamage( true ); + self.remotedog.owner = self; + self.remotedog.team = self.team; + self.remotedog.ammo = level._remoteDogAmmo; + self.remotedog.fireRate = level._remoteDogFireRate; + self.remotedog.damageCallback = ::Callback_DogDamage; + // hide the remote dog, we're going to attach another model to it + self.remotedog Hide(); + + // setup dog model + self.remotedog.remoteDogModel = spawn( "script_model", pos ); + self.remotedog.remoteDogModel.owner = self; + self.remotedog.remoteDogModel setModel( level._remoteDogScriptModel ); + self.remotedog.remoteDogModel ScriptModelPlayAnim( level._remoteDogIdleAnim ); + self.remotedog.remoteDogModel.angles = self._dogPlayerAngles; + self.remotedog.currAnim = level._remoteDogIdleAnim; + self.remotedog.remoteDogModel linkto( self.remotedog ); + + // setup hud and stuff + self.remotedog notify( "stop_turret_shoot" ); + self.in_dog = true; + self thread remotedogHud(); + self CameraLinkTo( self.remotedog, "tag_player" ); + self.remote_dog_orig_fov = GetDvarFloat( "cg_fov" ); + self setClientDvar( "cg_fov", level._remoteDogFOV ); + self ThermalVisionFOFOverlayOn(); + self visionSetNakedForPlayer( "cheat_bw", 0 ); + + // create the turret for the dawg + turretPoint = self.remotedog getTagOrigin( "TAG_TURRET" ); + self.remotedog.turret = spawnTurret( "misc_turret", turretPoint, level._remoteDogTurretInfo ); + self.remotedog.turret linkTo( self.remotedog, "TAG_TURRET", (0,0,0), (0,0,0) ); + self.remotedog.turret setModel( level._remoteDogTurretModel ); + self.remotedog.turret.angles = self.remotedog.angles; + self.remotedog.turret.owner = self.remotedog.owner; + self.remotedog.turret makeTurretInoperable(); + self.remotedog.turret SetDefaultDropPitch( 0 ); + //self.remotedog.turret.owner = self; + + // find a point to for the turret to look at when it isn't trying to fire + offset = turretPoint - self.remotedog.origin; + neutralTargetEnt = spawn("script_origin", self.remotedog.turret getTagOrigin("tag_flash") ); + neutralTargetEnt linkTo( self, "tag_origin", offset, (0,0,0) ); + neutralTargetEnt hide(); + self.remotedog.neutralTarget = neutralTargetEnt; + + // spawn a thread to control the turret + self.remotedog thread remoteDogFindTargets(); + + // get them controls hooked up! +// self ControlsLinkTo( self.remotedog ); + self MiniUAVOn( self.remotedog ); + + // Kick off timer. + self hudRemoteDogTimer( DOG_TIMEOUT_SEC ); + self.remotedog thread RemoteDogWaitForTimeout( DOG_TIMEOUT_SEC ); + + + // loop for the dog + self thread remoteDogLoop( self.remotedog ); + + // setup a thread to listen for the exit + self thread remoteDogPlayerEventListenerThread(); + + self.remotedog thread remoteDogExitCleanup(); + + return true; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogExitCleanup() +{ + remoteDogDebugPrint( "remoteDogExitCleanup()" ); + msg = self waittill_any_return( "death", "exit_remote_dog", "remote_dog_time_is_up", "remote_dog_out_of_ammo" ); // Wait for either way of exiting a uav. + remoteDogDebugPrint( "Running cleanup after msg " + msg ); + self.owner thread remoteDogExitPlayer(); + self notify( "cleanup_remote_dog" ); + self.owner notify( "cleanup_remote_dog" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogFindTargets() +{ + self endon( "death" ); + self endon( "cleanup_remote_dog" ); + + println( "Geting Targets" ); + + for ( ;; ) + { + targets = []; + players = level._players; + + for (i = 0; i <= players.size; i++) + { + if ( isDogTarget( players[i] ) && isdefined( players[i] ) ) + { + targets[targets.size] = players[i]; + } + else + { + continue; + } + + wait( .05 ); + } + if ( targets.size > 0 ) + { + self acquireTarget( targets ); + return; + } + else + { + wait( .05 ); + } + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +isDogTarget( potentialTarget ) +{ + self endon( "death" ); + + if ( !isalive( potentialTarget ) || potentialTarget.sessionstate != "playing" ) + return false; + + if ( !isdefined( potentialTarget.pers["team"] ) ) + return false; + + if ( potentialTarget == self.owner ) + return false; + + if ( distanceSquared( potentialTarget.origin , self.origin ) > DOG_TURRET_MAX_TARGETING_RANGE*DOG_TURRET_MAX_TARGETING_RANGE ) + return false; + + if ( level._teamBased && potentialTarget.pers["team"] == self.team ) + return false; + + if ( potentialTarget.pers["team"] == "spectator" ) + return false; + + if ( isdefined( potentialTarget.spawntime ) && ( gettime() - potentialTarget.spawntime )/1000 <= DOG_TURRET_SPAWN_GRACE_TIME ) + return false; + + // check to see if they are in our yaw range + vecToTarget = potentialTarget.origin - self.origin; + targetYaw = AngleClamp( VectorToYaw( vecToTarget ) ); + turretYaw = AngleClamp( self.angles[1] ); + degrees = abs( targetYaw - self.angles[1] ); + degrees = AngleClamp( degrees ); + if( degrees > DOG_TURRET_MAX_YAW && ( 360 - degrees ) > DOG_TURRET_MAX_YAW ) + { +// println( "bad degrees " + degrees + " angles " + turretYaw + " target yaw " + targetYaw ); + return false; + } +// println( "good degrees " + degrees + " angles " + turretYaw + " target yaw " + targetYaw ); + + + if ( isDefined( self ) ) + { + minTurretEye = self.turret.origin + ( 0, 0, 64 ); + minTurretCanSeeTarget = potentialTarget sightConeTrace( minTurretEye, self ); + + if ( minTurretCanSeeTarget < 1 ) + return false; + } + + return true; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +getBestTarget( targets ) +{ + self endon( "death" ); + origin = self.origin; + + closest = undefined; + bestTarget = undefined; + + foreach ( targ in targets ) + { + curDist = Distance( self.origin, targ.origin ); + + if ( !isDefined( closest ) ) + { + closest = curDist; + bestTarget = targ; + } + else if ( closest > curDist ) + { + closest = curDist; + bestTarget = targ; + } + } + return ( bestTarget ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +acquireTarget( targets ) +{ + self endon( "death" ); + + if ( targets.size == 1 ) + { + self.bestTarget = targets[0]; + } + else + { + self.bestTarget = self getBestTarget( targets ); + } + + self notify( "acquiringTarget" ); + self.turret SetTargetEntity( self.bestTarget, ( 0,0,42 ) ); // sets turret to target entity + wait( .15 ); + self thread fireOnTarget(); // fires on current target. + self thread watchTargetDeath( targets ); //abandons target when target killed + self thread watchTargetDistance( targets ); + self thread watchTargetAngle( targets ); + self thread watchTargetThreat( self.bestTarget ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +fireOnTarget() +{ + self endon( "death" ); + self endon( "abandonedTarget" ); + self endon( "killedTarget" ); + noTargTime = undefined; + acquiredTime = getTime(); + + if ( !isDefined( self.bestTarget ) ) + { + println("No Targ to fire on"); + return; + } + + println("firing on best target"); + + while( 1 ) + { + if ( !isDefined ( self.turret getTurretTarget( true ) ) ) + { + if ( !isDefined( noTargTime ) ) + noTargTime = getTime(); + + curTime = getTime(); + + if ( noTargTime - curTime > 1 ) + { + noTargTime = undefined; + self thread explicitAbandonTarget(); + return; + } + + println("Waiting because the turret doesnt have a target" ); + + wait ( .5 ); + continue; + } + + + numShots = randomIntRange( DOG_TURRET_MIN_SHOTS, DOG_TURRET_MAX_SHOTS ); + for ( i = 0; i < numShots; i++ ) + { + println( "actually shooting turret" ); + self.turret ShootTurret(); + wait ( DOG_TURRET_FIRE_DELAY ); + } + wait ( randomFloatRange( DOG_TURRET_MIN_BARRAGE_DELAY, DOG_TURRET_MAX_BARRAGE_DELAY ) ); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +watchTargetDeath( targets ) +{ + self endon( "abandonedTarget" ); + self endon( "death" ); + if ( !isDefined( self.bestTarget ) ) + return; + + self.bestTarget waittill( "death" ); + + self notify( "killedTarget" ); + println( "Killed Target" ); + + self.bestTarget = undefined; + self.turret ClearTargetEntity(); + self remoteDogFindTargets(); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +watchTargetAngle( targets ) +{ + self endon( "abandonedTarget" ); + self endon( "death" ); + + for ( ;; ) + { + if ( !isDefined( self.bestTarget ) ) + return; + + // check to see if they are in our yaw range + vecToTarget = self.bestTarget.origin - self.origin; + targetYaw = AngleClamp( VectorToYaw( vecToTarget ) ); + turretYaw = AngleClamp( self.angles[1] ); + degrees = abs( targetYaw - self.angles[1] ); + degrees = AngleClamp( degrees ); + if( degrees > DOG_TURRET_MAX_YAW && ( 360 - degrees ) > DOG_TURRET_MAX_YAW ) + { + println( "Abandon! degrees " + degrees + " angles " + self.angles[1] + " target yaw " + targetYaw ); + self thread explicitAbandonTarget(); + return; + } + wait ( 0.5 ); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +watchTargetDistance( targets ) +{ + self endon( "abandonedTarget" ); + self endon( "death" ); + + for ( ;; ) + { + if ( !isDefined( self.bestTarget ) ) + return; + + trace = BulletTrace( self.turret.origin, self.bestTarget.origin, false, self ); + traceDistance = Distance(self.origin, trace["position"] ); + + if ( traceDistance > DOG_TURRET_MAX_TARGETING_RANGE ) + { + println( "TARGET DIST TOO FAR!!!" ); + self thread explicitAbandonTarget(); + return; + } + println( traceDistance ); + wait ( 2 ); + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +watchTargetThreat( curTarget ) +{ + self endon( "abandonedTarget" ); + self endon( "death" ); + self endon( "killedTarget" ); + + for ( ;; ) + { + targets = []; + players = level._players; + + for (i = 0; i <= players.size; i++) + { + if ( isDogTarget( players[i] ) ) + { + if( !isdefined( players[i] ) ) + continue; + + if( !isdefined(curTarget) ) + return; + + traceOldTarg = Distance(self.origin, CurTarget.origin ); + traceNewTarg = Distance(self.origin, players[i].origin ); + + if ( traceNewTarg < traceOldTarg ) + { + self thread explicitAbandonTarget(); + return; + } + } + + wait( .05 ); + } + + wait( .25 ); + } +} + +explicitAbandonTarget( noNewTarget ) +{ + self notify( "abandonedTarget" ); + + println( "ABANDONED TARGET" ); + + self.bestTarget = undefined; + self.turret ClearTargetEntity(); + + if ( isDefined(noNewTarget) && noNewTarget ) + return; + + self thread remoteDogFindTargets(); + return; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogLoop( vehicle ) +{ + self endon( "death" ); + vehicle endon( "cleanup_remote_dog" ); + + self NotifyOnPlayerCommand( "exit_remote_dog", "+usereload" ); // BUTTON_X + + vehicle._oldOrigin = vehicle.origin; + vehicle.fireCycle = 0; + + while ( isalive( self ) ) + { + if( vehicle.fireCycle > 0 ) + { + vehicle.fireCycle = vehicle.fireCycle - 1; + } + + // steal the player's angles to control turning the dog, for now... + angles = vehicle.angles; + player_angles = self GetPlayerAngles(); + angles = ( player_angles[0], angles[1], angles[2] ); + target = vehicle.origin + vector_multiply( AnglesToForward( angles ), 2000.0 ); + + // don't do this anymore, the turret is auto targetting now +// vehicle SetTurretTargetVec( target ); + + vehicle.remoteDogModel.angels = vehicle.angles; + +// no more attack buttons to shoot +/* if( self AttackButtonPressed() ) + { + if( vehicle.ammo > 0 && vehicle.fireCycle == 0) + { + vehicle fireweapon(); + vehicle.fireCycle = vehicle.fireRate; + vehicle.ammo = vehicle.ammo - 1; + // out of ammo! lets get out of this thing! + if( vehicle.ammo == 0 ) + { + self thread remotedogOutOfAmmoThead( vehicle ); + } + } + }*/ + + if( distance( vehicle._oldOrigin, vehicle.origin ) > 0 ) + { + if( vehicle.currAnim != level._remoteDogMoveAnim ) + { + vehicle.remoteDogModel ScriptModelPlayAnim( level._remoteDogMoveAnim ); + vehicle.currAnim = level._remoteDogMoveAnim; + } + } + else + { + if( vehicle.currAnim != level._remoteDogIdleAnim ) + { + vehicle.remoteDogModel ScriptModelPlayAnim( level._remoteDogIdleAnim ); + vehicle.currAnim = level._remoteDogIdleAnim; + } + } + + vehicle._oldOrigin = vehicle.origin; + wait 0.1; + } +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remotedogOutOfAmmoThead( vehicle ) +{ + remoteDogDebugPrint( "remotedogOutOfAmmoThead() out of ammo!" ); + vehicle endon( "cleanup_remote_dog" ); + wait 2; + vehicle notify( "remote_dog_out_of_ammo" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +Callback_DogDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName ) +{ + remoteDogDebugPrint( "damage callback" ); + if ( ( attacker == self || ( isDefined( attacker.pers ) && attacker.pers["team"] == self.team ) ) && attacker != self.owner ) + return; + + remoteDogDebugPrint( "damaged dog! " + damage ); + self Vehicle_FinishDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remoteDogExitPlayer() +{ + // cleanup the models + self.remotedog.remoteDogModel Unlink(); + self.remotedog.remoteDogModel Delete(); + + // cleanup the actual things + self.remotedog.turret Delete(); + self.remotedog Delete(); + + self ThermalVisionFOFOverlayOff(); + self CameraUnlink(); + self setClientDvar( "cg_fov", self.remote_dog_orig_fov ); + self MiniUAVOff(); +// self ControlsUnlink(); + self visionSetNakedForPlayer( getDvar( "mapname" ), 0 ); + self setVelocity(( 0, 0, 0 )); + self setOrigin( self._dogPlayerOrigin ); + self setPlayerAngles( self._dogPlayerAngles ); + self switchToWeapon( self._pre_killstreak_weapon_name ); + self destroyRemoteDogTimer(); + wait 2.0; + self EnableOffhandWeapons(); + self.in_dog = false; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +remotedogHud() +{ +// crossHair = newClientHudElem( self ); +// crossHair.x = 0; +// crossHair.y = 0; +// crossHair.alignX = "center"; +// crossHair.alignY = "middle"; +// crossHair.horzAlign = "center"; +// crossHair.vertAlign = "middle"; +// crossHair setshader( level._remoteDogCrossHair, 640, 480 ); +// static = NewClientHudElem( self ); +// static.horzAlign = "fullscreen"; +// static.vertAlign = "fullscreen"; +// static SetShader( "ac130_overlay_grain", 640, 480 ); +// +// self waittill( "cleanup_remote_dog" ); // Wait for either way of exiting a uav. +// crossHair Destroy(); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +hudRemoteDogTimer( duration ) +{ + remoteDogDebugPrint( "hudRemoteDogTimer()" ); + self.remoteDogTimer = newClientHudElem( self ); + self.remoteDogTimer.x = DOG_HUD_TIMER_POS_X; + self.remoteDogTimer.y = DOG_HUD_TIMER_POS_Y; + self.remoteDogTimer.alignX = "center"; + self.remoteDogTimer.alignY = "bottom"; + self.remoteDogTimer.horzAlign = "center_adjustable"; + self.remoteDogTimer.vertAlign = "bottom_adjustable"; + self.remoteDogTimer.fontScale = 2.5; + self.remoteDogTimer setTimer( 1.0 ); + self.remoteDogTimer.alpha = 1.0; + + self.remoteDogTimer setTimer( duration ); + println( "done setting hud timer" ); +} + +//******************************************************************* +// * +// * +//******************************************************************* + +RemoteDogWaitForTimeout( duration ) +{ + self endon( "cleanup_remote_dog" ); + wait duration; + remoteDogDebugPrint( "RemoteDogWaitForTimeout() Time's up!" ); + self notify( "remote_dog_time_is_up" ); + self._time_is_up = 1; +} + +//******************************************************************* +// * +// * +//******************************************************************* + +destroyRemoteDogTimer() +{ + remoteDogDebugPrint( "cleanup timer!" ); + self.remoteDogTimer Destroy(); +} + +/* +QUAKED script_vehicle_nx_miniuav_player_mp (1 0 0) (-16 -16 -24) (16 16 32) USABLE SPAWNER + +put this in your GSC: +maps\mp\killstreaks\_miniuav::main( "nx_vehicle_miniuav" ); + +and these lines in your CSV: +include,nx_vehicle_miniuav_player + +defaultmdl="nx_vehicle_miniuav" +default:"vehicletype" "nx_miniuav_player" +default:"script_team" "allies" +*/ diff --git a/maps/mp/_scoreboard.gsc b/maps/mp/_scoreboard.gsc new file mode 100644 index 0000000..6ab6483 --- /dev/null +++ b/maps/mp/_scoreboard.gsc @@ -0,0 +1,164 @@ +#include maps\mp\_utility; +#include common_scripts\utility; + +processLobbyScoreboards() +{ + foreach ( player in level._placement["all"] ) + player setPlayerScoreboardInfo(); + + if( level._multiTeamBased ) + { + buildScoreboardType( "multiteam" ); + + foreach ( player in level._players ) + player setPlayerData( "round", "scoreboardType", "multiteam" ); + } + else if ( level._teamBased ) + { + alliesScore = getTeamScore( "allies" ); + axisScore = getTeamScore( "axis" ); + + if ( alliesScore == axisScore ) + winner = "tied"; + else if ( alliesScore > axisScore ) + winner = "allies"; + else + winner = "axis"; + + if ( winner == "tied" ) + { + // build both, assign type to your team + buildScoreboardType( "allies" ); + buildScoreboardType( "axis" ); + + foreach ( player in level._players ) + { + if ( player.pers["team"] == "spectator" ) + player setPlayerData( "round", "scoreboardType", "allies" ); + else + player setPlayerData( "round", "scoreboardType", player.pers["team"] ); + } + } + else + { + // build just winner, assign type to winner + buildScoreboardType( winner ); + + foreach ( player in level._players ) + player setPlayerData( "round", "scoreboardType", winner ); + } + } + else // not teambased + { + buildScoreboardType( "neutral" ); + + foreach ( player in level._players ) + player setPlayerData( "round", "scoreboardType", "neutral" ); + } + + foreach ( player in level._players ) + { + // TODO: convert this to round stats + player setClientDvars( + "player_summary_xp", player.pers["summary"]["xp"], + "player_summary_score", player.pers["summary"]["score"], + "player_summary_challenge", player.pers["summary"]["challenge"], + "player_summary_match", player.pers["summary"]["match"], + "player_summary_misc", player.pers["summary"]["misc"] + ); + } +} + +setPlayerScoreboardInfo() +{ + scoreboardPlayerCount = getClientMatchData( "scoreboardPlayerCount" ); + if ( scoreboardPlayerCount <= 24 ) //MaxPlayers + { + setClientMatchData( "players", self.clientMatchDataId, "score", self.pers["score"] ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][score]: " + self.pers["score"] ); + + kills = self getPlayerStat( "kills" ); + setClientMatchData( "players", self.clientMatchDataId, "kills", kills ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][kills]: " + kills ); + + assists = self getPlayerStat( "assists" ); + setClientMatchData( "players", self.clientMatchDataId, "assists", assists ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][assists]: " + assists ); + + deaths = self getPlayerStat( "deaths" ); + setClientMatchData( "players", self.clientMatchDataId, "deaths", deaths ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][deaths]: " + deaths ); + + checkpoints = self getPlayerStat( "checkpoints" ); + setClientMatchData( "players", self.clientMatchDataId, "checkpoints", checkpoints ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][checkpoints]: " + checkpoints ); + + team = self.pers["team"]; + setClientMatchData( "players", self.clientMatchDataId, "team", team ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][team]: " + team ); + + faction = game[self.pers["team"]]; + setClientMatchData( "players", self.clientMatchDataId, "faction", faction ); + println( "Scoreboard: [" + self.name + "(" + self.clientMatchDataId + ")][faction]: " + faction ); + + println( "Scoreboard: scoreboardPlayerCount was " + scoreboardPlayerCount ); + scoreboardPlayerCount++; + setClientMatchData( "scoreboardPlayerCount", scoreboardPlayerCount ); + println( "Scoreboard: scoreboardPlayerCount now " + scoreboardPlayerCount ); + } + else + { + println( "Scoreboard: scoreboardPlayerCount is greater than 24 (" + scoreboardPlayerCount + ")" ); + } +} + +buildScoreboardType( team ) +{ + assert( team == "allies" || team == "axis" || team == "neutral" || team == "multiteam" ); + + println( "Scoreboard: Building scoreboard (" + team + ")" ); + + if ( team == "multiteam" ) + { + index = 0; + + foreach( teamname in level._teamNameList ) + { + foreach ( player in level._placement[teamname] ) + { + setClientMatchData( "scoreboards", "multiteam", index, player.clientMatchDataId ); + println( "Scoreboard: [scoreboards][" + team + "][" + index + "][" + player.clientMatchDataId + "]" ); + index++; + } + } + } + else if ( team == "neutral" ) + { + index = 0; + foreach ( player in level._placement["all"] ) + { + setClientMatchData( "scoreboards", team, index, player.clientMatchDataId ); + println( "Scoreboard: [scoreboards][" + team + "][" + index + "][" + player.clientMatchDataId + "]" ); + index++; + } + } + else + { + otherTeam = getOtherTeam( team ); + + index = 0; + foreach ( player in level._placement[team] ) + { + setClientMatchData( "scoreboards", team, index, player.clientMatchDataId ); + println( "Scoreboard: [scoreboards][" + team + "][" + index + "][" + player.name + "(" + player.clientMatchDataId + ")]" ); + index++; + } + + foreach ( player in level._placement[otherTeam] ) + { + setClientMatchData( "scoreboards", team, index, player.clientMatchDataId ); + println( "Scoreboard: [scoreboards][" + team + "][" + index + "][" + player.name + "(" + player.clientMatchDataId + ")]" ); + index++; + } + } +} \ No newline at end of file diff --git a/maps/mp/_shutter.gsc b/maps/mp/_shutter.gsc new file mode 100644 index 0000000..fa42319 --- /dev/null +++ b/maps/mp/_shutter.gsc @@ -0,0 +1,179 @@ +#include common_scripts\utility; +#include maps\mp\_utility; +main() +{ +// thread windController(); + level._inc = 0; + + array_levelthread (getentarray("wire","targetname"), ::wireWander); + + leftShutters = getentarray ("shutter_left","targetname"); + addShutters = getentarray ("shutter_right_open","targetname"); + for (i=0;i 50) + windDirection = "right"; + level notify ("wind blows", windDirection); + wait (2 + randomfloat(10)); + } +} + +shutterWanderLeft(shutter, windDirection) +{ +// println ("shutter angles ", shutter.angles[1]); +// assert (shutter.angles[1] >= shutter.startYaw); +// assert (shutter.angles[1] < shutter.startYaw + 180); + +// println ("Wind + ", level.inc); + level._inc++; + level endon ("wind blows"); + + newYaw = shutter.startYaw; + if (windDirection == "left") + newYaw += 179.9; + + newTime = 0.2; + shutter rotateto((shutter.angles[0], newYaw, shutter.angles[2]), newTime); + wait (newTime + 0.1); + + for (;;) + { + rot = randomint(80); + if (randomint(100) > 50) + rot *= -1; + + newYaw = shutter.angles[1] + rot; + altYaw = shutter.angles[1] + (rot*-1); + if ((newYaw < shutter.startYaw) || (newYaw > shutter.startYaw + 179)) + { + newYaw = altYaw; + } + + dif = abs(shutter.angles[1] - newYaw); + + newTime = dif*0.02 + randomfloat(2); + if (newTime < 0.3) + newTime = 0.3; +// println ("startyaw " + shutter.startyaw + " newyaw " + newYaw); + +// assert (newYaw >= shutter.startYaw); +// assert (newYaw < shutter.startYaw + 179); + + shutter rotateto((shutter.angles[0], newYaw, shutter.angles[2]), newTime, newTime * 0.5, newTime * 0.5); + wait (newTime); + } +} + +shutterWanderRight(shutter, windDirection) +{ +// println ("shutter angles ", shutter.angles[1]); +// assert (shutter.angles[1] >= shutter.startYaw); +// assert (shutter.angles[1] < shutter.startYaw + 180); + +// println ("Wind + ", level.inc); + level._inc++; + level endon ("wind blows"); + + newYaw = shutter.startYaw; + if (windDirection == "left") + newYaw += 179.9; + + newTime = 0.2; + shutter rotateto((shutter.angles[0], newYaw, shutter.angles[2]), newTime); + wait (newTime + 0.1); + + for (;;) + { + rot = randomint(80); + if (randomint(100) > 50) + rot *= -1; + + newYaw = shutter.angles[1] + rot; + altYaw = shutter.angles[1] + (rot*-1); + if ((newYaw < shutter.startYaw) || (newYaw > shutter.startYaw + 179)) + { + newYaw = altYaw; + } + + dif = abs(shutter.angles[1] - newYaw); + + newTime = dif*0.02 + randomfloat(2); + if (newTime < 0.3) + newTime = 0.3; +// println ("startyaw " + shutter.startyaw + " newyaw " + newYaw); + +// assert (newYaw >= shutter.startYaw); +// assert (newYaw < shutter.startYaw + 179); + + shutter rotateto((shutter.angles[0], newYaw, shutter.angles[2]), newTime, newTime * 0.5, newTime * 0.5); + wait (newTime); + } +} + +wireWander (wire) +{ + origins = getentarray (wire.target,"targetname"); + org1 = origins[0].origin; + org2 = origins[1].origin; + + angles = vectortoangles (org1 - org2); + ent = spawn ("script_model",(0,0,0)); + ent.origin = vector_multiply(org1, 0.5) + vector_multiply(org2, 0.5); +// ent setmodel ("temp"); + ent.angles = angles; + wire linkto (ent); + rottimer = 2; + rotrange = 0.9; + dist = 4 + randomfloat(2); + ent rotateroll(dist*0.5,0.2); + wait (0.2); + for (;;) + { + rottime = rottimer + randomfloat (rotRange) - (rotRange * 0.5); + ent rotateroll(dist,rottime, rottime*0.5, rottime*0.5); + wait (rottime); + ent rotateroll(dist * -1,rottime, rottime*0.5, rottime*0.5); + wait (rottime); + } +} \ No newline at end of file diff --git a/maps/mp/_skill.gsc b/maps/mp/_skill.gsc new file mode 100644 index 0000000..511dbcb --- /dev/null +++ b/maps/mp/_skill.gsc @@ -0,0 +1,71 @@ +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +init() +{ + level thread onPlayerConnect(); + level thread onPlayerDisconnect(); +} + +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + // look at how spawning works + player.connectTime = getTime(); + player.targets = []; + + player thread onWeaponFired(); + player thread onDeath(); + } +} + +onPlayerDisconnect() +{ + for(;;) + { + level waittill( "disconnected", player ); + + player.targets = []; + } +} + + +onWeaponFired() +{ + level endon( "game_ended" ); + self endon( "disconnected" ); + + for ( ;; ) + { + self waittill( "weapon_fired" ); + + // find likely target + // find target and tag when they shot me. + //self.target + } +} + +onDeath() +{ + level endon( "game_ended" ); + self endon( "disconnected" ); + + for ( ;; ) + { + self waittill( "death" ); + + // + // find target and tag when they shot me. + //self.target + } +} + + +processKill( attacker, defender ) +{ + updateSkill( attacker, defender, "tdm", 1.0 ); +} \ No newline at end of file diff --git a/maps/mp/_stinger.gsc b/maps/mp/_stinger.gsc new file mode 100644 index 0000000..b39ef25 --- /dev/null +++ b/maps/mp/_stinger.gsc @@ -0,0 +1,419 @@ +#include maps\mp\_utility; + +InitStingerUsage() +{ + self.stingerStage = undefined; + self.stingerTarget = undefined; + self.stingerLockStartTime = undefined; + self.stingerLostSightlineTime = undefined; + + self thread ResetStingerLockingOnDeath(); + level._stingerTargets = []; +} + + +ResetStingerLocking() +{ + if ( !IsDefined( self.stingerUseEntered ) ) + return; + self.stingerUseEntered = undefined; + + self notify( "stop_javelin_locking_feedback" ); + self notify( "stop_javelin_locked_feedback" ); + + self WeaponLockFree(); + InitStingerUsage(); +} + + +ResetStingerLockingOnDeath() +{ + self endon( "disconnect" ); + + self notify ( "ResetStingerLockingOnDeath" ); + self endon ( "ResetStingerLockingOnDeath" ); + + for ( ;; ) + { + self waittill( "death" ); + self ResetStingerLocking(); + } +} + + +StillValidStingerLock( ent ) +{ + assert( IsDefined( self ) ); + + if ( !IsDefined( ent ) ) + return false; + if ( !(self WorldPointInReticle_Circle( ent.origin, 65, 85 )) ) + return false; + + if ( self.stingerTarget == level._ac130.planeModel && !isDefined( level._ac130player ) ) + return false; + + return true; +} + + +LoopStingerLockingFeedback() +{ + self endon( "stop_javelin_locking_feedback" ); + + for ( ;; ) + { + if ( isDefined( level._chopper ) && isDefined( level._chopper.gunner ) && isDefined( self.stingerTarget ) && self.stingerTarget == level._chopper.gunner ) + level._chopper.gunner playLocalSound( "missile_locking" ); + + if ( isDefined( level._ac130player ) && isDefined( self.stingerTarget ) && self.stingerTarget == level._ac130.planeModel ) + level._ac130player playLocalSound( "missile_locking" ); + + self playLocalSound( "stinger_locking" ); + self PlayRumbleOnEntity( "ac130_25mm_fire" ); + + wait 0.6; + } +} + + +LoopStingerLockedFeedback() +{ + self endon( "stop_javelin_locked_feedback" ); + + for ( ;; ) + { + if ( isDefined( level._chopper ) && isDefined( level._chopper.gunner ) && isDefined( self.stingerTarget ) && self.stingerTarget == level._chopper.gunner ) + level._chopper.gunner playLocalSound( "missile_locking" ); + + if ( isDefined( level._ac130player ) && isDefined( self.stingerTarget ) && self.stingerTarget == level._ac130.planeModel ) + level._ac130player playLocalSound( "missile_locking" ); + + self playLocalSound( "stinger_locked" ); + self PlayRumbleOnEntity( "ac130_25mm_fire" ); + + wait 0.25; + } +} + + +/# +DrawStar( point ) +{ + Line( point + (10,0,0), point - (10,0,0) ); + Line( point + (0,10,0), point - (0,10,0) ); + Line( point + (0,0,10), point - (0,0,10) ); +} +#/ + + +LockSightTest( target ) +{ + eyePos = self GetEye(); + + if ( !isDefined( target ) ) //targets can disapear during targeting. + return false; + + passed = BulletTracePassed( eyePos, target.origin, false, target ); + if ( passed ) + return true; + + front = target GetPointInBounds( 1, 0, 0 ); + passed = BulletTracePassed( eyePos, front, false, target ); + if ( passed ) + return true; + + back = target GetPointInBounds( -1, 0, 0 ); + passed = BulletTracePassed( eyePos, back, false, target ); + if ( passed ) + return true; + + return false; +} + + +StingerDebugDraw( target ) +{ +/# + if ( GetDVar( "missileDebugDraw" ) != "1" ) + return; + if ( !IsDefined( target ) ) + return; + + org = target.origin; + DrawStar( org ); + org = target GetPointInBounds( 1, 0, 0 ); + DrawStar( org ); + org = target GetPointInBounds( -1, 0, 0 ); + DrawStar( org ); +#/ +} + + +SoftSightTest() +{ + LOST_SIGHT_LIMIT = 500; + + if ( self LockSightTest( self.stingerTarget ) ) + { + self.stingerLostSightlineTime = 0; + return true; + } + + if ( self.stingerLostSightlineTime == 0 ) + self.stingerLostSightlineTime = getTime(); + + timePassed = GetTime() - self.stingerLostSightlineTime; + //PrintLn( "Losing sight of target [", timePassed, "]..." ); + + if ( timePassed >= LOST_SIGHT_LIMIT ) + { + //PrintLn( "Lost sight of target." ); + ResetStingerLocking(); + return false; + } + + return true; +} + +GetTargetList() +{ + targets = []; + + if ( level._teamBased ) + { + if ( IsDefined( level._chopper ) && ( level._chopper.team != self.team || level._chopper.owner == self ) ) + targets[targets.size] = level._chopper; + + if ( IsDefined( level._raven ) && ( level._raven.team != self.team || level._raven.owner == self ) ) + targets[targets.size] = level._raven; + + if ( isDefined( level._ac130player ) && level._ac130player.team != self.team ) + targets[targets.size] = level._ac130.planemodel; + + if ( isDefined( level._harriers) ) + { + foreach( harrier in level._harriers ) + { + if ( isDefined( harrier ) && ( harrier.team != self.team || ( isDefined( harrier.owner ) && harrier.owner == self ) ) ) + targets[targets.size] = harrier; + } + } + + foreach( target_player in level._players ) + { + if (( target_player.team != self.team ) && (target_player _hasPerk("specialty_juggersuit"))) + { + targets[targets.size] = target_player; + } + } + + if( level._multiTeamBased ) + { + //for all teams + for( i = 0; i < level._teamNameList.size; i++ ) + { + //that are not our team + if( self.team != level._teamNameList[i] ) + { + //does that team have any uav's + if( level._UAVModels[level._teamNameList[i]].size ) + { + //add each uav to the target list + foreach ( UAV in level._UAVModels[level._teamNameList[i]] ) + { + targets[targets.size] = UAV; + } + } + } + } + } + else if ( level._UAVModels[level._otherTeam[self.team]].size ) + { + foreach ( UAV in level._UAVModels[level._otherTeam[self.team]] ) + targets[targets.size] = UAV; + } + + if ( isDefined( level._littleBird ) ) + { + foreach ( bird in level._littleBird ) + { + if ( !isDefined( bird ) ) + continue; + + if ( self.team != bird.owner.team || self == bird.owner ) + targets[targets.size] = bird; + } + } + + } + else + { + if ( IsDefined( level._chopper ) && ( level._chopper.owner != self ) ) ///check for teams + targets[targets.size] = level._chopper; + + if ( isDefined( level._ac130player ) ) + targets[targets.size] = level._ac130.planemodel; + + if ( isDefined( level._harriers) ) + { + foreach( harrier in level._harriers ) + { + if ( isDefined( harrier ) ) + targets[targets.size] = harrier; + } + } + + foreach( target_player in level._players ) + { + if (( target_player != self ) && (target_player _hasPerk("specialty_juggersuit"))) + { + targets[targets.size] = target_player; + } + } + + if ( level._UAVModels.size ) + { + foreach ( ownerGuid, UAV in level._UAVModels ) + { + if ( isDefined( UAV.owner ) && UAV.owner == self ) + continue; + + targets[targets.size] = UAV; + } + } + } + + return targets; +} + + +StingerUsageLoop() +{ + self endon("death"); + self endon("disconnect"); + + LOCK_LENGTH = 1000; + + InitStingerUsage(); + + for( ;; ) + { + wait 0.05; + + weapon = self getCurrentWeapon(); + + if ( weapon != "stinger_mp" && weapon != "at4_mp" ) + { + ResetStingerLocking(); + continue; + } + + if ( self PlayerADS() < 0.95 ) + { + ResetStingerLocking(); + continue; + } + + self.stingerUseEntered = true; + + if ( !IsDefined( self.stingerStage ) ) + self.stingerStage = 0; + + StingerDebugDraw( self.stingerTarget ); + + if ( self.stingerStage == 0 ) // searching for target + { + targets = GetTargetList(); + if ( targets.size == 0 ) + continue; + + targetsInReticle = []; + foreach ( target in targets ) + { + if ( !isDefined( target ) ) + continue; + + insideReticle = self WorldPointInReticle_Circle( target.origin, 65, 75 ); + + if ( insideReticle ) + targetsInReticle[targetsInReticle.size] = target; + } + if ( targetsInReticle.size == 0 ) + continue; + + sortedTargets = SortByDistance( targetsInReticle, self.origin ); + if ( !( self LockSightTest( sortedTargets[0] ) ) ) + continue; + + //PrintLn( "Found a target to lock to..." ); + thread LoopStingerLockingFeedback(); + self.stingerTarget = sortedTargets[0]; + self.stingerLockStartTime = GetTime(); + self.stingerStage = 1; + self.stingerLostSightlineTime = 0; + } + + if ( self.stingerStage == 1 ) // locking on to a target + { + if ( !(self StillValidStingerLock( self.stingerTarget )) ) + { + //PrintLn( "Failed to get lock." ); + ResetStingerLocking(); + continue; + } + + passed = SoftSightTest(); + if ( !passed ) + continue; + + timePassed = getTime() - self.stingerLockStartTime; + //PrintLn( "Locking [", timePassed, "]..." ); + if( self _hasPerk( "specialty_fasterlockon" )) + { + if( timePassed < ( LOCK_LENGTH * 0.5 )) + { + continue; + } + } + else + { + if ( timePassed < LOCK_LENGTH ) + continue; + } + + self notify( "stop_javelin_locking_feedback" ); + thread LoopStingerLockedFeedback(); + + //PrintLn( "Locked!"); + if ( self.stingerTarget.model == "vehicle_av8b_harrier_jet_mp" || self.stingerTarget.model == "vehicle_little_bird_armed" ) + { + self WeaponLockFinalize( self.stingerTarget ); + } + else if ( IsPlayer( self.stingerTarget ) ) + { + self WeaponLockFinalize( self.stingerTarget, (0,0,32) ); + } + else + { + self WeaponLockFinalize( self.stingerTarget, (100,0,-32) ); + } + + self.stingerStage = 2; + } + + if ( self.stingerStage == 2 ) // target locked + { + passed = SoftSightTest(); + if ( !passed ) + continue; + + if ( !(self StillValidStingerLock( self.stingerTarget )) ) + { + //PrintLn( "Gave up lock." ); + ResetStingerLocking(); + continue; + } + } + } +} \ No newline at end of file diff --git a/maps/mp/_upgrade.gsc b/maps/mp/_upgrade.gsc new file mode 100644 index 0000000..1bc3006 --- /dev/null +++ b/maps/mp/_upgrade.gsc @@ -0,0 +1,745 @@ +//**************************************************************************** +// ** +// Confidential - (C) Activision Publishing, Inc. 2010 ** +// ** +//**************************************************************************** +// ** +// Module: The Combat Awareness Upgrade System ** +// (1) Players are displayed with Earned Strike Points (ESP) ** +// while alive. ** +// (2) The ESP will increment when a new killstreak is earned. ** +// (3) If enough ESP is earned, players will be presented with ** +// options that they can spend the earned ESP. ** +// (4) If spending occurs, the ESP counters as well as players' ** +// killstreak queue will be adjusted accordingly. ** +// ** +// This script is organized into four major components: ** +// ** +// Components ** +// ------------------------------------------------------------------- ** +// initialization functions ** +// major logic functions ** +// HUD element functions ** +// helper functions ** +// ** +// Created: September 21st, 2011 - James Chen ** +// ** +//***************************************************************************/ + +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; +#include common_scripts\utility; + +//******************************************************************* +// Beginning of initialization functions * +// * +//******************************************************************* +KILLSTREAK_STRING_TABLE = "mp/killstreakTable.csv"; + +//tagJC: The beginning branching function. Use the dvar "upgradeEnabling" to decide whether the upgrade is enabled for the level +init() +{ + if ( getDvarInt( "upgradeEnabling" ) == 1 ) + { + println( "Upgrade: Enabled" ); + initUpgrade(); + level thread onPlayerConnect(); + } + else + { + println ( "Upgrade: Disabled" ); + level thread onPlayerConnectNoUpGrade(); + } +} + +//tagJC: Initialize the award types and precache all the necessary assets +initUpgrade() +{ + level._upgrade = undefined; + + //tagJC: Initialize the award types + //addUpgradeType ( "threatID", 15, ::activateThreatID, false ); + addUpgradeType ( "attackHelicopter", 9, ::giveAttackHelicopter, false ); + addUpgradeType ( "lightWeight", 12, ::activateExtraLightWeight, true ); + addUpgradeType ( "chopperGunner", 15, ::giveChopperGunner, false ); + + precacheString ( &"MP_A_BUTTON" ); + precacheString ( &"MP_B_BUTTON" ); + precacheString ( &"MP_Y_BUTTON" ); + precacheString ( &"MP_ESP" ); + for ( i = 1; true; i++ ) + { + retVal = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 1 ); + if ( !isDefined( retVal ) || retVal == "" ) + break; + + streakRef = tableLookupIString( KILLSTREAK_STRING_TABLE, 0, i, 2 ); + assert( streakRef != &"" ); + precacheString( streakRef ); + } +} + +//tagJC: Build and add the upgrade types +addUpgradeType( name, requiredPoints, activationFunc, reactivateWhenSpawn ) +{ + level._upgradeDefs[name]["requiredPoints"] = requiredPoints; + level._upgradeDefs[name]["activationFunc"] = activationFunc; + level._upgradeDefs[name]["reactivateWhenSpawn"] = reactivateWhenSpawn; +} + +//tagJC: The call-back function for the threadID +//tagJC: Self is the player +activateThreatID() +{ + self ThermalVisionFOFOverlayOn(); +} + +//tagJC: The call-back function for the extra light weight +//tagJC: Self is the player +activateExtraLightWeight() +{ + self.moveSpeedScaler = 1.30; + self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" ); +} + +//tagJC: The call-back function for giving the attacker helicopter. Since the killstreak is given on the button press during killcam, no action is necessary when player spawns +giveAttackHelicopter() +{ +} + +//tagJC: The call-back function for giving the chopper gunner. Since the killstreak is given on the button press during killcam, no action is necessary when player spawns +giveChopperGunner() +{ +} + +//tagJC: Initialize all the data necessary on player connect +onPlayerConnect() +{ + for(;;) + { + level waittill( "connected", player ); + + player.earnedStrikePoints = 0; + player createESPCounter(); + player.acquiredUpgrades = []; + player thread onPlayerSpawned(); + player.upgradeList["switchWeap"] = "chopperGunner"; + player.killstreakToRemove["switchWeap"] = []; + player.upgradeList["prone"] = "lightWeight"; + player.killstreakToRemove["prone"] = []; + player.upgradeList["jump"] = "attackHelicopter"; + player.killstreakToRemove["jump"] = []; + } +} + +//tagJC: In order to wait for the button presses for Y and B during killcam, the following two member data is necessary. +onPlayerConnectNoUpGrade() +{ + for(;;) + { + level waittill( "connected", player ); + player.YbuttonPressedDuringKillCam = false; + player.BbuttonPressedDuringKillCam = false; + } +} + +//tagJC: The call-back function for when player spawns +//tagJC: Self is the player +onPlayerSpawned() +{ + self endon( "disconnect" ); + + for(;;) + { + self waittill( "spawned_player" ); + self thread waitForChangeTeam(); + + self.YbuttonPressedDuringKillCam = false; + self.BbuttonPressedDuringKillCam = false; + + if ( isDefined ( self.ESPCounter_a )) + { + self.ESPCounter_a.alpha = 1; + } + + if ( isDefined ( self.ESPCounter_b )) + { + self.ESPCounter_b.alpha = 1; + } + + //tagJC: If there is anything in the player's acquired upgrade list, reactivate the effects + for ( i = 0; i < self.acquiredUpgrades.size; i++ ) + { + upgradeName = self.acquiredUpgrades[i]; + if (( isDefined (level._upgradeDefs[upgradeName]["reactivateWhenSpawn"])) && (level._upgradeDefs[upgradeName]["reactivateWhenSpawn"] == true )) + { + self [[level._upgradeDefs[upgradename]["activationFunc"]]](); + } + } + } +} + +//tagJC: Thread running on players for team changes +//tagJC: Self is the player +waitForChangeTeam() +{ + self endon ( "disconnect" ); + + self notify ( "waitForChangeTeam" ); + self endon ( "waitForChangeTeam" ); + + for ( ;; ) + { + self waittill ( "joined_team" ); + self.earnedStrikePoints = 0; + } +} + +//******************************************************************* +// End of initialization functions * +// Beginning of main logic functions * +//******************************************************************* +//tagJC: Based on the point values passed in, this function remove earned killstreak from player's killstreak until enough points are cumulated. +//tagJC: Self is the player +removeKillstreakToGetUpgrade ( earnedStrikePointLimit ) +{ + earnedStrikePoints = 0; + removeCounter = 0; + size = self.pers["killstreaks"].size; + foreach ( index, streakStruct in self.pers["killstreaks"] ) + { + earnedStrikePoints += streakStruct.strikePoints; + self.pers["killstreaks"][index] = undefined; + removeCounter += 1; + if ( earnedStrikePoints >= earnedStrikePointLimit ) + { + break; + } + } + streakRemain = size - removeCounter; + for ( i = 0; i < size ; i++ ) + { + if ( i <= ( streakRemain - 1 )) + { + self.pers["killstreaks"][i] = self.pers["killstreaks"][i + removeCounter]; + } + else + { + self.pers["killstreaks"][i] = undefined; + } + } + self.earnedStrikePoints = 0; + for ( i = 0; i < self.pers["killstreaks"].size; i++ ) + { + self.earnedStrikePoints += self.pers["killstreaks"][i].strikePoints; + } + self updateESPNumber(); +} + +//tagJC: This function is called during player's killcam and process the upgrade selection accordingly. Currently, given +// the players killstreak is hard-coded. In the future, if such selection is desirable, a more generic approach +// will be implemented by then. +//tagJC: Self is the player +processUpgradeSelections() +{ + if (( self.killCamButtonPressed == "jump") && ( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["jump"]]["requiredPoints"] ) && !(maps\mp\_upgrade::hasUpgrade(self, self.upgradeList["jump"] ))) + { + self.acquiredUpgrades[self.acquiredUpgrades.size] = self.upgradeList["jump"]; + self removeKillstreakToGetUpgrade( level._upgradeDefs[self.upgradeList["jump"]]["requiredPoints"]); + self thread maps\mp\killstreaks\_killstreaks::giveKillstreak( "helicopter", false, false, self, true ); + } + else if (( self.killCamButtonPressed == "prone") && ( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["prone"]]["requiredPoints"] ) && !(maps\mp\_upgrade::hasUpgrade(self, self.upgradeList["prone"] ))) + { + self.acquiredUpgrades[self.acquiredUpgrades.size] = self.upgradeList["prone"]; + self removeKillstreakToGetUpgrade( level._upgradeDefs[self.upgradeList["prone"]]["requiredPoints"]); + } + else if (( self.killCamButtonPressed == "switchWeap") && ( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["switchWeap"]]["requiredPoints"] ) && !(maps\mp\_upgrade::hasUpgrade(self, self.upgradeList["switchWeap"] ))) + { + self.acquiredUpgrades[self.acquiredUpgrades.size] = self.upgradeList["switchWeap"]; + self removeKillstreakToGetUpgrade( level._upgradeDefs[self.upgradeList["switchWeap"]]["requiredPoints"]); + self thread maps\mp\killstreaks\_killstreaks::giveKillstreak( "helicopter_minigun", false, false, self, true ); + } +} + +//******************************************************************* +// End of main logic functions * +// Beginning of HUD element functions * +//******************************************************************* +//tagJC: Creating the A, B, and Y buttons that will be shown during the killcam +//tagJC: Self is the player +initUpgradeElements() +{ + if ( !isDefined( self.kc_A_button ) ) + { + self.kc_A_button = newClientHudElem(self); + self.kc_A_button.label = &"MP_A_BUTTON"; + self.kc_A_button.archived = false; + self.kc_A_button.x = 0; + self.kc_A_button.alignX = "left"; + self.kc_A_button.alignY = "middle"; + self.kc_A_button.horzAlign = "left"; + self.kc_A_button.vertAlign = "middle"; + self.kc_A_button.sort = 1; // force to draw after the bars + self.kc_A_button.font = "default"; + self.kc_A_button.foreground = true; + self.kc_A_button.hideWhenInMenu = true; + self.kc_A_button.alpha = 0; + self.kc_A_button.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + self.kc_A_button.y = 20; + self.kc_A_button.fontscale = 1.2; // 1.8/1.5 + } + else + { + self.kc_A_button.y = 32; + self.kc_A_button.fontscale = 1.8; + } + } + + if ( !isDefined( self.kc_B_button ) ) + { + self.kc_B_button = newClientHudElem(self); + self.kc_B_button.label = &"MP_B_BUTTON"; + self.kc_B_button.archived = false; + self.kc_B_button.x = 160; + self.kc_B_button.alignX = "left"; + self.kc_B_button.alignY = "top"; + self.kc_B_button.horzAlign = "left"; + self.kc_B_button.vertAlign = "top"; + self.kc_B_button.sort = 1; // force to draw after the bars + self.kc_B_button.font = "default"; + self.kc_B_button.foreground = true; + self.kc_B_button.hideWhenInMenu = true; + self.kc_B_button.alpha = 0; + self.kc_B_button.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + self.kc_B_button.y = 20; + self.kc_B_button.fontscale = 1.2; // 1.8/1.5 + } + else + { + self.kc_B_button.y = 128; + self.kc_B_button.fontscale = 1.8; + } + } + + if ( !isDefined( self.kc_Y_button ) ) + { + self.kc_Y_button = newClientHudElem(self); + self.kc_Y_button.label = &"MP_Y_BUTTON"; + self.kc_Y_button.archived = false; + self.kc_Y_button.x = 0; + self.kc_Y_button.alignX = "left"; + self.kc_Y_button.alignY = "top"; + self.kc_Y_button.horzAlign = "left"; + self.kc_Y_button.vertAlign = "top"; + self.kc_Y_button.sort = 1; // force to draw after the bars + self.kc_Y_button.font = "default"; + self.kc_Y_button.foreground = true; + self.kc_Y_button.hideWhenInMenu = true; + self.kc_Y_button.alpha = 0; + self.kc_Y_button.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + self.kc_Y_button.y = 20; + self.kc_Y_button.fontscale = 1.2; // 1.8/1.5 + } + else + { + self.kc_Y_button.y = 0; + self.kc_Y_button.fontscale = 1.8; + } + } +} + +//tagJC: This function displays the killstreak icons and names that the player is about to lose when making the upgrade +//tagJC: Self is the player +showRemovedKillstreaks ( pointRequirement, buttonAssignment ) +{ + earnedStrikePoints = 0; + removeCounter = 0; + foreach ( index, streakStruct in self.pers["killstreaks"] ) + { + earnedStrikePoints += streakStruct.strikePoints; + removeCounter += 1; + if ( earnedStrikePoints >= pointRequirement ) + { + break; + } + } + if ( !(isDefined ( self.killstreakToRemove[buttonAssignment] ))) + { + self.killstreakToRemove[buttonAssignment] = []; + } + for ( i = 0; i < removeCounter; i++) + { + self.killstreakToRemove[buttonAssignment][i] = showKillstreakIcon ( self.pers["killstreaks"][i].streakName, buttonAssignment, i * 0, i * 25 ); + self.killstreakToRemove[buttonAssignment][i+removeCounter] = showKillstreakName ( self.pers["killstreaks"][i].streakName, buttonAssignment, i * 0, i * 25 ); + } +} + +//tagJC: This function returns a HUD element for the killstreak icons +//tagJC: Self is the player +showKillstreakIcon ( streakName, buttonAssignment, xOffset, yOffset ) +{ + iconName = getKillstreakIcon (streakName ); + real_yOffset = 32; + if ( buttonAssignment == "prone" ) + { + real_yOffset = 128; + } + else if ( buttonAssignment == "switchWeap" ) + { + real_yOffset = 0; + } + real_yOffset += 30; + real_yOffset += yOffset; + + xValue = 0; + if ( buttonAssignment == "prone" ) + { + xValue = 160; + } + xValue += xOffset; + + alignYValue = "top"; + if ( buttonAssignment == "jump" ) + { + alignYValue = "middle"; + } + + vertAlignValue = "top"; + if ( buttonAssignment == "jump" ) + { + vertAlignValue = "middle"; + } + + killstreakIcon = newClientHudElem(self); + killstreakIcon setShader ( iconName ); + killstreakIcon.archived = false; + killstreakIcon.x = xValue; + killstreakIcon.alignX = "left"; + killstreakIcon.alignY = alignYValue; + killstreakIcon.horzAlign = "left"; + killstreakIcon.vertAlign = vertAlignValue; + killstreakIcon.sort = 1; // force to draw after the bars + killstreakIcon.font = "default"; + killstreakIcon.foreground = true; + killstreakIcon.hideWhenInMenu = true; + killstreakIcon.alpha = 1; + //killstreakIcon.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + killstreakIcon.y = real_yOffset + 20; + killstreakIcon.fontscale = 1.2; // 1.8/1.5 + } + else + { + killstreakIcon.y = real_yOffset; + killstreakIcon.fontscale = 1.8; + } + return killstreakIcon; +} + +//tagJC: This function returns a HUD element for the killstreak names +//tagJC: Self is the player +showKillstreakName ( streakName, buttonAssignment, xOffset, yOffset ) +{ + iconName = getKillstreakIcon (streakName ); + real_yOffset = 32; + if ( buttonAssignment == "prone" ) + { + real_yOffset = 128; + } + else if ( buttonAssignment == "switchWeap" ) + { + real_yOffset = 0; + } + real_yOffset += 30; + real_yOffset += yOffset; + + xValue = 0; + if ( buttonAssignment == "prone" ) + { + xValue = 160; + } + xValue += xOffset; + + alignYValue = "top"; + if ( buttonAssignment == "jump" ) + { + alignYValue = "middle"; + } + + vertAlignValue = "top"; + if ( buttonAssignment == "jump" ) + { + vertAlignValue = "middle"; + } + + killstreakIcon = CreateFontString( "objective", 1.25 );; + killstreakIcon SetText( getKillstreakUserFriendlyName ( streakName )); + killstreakIcon.archived = false; + killstreakIcon.x = xValue + 20; + killstreakIcon.alignX = "left"; + killstreakIcon.alignY = alignYValue; + killstreakIcon.horzAlign = "left"; + killstreakIcon.vertAlign = vertAlignValue; + killstreakIcon.sort = 1; // force to draw after the bars + killstreakIcon.font = "default"; + killstreakIcon.foreground = true; + killstreakIcon.hideWhenInMenu = true; + killstreakIcon.alpha = 1; + //killstreakIcon.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + killstreakIcon.y = real_yOffset + 20; + killstreakIcon.fontscale = 1.5; // 1.8/1.5 + } + else + { + killstreakIcon.y = real_yOffset; + killstreakIcon.fontscale = 1.5; + } + return killstreakIcon; +} + +//tagJC: The ESP counter is displayed while the player is alive +//tagJC: Self is the player +createESPCounter() +{ + if ( !isDefined( self.ESPCounter_a ) ) + { + self.ESPCounter_a = newClientHudElem(self); + self.ESPCounter_a.label = &"MP_ESP"; + self.ESPCounter_a.archived = false; + self.ESPCounter_a.x = 0; + self.ESPCounter_a.alignX = "left"; + self.ESPCounter_a.alignY = "top"; + self.ESPCounter_a.horzAlign = "left"; + self.ESPCounter_a.vertAlign = "top"; + self.ESPCounter_a.sort = 1; // force to draw after the bars + self.ESPCounter_a.font = "default"; + self.ESPCounter_a.foreground = true; + self.ESPCounter_a.hideWhenInMenu = true; + self.ESPCounter_a.alpha = 1; + self.ESPCounter_a.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + self.ESPCounter_a.y = 20; + self.ESPCounter_a.fontscale = 1.2; // 1.8/1.5 + } + else + { + self.ESPCounter_a.y = 100; + self.ESPCounter_a.fontscale = 1.8; + } + } + + if ( !isDefined( self.ESPCounter_b ) ) + { + self.ESPCounter_b = CreateFontString( "objective", 1.25 );; + self.ESPCounter_b SetText( "" + self.earnedStrikePoints ); + self.ESPCounter_b.archived = false; + self.ESPCounter_b.x = 40; + self.ESPCounter_b.alignX = "left"; + self.ESPCounter_b.alignY = "top"; + self.ESPCounter_b.horzAlign = "left"; + self.ESPCounter_b.vertAlign = "top"; + self.ESPCounter_b.sort = 1; // force to draw after the bars + self.ESPCounter_b.font = "default"; + self.ESPCounter_b.foreground = true; + self.ESPCounter_b.hideWhenInMenu = true; + self.ESPCounter_b.alpha = 1; + self.ESPCounter_b.color = ( 0, 1, 0 ); + + if ( level._splitscreen ) + { + self.ESPCounter_b.y = 20; + self.ESPCounter_b.fontscale = 1.2; // 1.8/1.5 + } + else + { + self.ESPCounter_b.y = 100; + self.ESPCounter_b.fontscale = 1.8; + } + } +} + +//tagJC: This function is called at the beginning of the killcam, it will display all the HUD elements depending on the +// ESP earning situation. +//tagJC: Self is the player +showUpgradeHUDElement() +{ + if ( isDefined ( self.ESPCounter_a )) + { + self.ESPCounter_a.alpha = 0; + } + + if ( isDefined ( self.ESPCounter_b )) + { + self.ESPCounter_b.alpha = 0; + } + + if (( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["jump"]]["requiredPoints"] ) + && !( hasUpgrade(self, self.upgradeList["jump"] ))) + { + if ( isDefined( self.kc_A_button )) + { + self.kc_A_button.alpha = 1; + } + self showRemovedKillstreaks ( level._upgradeDefs[self.upgradeList["jump"]]["requiredPoints"], "jump" ); + } + + if (( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["prone"]]["requiredPoints"] ) + && !( hasUpgrade(self, self.upgradeList["prone"] ))) + { + if ( isDefined( self.kc_B_button )) + { + self.kc_B_button.alpha = 1; + } + self showRemovedKillstreaks ( level._upgradeDefs[self.upgradeList["prone"]]["requiredPoints"], "prone" ); + } + + if (( self.earnedStrikePoints >= level._upgradeDefs[self.upgradeList["switchWeap"]]["requiredPoints"] ) + && !( hasUpgrade(self, self.upgradeList["switchWeap"] ))) + { + if ( isDefined( self.kc_Y_button )) + { + self.kc_Y_button.alpha = 1; + } + self showRemovedKillstreaks ( level._upgradeDefs[self.upgradeList["switchWeap"]]["requiredPoints"], "switchWeap" ); + } +} + +//tagJC: Updating the numerical value for the ESP counter. +//tagJC: Self is the player +updateESPNumber() +{ + if ( isDefined( self.ESPCounter_b ) ) + { + self.ESPCounter_b SetText( "" + self.earnedStrikePoints ); + } +} + +//tagJC: Clean up all the upgrade related HUD elements once the killcam is complete. +//tagJC: Self is the player +upgradeHUDCleanUp() +{ + if ( isDefined( self.kc_A_button )) + self.kc_A_button.alpha = 0; + if ( isDefined( self.kc_B_button )) + self.kc_B_button.alpha = 0; + if ( isDefined( self.kc_Y_button )) + self.kc_Y_button.alpha = 0; + if ( isDefined( self.killstreakToRemove["jump"] )) + { + for ( i = 0; i < self.killstreakToRemove["jump"].size ; i++) + { + self.killstreakToRemove["jump"][i] Destroy(); + } + self.killstreakToRemove["jump"] = undefined; + } + if ( isDefined( self.killstreakToRemove["prone"] )) + { + for ( i = 0; i < self.killstreakToRemove["prone"].size ; i++) + { + self.killstreakToRemove["prone"][i] Destroy(); + } + self.killstreakToRemove["prone"] = undefined; + } + if ( isDefined( self.killstreakToRemove["switchWeap"] )) + { + for ( i = 0; i < self.killstreakToRemove["switchWeap"].size ; i++) + { + self.killstreakToRemove["switchWeap"][i] Destroy(); + } + self.killstreakToRemove["switchWeap"] = undefined; + } +} +//******************************************************************* +// End of HUD element functions * +// Beginning of helper functions * +//******************************************************************* +//tagJC: Check a specific upgrade is already acquired by the player. +//tagJC: player is the player that owns the killstreak. +hasUpgrade ( player, upgradeName ) +{ + result = false; + if ( isDefined ( player.acquiredUpgrades )) + { + for ( i = 0; i < player.acquiredUpgrades.size; i++ ) + { + if (( isDefined (player.acquiredUpgrades[i] )) && ( player.acquiredUpgrades[i] == upgradeName )) + { + result = true; + break; + } + } + } + return result; +} + +//tagJC: Returning the name of the kill streak icons. +getKillstreakIcon ( killstreakName ) +{ + return tableLookup( KILLSTREAK_STRING_TABLE, 1, killstreakName, 14 ); +} + +//tagJC: Waiting for the Y button press +//tagJC: Self is the player +waitForYButtonPress() +{ + self endon ("disconnect"); + self endon ("killcam_ended"); + + self notifyOnPlayerCommand ( "Y button pressed" , "weapnext" ); + self waittill ( "Y button pressed" ); + + self.YbuttonPressedDuringKillCam = true; +} + +//tagJC: Waiting for the B button press +//tagJC: Self is the player +waitForBButtonPress() +{ + self endon ("disconnect"); + self endon ("killcam_ended"); + + self notifyOnPlayerCommand ( "B button pressed" , "+stance" ); + self waittill ( "B button pressed" ); + + self.BbuttonPressedDuringKillCam = true; +} + +//tagJC: Returning the status for whether the Y button is pressed. +//tagJC: Self is the player +ReloadButtonPressed() +{ + return self.YbuttonPressedDuringKillCam; +} + +//tagJC: Returning the status for whether the B button is pressed. +//tagJC: Self is the player +ProneButtonPressed() +{ + return self.BbuttonPressedDuringKillCam; +} + +//tagJC: Returning the name of the kill streak reference. +getKillstreakUserFriendlyName ( killstreakName ) +{ + return tableLookupIString( KILLSTREAK_STRING_TABLE, 1, killstreakName, 2 ); +} +//******************************************************************* +// End of helper functions * +// * +//******************************************************************* \ No newline at end of file diff --git a/maps/mp/_utility.gsc b/maps/mp/_utility.gsc new file mode 100644 index 0000000..e00283f --- /dev/null +++ b/maps/mp/_utility.gsc @@ -0,0 +1,2914 @@ +#include common_scripts\utility; +#include maps\mp\gametypes\_hud_util; + +exploder_sound() +{ + if ( isdefined( self.script_delay ) ) + wait self.script_delay; + + self playSound( level._scr_sound[ self.script_sound ] ); +} + +/* +saveModel() +{ + info["model"] = self.model; + info["viewmodel"] = self getViewModel(); + attachSize = self getAttachSize(); + info["attach"] = []; + + assert(info["viewmodel"] != ""); // No viewmodel was associated with the player's model + + for(i = 0; i < attachSize; i++) + { + info["attach"][i]["model"] = self getAttachModelName(i); + info["attach"][i]["tag"] = self getAttachTagName(i); + info["attach"][i]["ignoreCollision"] = self getAttachIgnoreCollision(i); + } + + return info; +} + +loadModel(info) +{ + self detachAll(); + self setModel(info["model"]); + self setViewModel(info["viewmodel"]); + + attachInfo = info["attach"]; + attachSize = attachInfo.size; + + for(i = 0; i < attachSize; i++) + self attach(attachInfo[i]["model"], attachInfo[i]["tag"], attachInfo[i]["ignoreCollision"]); +} +*/ + +/* +============= +///ScriptDocBegin +"Name: delayThread( , , , , , )" +"Summary: Delaythread is cool! It saves you from having to write extra script for once off commands. Note you don�t have to thread it off. Delaythread is that smart!" +"Module: Utility" +"MandatoryArg: : The delay before the function occurs" +"MandatoryArg: : The function to run." +"OptionalArg: : parameter 1 to pass to the process" +"OptionalArg: : parameter 2 to pass to the process" +"OptionalArg: : parameter 3 to pass to the process" +"OptionalArg: : parameter 4 to pass to the process" +"OptionalArg: : parameter 5 to pass to the process" +"Example: delayThread( 3, ::flag_set, "player_can_rappel" ); +"SPMP: both" +///ScriptDocEnd +============= +*/ +delayThread( timer, func, param1, param2, param3, param4, param5 ) +{ + // to thread it off + thread delayThread_proc( func, timer, param1, param2, param3, param4, param5 ); +} + + +delayThread_proc( func, timer, param1, param2, param3, param4, param5 ) +{ + wait( timer ); + if ( !IsDefined( param1 ) ) + { + assertex( !isdefined( param2 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param3 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param4 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param5 ), "Delaythread does not support vars after undefined." ); + thread [[ func ]](); + } + else + if ( !IsDefined( param2 ) ) + { + assertex( !isdefined( param3 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param4 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param5 ), "Delaythread does not support vars after undefined." ); + thread [[ func ]]( param1 ); + } + else + if ( !IsDefined( param3 ) ) + { + assertex( !isdefined( param4 ), "Delaythread does not support vars after undefined." ); + assertex( !isdefined( param5 ), "Delaythread does not support vars after undefined." ); + thread [[ func ]]( param1, param2 ); + } + else + if ( !IsDefined( param4 ) ) + { + assertex( !isdefined( param5 ), "Delaythread does not support vars after undefined." ); + thread [[ func ]]( param1, param2, param3 ); + } + else + if ( !IsDefined( param5 ) ) + { + thread [[ func ]]( param1, param2, param3, param4 ); + } + else + { + thread [[ func ]]( param1, param2, param3, param4, param5 ); + } +} + +getPlant() +{ + start = self.origin + ( 0, 0, 10 ); + + range = 11; + forward = anglesToForward( self.angles ); + forward = vector_multiply( forward, range ); + + traceorigins[ 0 ] = start + forward; + traceorigins[ 1 ] = start; + + trace = bulletTrace( traceorigins[ 0 ], ( traceorigins[ 0 ] + ( 0, 0, -18 ) ), false, undefined ); + if ( trace[ "fraction" ] < 1 ) + { + //println("^6Using traceorigins[0], tracefraction is", trace["fraction"]); + + temp = spawnstruct(); + temp.origin = trace[ "position" ]; + temp.angles = orientToNormal( trace[ "normal" ] ); + return temp; + } + + trace = bulletTrace( traceorigins[ 1 ], ( traceorigins[ 1 ] + ( 0, 0, -18 ) ), false, undefined ); + if ( trace[ "fraction" ] < 1 ) + { + //println("^6Using traceorigins[1], tracefraction is", trace["fraction"]); + + temp = spawnstruct(); + temp.origin = trace[ "position" ]; + temp.angles = orientToNormal( trace[ "normal" ] ); + return temp; + } + + traceorigins[ 2 ] = start + ( 16, 16, 0 ); + traceorigins[ 3 ] = start + ( 16, -16, 0 ); + traceorigins[ 4 ] = start + ( -16, -16, 0 ); + traceorigins[ 5 ] = start + ( -16, 16, 0 ); + + besttracefraction = undefined; + besttraceposition = undefined; + for ( i = 0; i < traceorigins.size; i++ ) + { + trace = bulletTrace( traceorigins[ i ], ( traceorigins[ i ] + ( 0, 0, -1000 ) ), false, undefined ); + + //ent[i] = spawn("script_model",(traceorigins[i]+(0, 0, -2))); + //ent[i].angles = (0, 180, 180); + //ent[i] setmodel("105"); + + //println("^6trace ", i ," fraction is ", trace["fraction"]); + + if ( !isdefined( besttracefraction ) || ( trace[ "fraction" ] < besttracefraction ) ) + { + besttracefraction = trace[ "fraction" ]; + besttraceposition = trace[ "position" ]; + + //println("^6besttracefraction set to ", besttracefraction, " which is traceorigin[", i, "]"); + } + } + + if ( besttracefraction == 1 ) + besttraceposition = self.origin; + + temp = spawnstruct(); + temp.origin = besttraceposition; + temp.angles = orientToNormal( trace[ "normal" ] ); + return temp; +} + +orientToNormal( normal ) +{ + hor_normal = ( normal[ 0 ], normal[ 1 ], 0 ); + hor_length = length( hor_normal ); + + if ( !hor_length ) + return( 0, 0, 0 ); + + hor_dir = vectornormalize( hor_normal ); + neg_height = normal[ 2 ] * - 1; + tangent = ( hor_dir[ 0 ] * neg_height, hor_dir[ 1 ] * neg_height, hor_length ); + plant_angle = vectortoangles( tangent ); + + //println("^6hor_normal is ", hor_normal); + //println("^6hor_length is ", hor_length); + //println("^6hor_dir is ", hor_dir); + //println("^6neg_height is ", neg_height); + //println("^6tangent is ", tangent); + //println("^6plant_angle is ", plant_angle); + + return plant_angle; +} + +deletePlacedEntity( entity ) +{ + entities = getentarray( entity, "classname" ); + for ( i = 0; i < entities.size; i++ ) + { + //println("DELETED: ", entities[i].classname); + entities[ i ] delete(); + } +} + +playSoundOnPlayers( sound, team, excludeList ) +{ + assert( isdefined( level._players ) ); + + if ( level._splitscreen ) + { + if ( isdefined( level._players[ 0 ] ) ) + level._players[ 0 ] playLocalSound( sound ); + } + else + { + if ( isDefined( team ) ) + { + if ( isdefined( excludeList ) ) + { + for ( i = 0; i < level._players.size; i++ ) + { + player = level._players[ i ]; + if ( isdefined( player.pers[ "team" ] ) && ( player.pers[ "team" ] == team ) && !isExcluded( player, excludeList ) ) + player playLocalSound( sound ); + } + } + else + { + for ( i = 0; i < level._players.size; i++ ) + { + player = level._players[ i ]; + if ( isdefined( player.pers[ "team" ] ) && ( player.pers[ "team" ] == team ) ) + player playLocalSound( sound ); + } + } + } + else + { + if ( isdefined( excludeList ) ) + { + for ( i = 0; i < level._players.size; i++ ) + { + if ( !isExcluded( level._players[ i ], excludeList ) ) + level._players[ i ] playLocalSound( sound ); + } + } + else + { + for ( i = 0; i < level._players.size; i++ ) + level._players[ i ] playLocalSound( sound ); + } + } + } +} + + +sortLowerMessages() +{ + for ( i = 1; i < self.lowerMessages.size; i++ ) + { + message = self.lowerMessages[ i ]; + priority = message.priority; + for ( j = i - 1; j >= 0 && priority > self.lowerMessages[ j ].priority; j -- ) + self.lowerMessages[ j + 1 ] = self.lowerMessages[ j ]; + self.lowerMessages[ j + 1 ] = message; + } +} + + +addLowerMessage( name, text, time, priority, showTimer, shouldFade, fadeToAlpha, fadeToAlphaTime ) +{ + newMessage = undefined; + foreach ( message in self.lowerMessages ) + { + if ( message.name == name ) + { + if ( message.text == text && message.priority == priority ) + return; + + newMessage = message; + break; + } + } + + if ( !isDefined( newMessage ) ) + { + newMessage = spawnStruct(); + self.lowerMessages[ self.lowerMessages.size ] = newMessage; + } + + newMessage.name = name; + newMessage.text = text; + newMessage.time = time; + newMessage.addTime = getTime(); + newMessage.priority = priority; + newMessage.showTimer = showTimer; + newMessage.shouldFade = shouldFade; + newMessage.fadeToAlpha = fadeToAlpha; + newMessage.fadeToAlphaTime = fadeToAlphaTime; + + sortLowerMessages(); +} + + +removeLowerMessage( name ) +{ + if( IsDefined( self.lowerMessages ) ) + { + for ( i = 0; i < self.lowerMessages.size; i++ ) + { + if ( self.lowerMessages[ i ].name != name ) + continue; + + message = self.lowerMessages[ i ]; + if ( i < self.lowerMessages.size - 1 ) + self.lowerMessages[ i ] = self.lowerMessages[ self.lowerMessages.size - 1 ]; + + self.lowerMessages[ self.lowerMessages.size - 1 ] = undefined; + } + + sortLowerMessages(); + } +} + + +getLowerMessage() +{ + return self.lowerMessages[ 0 ]; +} + +/* +============= +///ScriptDocBegin +"Name: setLowerMessage( , ,