#include maps\mp\zombies\_zm_equip_headchopper; #include common_scripts\utility; #include maps\mp\_utility; #include maps\mp\zombies\_zm_utility; #include maps\mp\zombies\_zm_equipment; #include maps\mp\zombies\_zm_spawner; #include maps\mp\gametypes_zm\_weaponobjects; #include maps\mp\zombies\_zm; #include maps\mp\zombies\_zm_unitrigger; #include maps\mp\zombies\_zm_power; #include maps\mp\zombies\_zm_buildables; #include maps\mp\animscripts\zm_death; #include maps\mp\animscripts\zm_run; #include maps\mp\zombies\_zm_audio; #using_animtree("zombie_headchopper"); init_anim_slice_times() { level.headchopper_slice_times = []; slice_times = getnotetracktimes(%o_zmb_chopper_slice_slow, "slice"); retract_times = getnotetracktimes(%o_zmb_chopper_slice_slow, "retract"); animlength = getanimlength(%o_zmb_chopper_slice_slow); i = 0; foreach (frac in slice_times) { if (i != 6) { i++; continue; } level.headchopper_slice_times[level.headchopper_slice_times.size] = animlength * frac; i++; } i = 0; foreach (frac in retract_times) { if (i == 0 || i == 6) { i++; continue; } level.headchopper_slice_times[level.headchopper_slice_times.size] = animlength * frac; i++; } } headchopperthink(weapon, electricradius, armed) { self endon("death"); self endon("disconnect"); self endon("equip_headchopper_zm_taken"); weapon endon("death"); radiussquared = electricradius * electricradius; traceposition = weapon getcentroid() + anglestoforward(flat_angle(weapon.angles)) * -15; trace = bullettrace(traceposition, traceposition + vectorscale((0, 0, -1), 48.0), 1, weapon); trigger_origin = weapon gettagorigin("TAG_SAW"); trigger = spawn("trigger_box", trigger_origin, 1, 16, 128, 64); trigger.origin += anglestoup(weapon.angles) * 32.0; trigger.angles = weapon.angles; trigger enablelinkto(); trigger linkto(weapon); weapon.trigger = trigger; weapon thread headchopperthinkcleanup(trigger); direction_forward = anglestoforward(flat_angle(weapon.angles) + vectorscale((-1, 0, 0), 60.0)); direction_vector = vectorscale(direction_forward, 1024); direction_origin = weapon.origin + direction_vector; home_angles = weapon.angles; weapon.is_armed = 0; self thread headchopper_fx(weapon); self thread headchopper_animate(weapon, armed); while (!(isdefined(weapon.is_armed) && weapon.is_armed)) wait 0.5; weapon.chop_targets = []; self thread targeting_thread(weapon, trigger); while (isdefined(weapon)) { wait_for_targets(weapon); if (isdefined(weapon.chop_targets) && weapon.chop_targets.size > 0) { is_slicing = 1; slice_count = 0; weapon.headchopper_kills++; while (isdefined(is_slicing) && is_slicing) { weapon notify("chop", 1); weapon.is_armed = 0; weapon.zombies_only = 1; self headchopper_add_chop_ents(weapon, trigger); foreach (ent in weapon.chop_targets) self thread headchopperattack(weapon, ent); weapon.chop_targets = []; weapon waittill_any("slicing", "end"); slice_count++; is_slicing = weapon.is_slicing; } weapon notify("slice_done"); while (!(isdefined(weapon.is_armed) && weapon.is_armed)) wait 0.05; if (weapon.headchopper_kills >= 10) { self thread headchopper_expired(weapon); return; } } else wait 0.1; } } targeting_thread(weapon, trigger) { self endon("death"); self endon("disconnect"); self endon("equip_headchopper_zm_taken"); weapon endon("death"); weapon.zombies_only = 1; while (isdefined(weapon)) { if (weapon.is_armed || isdefined(weapon.is_slicing) && weapon.is_slicing) { if (isdefined(weapon.is_slicing) && weapon.is_slicing) weapon waittill("slice_done"); self headchopper_add_chop_ents(weapon, trigger); if (!weapon.zombies_only) weapon notify("hi_priority_target"); } wait 0.05; } } headchopper_add_chop_ents(weapon, trigger) { zombies = getaiarray(level.zombie_team); foreach (zombie in zombies) { if (!isdefined(zombie) || !isalive(zombie)) continue; if (isdefined(zombie.ignore_headchopper) && zombie.ignore_headchopper) continue; if (zombie istouching(trigger)) weapon headchopper_add_chop_ent(zombie); } players = get_players(); foreach (player in players) { if (is_player_valid(player) && player istouching(trigger)) { weapon headchopper_add_chop_ent(player); weapon.zombies_only = 0; } } } wait_for_targets(weapon) { weapon endon("hi_priority_target"); while (isdefined(weapon)) { if (isdefined(weapon.chop_targets) && weapon.chop_targets.size > 0) { return; } wait 0.05; } } headchopperattack(weapon, ent) { self endon("death"); self endon("disconnect"); self endon("equip_headchopper_zm_taken"); weapon endon("death"); if (!isdefined(ent) || !isalive(ent)) return; eye_position = ent geteye(); head_position = eye_position[2] + 13; foot_position = ent.origin[2]; length_head_to_toe = abs(head_position - foot_position); length_head_to_toe_25_percent = length_head_to_toe * 0.25; is_headchop = weapon.origin[2] >= head_position - length_head_to_toe_25_percent; is_torsochop = weapon.origin[2] >= foot_position + length_head_to_toe_25_percent; is_footchop = abs(foot_position - weapon.origin[2]) <= length_head_to_toe_25_percent; trace_point = undefined; if (isdefined(is_headchop) && is_headchop) trace_point = eye_position; else if (isdefined(is_torsochop) && is_torsochop) trace_point = ent.origin + (0, 0, length_head_to_toe_25_percent * 2); else trace_point = ent.origin + (0, 0, length_head_to_toe_25_percent); fwdangles = anglestoup(weapon.angles); tracefwd = bullettrace(weapon.origin + fwdangles * 5, trace_point, 0, weapon, 1, 1); if (!isdefined(tracefwd) || !isdefined(tracefwd["position"]) || tracefwd["position"] != trace_point) return; if (isplayer(ent)) { if (isdefined(is_headchop) && is_headchop) { radiusdamage(ent.origin + (0, 0, 5), 10, 50, 50, weapon, "MOD_MELEE"); } else { radiusdamage(ent.origin + (0, 0, 5), 10, 25, 25, weapon, "MOD_MELEE"); } } else { if (!(isdefined(is_headchop) && is_headchop) || !(isdefined(is_headchop) && is_headchop) && !(isdefined(ent.has_legs) && ent.has_legs)) { headchop_height = 25; if (!(isdefined(ent.has_legs) && ent.has_legs)) headchop_height = 35; is_headchop = abs(eye_position[2] - weapon.origin[2]) <= headchop_height; } if (isdefined(is_headchop) && is_headchop) { if (!(isdefined(ent.no_gib) && ent.no_gib)) ent maps\mp\zombies\_zm_spawner::zombie_head_gib(); ent dodamage(ent.health + 666, weapon.origin); ent.headchopper_last_damage_time = gettime(); ent playsound("zmb_exp_jib_headchopper_zombie"); self thread headchopper_kill_vo(ent); } else if (isdefined(is_torsochop) && is_torsochop) { if (ent.health <= 20) { ent playsound("zmb_exp_jib_headchopper_zombie"); self thread headchopper_kill_vo(ent); } ent dodamage(20, weapon.origin); ent.headchopper_last_damage_time = gettime(); } else if (isdefined(is_footchop) && is_footchop) { if (!(isdefined(ent.no_gib) && ent.no_gib)) { ent.a.gib_ref = "no_legs"; ent thread maps\mp\animscripts\zm_death::do_gib(); ent.has_legs = 0; ent allowedstances("crouch"); ent setphysparams(15, 0, 24); ent allowpitchangle(1); ent setpitchorient(); ent thread maps\mp\animscripts\zm_run::needsdelayedupdate(); if (isdefined(ent.crawl_anim_override)) ent [[ent.crawl_anim_override]](); } if (ent.health <= 10) { ent playsound("zmb_exp_jib_headchopper_zombie"); self thread headchopper_kill_vo(ent); } ent dodamage(10, weapon.origin); ent.headchopper_last_damage_time = gettime(); } } } setupwatchers() { self waittill("weapon_watchers_created"); watcher = maps\mp\gametypes_zm\_weaponobjects::getweaponobjectwatcher("equip_headchopper"); watcher.onspawnretrievetriggers = ::equipment_onspawnretrievableweaponobject; } equipment_onspawnretrievableweaponobject(watcher, player) { self.plant_parent = self; iswallmount = isdefined(level.placeable_equipment_type[self.name]) && level.placeable_equipment_type[self.name] == "wallmount"; if (!isdefined(player.turret_placement) || !player.turret_placement["result"]) { if (iswallmount || !getdvarint("tu11_zombie_turret_placement_ignores_bodies")) { self waittill("stationary"); waittillframeend; if (iswallmount) { if (isdefined(player.planted_wallmount_on_a_zombie) && player.planted_wallmount_on_a_zombie) { equip_name = self.name; equipment_disappear_fx(self.origin, undefined, self.angles); self delete(); player.do_not_display_equipment_pickup_hint = 1; player maps\mp\zombies\_zm_equipment::equipment_take(equip_name); player maps\mp\zombies\_zm_equipment::equipment_give(equip_name); player.do_not_display_equipment_pickup_hint = undefined; player.planted_wallmount_on_a_zombie = undefined; return; } } } else { self.plant_parent = player; self.origin = player.origin; self.angles = player.angles; wait_network_frame(); } } equipment = watcher.name + "_zm"; if (isdefined(player.current_equipment) && player.current_equipment == equipment) player equipment_to_deployed(equipment); if (isdefined(level.zombie_equipment[equipment].place_fn)) { if (isdefined(player.turret_placement) && player.turret_placement["result"]) { plant_origin = player.turret_placement["origin"]; plant_angles = player.turret_placement["angles"]; } else if (isdefined(level.placeable_equipment_type[self.name]) && level.placeable_equipment_type[self.name] == "wallmount") { plant_origin = self.origin; plant_angles = self.angles; } else { plant_origin = self.origin; plant_angles = self.angles; } if (isdefined(level.check_force_deploy_origin)) { if (player [[level.check_force_deploy_origin]](self, plant_origin, plant_angles)) { plant_origin = player.origin; plant_angles = player.angles; self.plant_parent = player; } } else if (isdefined(level.check_force_deploy_z)) { if (player [[level.check_force_deploy_z]](self, plant_origin, plant_angles)) plant_origin = (plant_origin[0], plant_origin[1], player.origin[2] + 10); } if (isdefined(iswallmount) && iswallmount) self ghost(); replacement = player [[level.zombie_equipment[equipment].place_fn]](plant_origin, plant_angles); if (isdefined(replacement)) { replacement.owner = player; replacement.original_owner = player; replacement.name = self.name; player notify("equipment_placed", replacement, self.name); if (isdefined(level.equipment_planted)) player [[level.equipment_planted]](replacement, equipment, self.plant_parent); player maps\mp\zombies\_zm_buildables::track_buildables_planted(self); } if (isdefined(self)) self delete(); } }