4U>nutscripts/vscriptsdirector_base_addon#QVPrecacheSound("player/survivor/swing/swing_miss1.wav"); PrecacheSound("player/survivor/hit/rifle_swing_hit_infected10.wav"); for(local i=1;i<=6;) PrecacheSound(format("player/survivor/splat/zombie_blood_spray_%02d.wav", i++)); if (!("MeleeThrowSettings" in getroottable())) ::MeleeThrowSettings <- { throw_force = 1000.0, upward_force = 0.0, spin = 3000.0, damage = 650, hit_time = 2.0 }; ::ThrownMelee <- {}; ::MeleeThrowButtons <- {}; ::GetInventoryWeapon <- function(p, slot) { try { return NetProps.GetPropEntityArray(p, "m_hMyWeapons", slot); } catch(e) { return null; } }; ::ThrowMelee <- function(player) { local w = player.GetActiveWeapon(); if (!w || !w.IsValid() || w.GetClassname() != "weapon_melee") return; local name = "fireaxe"; try { name = NetProps.GetPropString(w, "m_strMapSetScriptName"); } catch(e) {} w.Kill(); local eye = player.EyePosition(), ang = player.EyeAngles(), fwd = ang.Forward(), pos = eye + fwd * 40; local m = SpawnEntityFromTable("weapon_melee", { origin = format("%f %f %f", pos.x, pos.y, pos.z), angles = format("%f %f %f", ang.x, ang.y, ang.z), melee_script_name = name }); if (!m || !m.IsValid()) return; EmitSoundOn("player/survivor/swing/swing_miss1.wav", m); m.ApplyAbsVelocityImpulse(fwd * ::MeleeThrowSettings.throw_force + Vector(0, 0, ::MeleeThrowSettings.upward_force)); m.ApplyLocalAngularVelocityImpulse(Vector(0, ::MeleeThrowSettings.spin, 0)); ::ThrownMelee[m.GetEntityIndex()] <- { owner = player, hit_expire = Time() + ::MeleeThrowSettings.hit_time, hit = {} }; }; ::MeleeThrowThink <- function() { local remove = [], now = Time(); foreach(idx, data in ::ThrownMelee) { local m = EntIndexToHScript(idx); if (!m || !m.IsValid()) { remove.append(idx); continue; } local pickedUp = false, p = null; while ((p = Entities.FindByClassname(p, "player")) != null) { if (!p.IsValid() || !p.IsSurvivor()) continue; local slot = 0, inv = null; while ((inv = GetInventoryWeapon(p, slot)) != null) { if (inv.IsValid() && inv.GetEntityIndex() == idx) { pickedUp = true; break; } slot++; } if (pickedUp) break; } if (pickedUp) { remove.append(idx); continue; } if (now < data.hit_expire) { local pos = m.GetOrigin(), target = null; while ((target = Entities.FindInSphere(target, pos, 20)) != null) { if (target == m || target == data.owner || !target.IsValid()) continue; local cname = target.GetClassname(), id = target.GetEntityIndex(); if (id in data.hit) continue; data.hit[id] <- true; target.TakeDamage(::MeleeThrowSettings.damage, 16778324, data.owner); if (cname == "infected" || cname == "witch" || (cname == "player" && !target.IsSurvivor())) { EmitSoundOn("player/survivor/hit/rifle_swing_hit_infected10.wav", target); EmitSoundOn(format("player/survivor/splat/zombie_blood_spray_%02d.wav", RandomInt(1, 6)), target); local fx = SpawnEntityFromTable("info_particle_system", { effect_name = "blood_impact_infected_01", start_active = 1, origin = target.GetOrigin() }); if (fx && fx.IsValid()) { DoEntFire("!self", "Start", "", 0, null, fx); DoEntFire("!self", "Kill", "", 1, null, fx); } } } } else remove.append(idx); } foreach(idx in remove) if (idx in ::ThrownMelee) delete ::ThrownMelee[idx]; }; ::MeleeThrowUpdate <- function() { local p = null; while ((p = Entities.FindByClassname(p, "player")) != null) { if (!p.IsValid() || !p.IsSurvivor()) continue; local id = p.GetEntityIndex(), melee = null, slot = 0; while ((melee = GetInventoryWeapon(p, slot)) != null) { if (melee.IsValid() && melee.GetClassname() == "weapon_melee") break; slot++; } if (!melee || !melee.IsValid()) continue; local buttons = p.GetButtonMask(); if (!(id in ::MeleeThrowButtons)) ::MeleeThrowButtons[id] <- 0; local old = ::MeleeThrowButtons[id], combo = 133120; if ((buttons & combo) == combo && (old & combo) != combo) { p.SwitchToItem(melee.GetClassname()); ::ThrowMelee(p); } ::MeleeThrowButtons[id] = buttons; } ::MeleeThrowThink(); }; if (!("meleethrow_thinker" in getroottable())) { local t = SpawnEntityFromTable("info_target", { targetname = "meleethrow_thinker" }); if (t && t.IsValid()) { t.ValidateScriptScope(); t.GetScriptScope().Think <- function() { ::MeleeThrowUpdate(); return 0.05; }; AddThinkToEnt(t, "Think"); } }