--I didn't want to make yet another file that'll have to be stored on the archives for all of eternity but the LuaScript block is a piece of shit --that can't store more than 4096 characters, which makes it useless for storing mission specific scripts (which is all you'd ever use it for) AddEventCallback("mvm_reset_stats", function () for _, player in pairs(ents.GetAllPlayers()) do player.m_debugOverlays = player.m_debugOverlays & ~0x02000000 end end) local function removeCallbacks(player, callbacks) if not IsValid(player) then return end for _, callbackId in pairs(callbacks) do player:RemoveCallback(callbackId) end end local activeSpyChief = nil function DemoknightChargeLeapChief(_, activator) local callbacks = {} local check local terminated = false local mimic local function terminate() if terminated then return end terminated = true timer.Stop(check) if mimic:IsValid() then mimic:DetonateStickies() mimic:Remove() end removeCallbacks(activator, callbacks) end --this assumes that these weapons will not be replaced with new ones, but is more optimized due to not getting them every tick local shield = activator:GetPlayerItemBySlot(1) local chargeSpeedMult = shield:GetAttributeValueByClass("mod_charge_time", 1) local chargeTurningControlMult = activator:GetAttributeValue("mult charge turn control", true) local phaseTwoHealth = activator.m_iHealth * 0.66 local phaseThreeHealth = activator.m_iHealth * 0.33 local mimicFireDuration = 0.15 local mimicFireEnabled = true --This "fills" with time local mimicFireDurationBucket = 0 --local adaptiveChargeSystemEnabled = false timer.Simple(0.01, function() --We spawn and attach the mimic within the popfile, but we grab and control it with lua local mimicTable = ents.FindAllByClass("tf_point_weapon_mimic") for _, entity in pairs(mimicTable) do if entity.m_iName == "hussarBomber" then mimic = entity mimic.m_iName = "ClaimedByScript" break end end end) activator.m_flChargeMeter = 50 if (chargeTurningControlMult ~= nil and chargeTurningControlMult > 3) or activator:GetAttributeValue("full charge turn control", true) then chargeTurningControlMult = 3 end local isCharging = false check = timer.Create(0.015, function() if not IsValid(activator) or not activator:IsAlive() then terminate() return end if not shield:IsValid() then shield = activator:GetPlayerItemBySlot(1) chargeSpeedMult = shield:GetAttributeValueByClass("mod_charge_time", 1) chargeTurningControlMult = activator:GetAttributeValue("mult charge turn control", true) end if isCharging == true and activator:InCond(125) ~= true then shield:SetAttributeValue("increased air control", 1) shield:SetAttributeValue("dmg taken increased", 1) isCharging = false mimic:DetonateStickies() mimicFireDurationBucket = 0 end if activator:InCond(17) then --done to guarantee that the charge scream will play, and to ensure the leap doesn't stack multiple times. timer.Simple(0.01, function() if activator:InCond(17) then activator:RemoveCond(17) isCharging = true shield:SetAttributeValue("increased air control", chargeTurningControlMult) shield:SetAttributeValue("dmg taken increased", 1.4) local currentVelocity = activator.m_vecAbsVelocity local editedVelocity --local chargeDistanceModifier = 1 --if adaptiveChargeSystemEnabled == true then --local chargeDistanceModifierTable = { --"TARGET_NONE" = 1, --"TARGET_FAR" = 1.5, --"TARGET_MEDIUM" = 1, --"TARGET_CLOSE" = 0.5, --"TARGET_MELEERANGE" = 0, --} --chargeDistanceModifier = chargeDistanceModifierTable[shield:GetAttributeValue("hidden string attribute 1", true)] --end editedVelocity = Vector(currentVelocity[1],currentVelocity[2],(currentVelocity[3] + (600 * chargeSpeedMult))) activator:AddOutput("BaseVelocity " .. editedVelocity[1] .. " " .. editedVelocity[2] .. " " .. editedVelocity[3]) activator:SetForwardVelocity(500 * chargeSpeedMult) activator:AddCond(125, 1.2) end end) end if activator:InCond(125) then if mimicFireEnabled == true then mimicFireDurationBucket = mimicFireDurationBucket + 0.015 end if mimicFireDurationBucket >= mimicFireDuration then mimic:FireOnce() mimicFireDurationBucket = 0 end end if activator.m_iHealth <= phaseTwoHealth and activator.m_iHealth > phaseThreeHealth then mimicFireDuration = 0.10 elseif activator.m_iHealth < phaseThreeHealth then mimicFireEnabled = false --adaptiveChargeSystemEnabled = true end end, 0) callbacks.died = activator:AddCallback(ON_DEATH, function() terminate() end) callbacks.removed = activator:AddCallback(ON_REMOVE, function() terminate() end) callbacks.spawned = activator:AddCallback(ON_SPAWN, function() terminate() end) end local function getEyeAngles(player) local pitch = player["m_angEyeAngles[0]"] local yaw = player["m_angEyeAngles[1]"] return Vector(pitch, yaw, 0) end --adaptation of checkIfMeleeHitGauntletEmbodiment in my upgrade lua file, does not have a damage bonus component --does not check for teammate collision due to bots not stuffing melee hits, and it uses 175 instead of 100 to account for giant melee range. function CheckIfMeleeHitHussar(param, activator, calller) if not util.IsLagCompensationActive() then util.StartLagCompensation(activator) end local melee = activator:GetPlayerItemBySlot(2) local meleeSpeedBonus if not melee:GetAttributeValue("fire rate bonus", true) then meleeSpeedBonus = 1 else meleeSpeedBonus = melee:GetAttributeValue("fire rate bonus", true) end local TraceLineOfSight = { start = activator, -- Start position vector. Can also be set to entity, in this case the trace will start from entity eyes position distance = 175, -- Used if endpos is nil angles = getEyeAngles(activator), -- Used if endpos is nil mask = MASK_SOLID, -- Solid type mask, see MASK_* globals collisiongroup = COLLISION_GROUP_PLAYER, -- Pretend the trace to be fired by an entity belonging to this group. See COLLISION_GROUP_* globals } local lineOfSightTraceTable = util.Trace(TraceLineOfSight) local hitEntity = lineOfSightTraceTable.Entity if IsValid(hitEntity) and (hitEntity:IsPlayer() or hitEntity:IsObject() or hitEntity:IsNPC()) and hitEntity.m_iTeamNum ~= activator.m_iTeamNum then melee:SetAttributeValue("fire rate bonus", (meleeSpeedBonus - 0.05)) meleeSpeedBonus = meleeSpeedBonus - 0.05 if meleeSpeedBonus < 0.5 then melee:SetAttributeValue("fire rate bonus", 0.5) end --if we miss, we reduce our bonus slightly else melee:SetAttributeValue("fire rate bonus", (meleeSpeedBonus + 0.1)) meleeSpeedBonus = meleeSpeedBonus + 0.1 end if meleeSpeedBonus > 1 then meleeSpeedBonus = 1 melee:SetAttributeValue("fire rate bonus", 1) end util.FinishLagCompensation(activator) end local function spawnSkeletons(owner, angleIncrement, skeletonOrigin, skeletonCount) local pivotedAngle = 0 local skeletonTable = { TeamNum = owner.m_iTeamNum, origin = tostring(skeletonOrigin), angles = tostring(Vector(0, 0, 0)), } if skeletonCount > 1 then for i=0,(skeletonCount - 1),1 do local skellington = ents.CreateWithKeys("tf_projectile_spellspawnzombie", skeletonTable, true, true) skellington.m_hThrower = owner skellington:SetAbsAngles(Vector(0, pivotedAngle, 0)) skellington:SetForwardVelocity(400) pivotedAngle = pivotedAngle + angleIncrement end else local skellington = ents.CreateWithKeys("tf_projectile_spellspawnzombie", skeletonTable, true, true) skellington.m_hThrower = owner end end function spyChiefTaunt(tauntIndex, activator) local skellingtonOrigin = (activator:GetAbsOrigin() + Vector(0,0,20)) spawnSkeletons(activator, 72, skellingtonOrigin, 5) end function DesignateSpyChief(_, activator) local callbacks = {} local check local terminated = false local function terminate() if terminated then return end terminated = true removeCallbacks(activator, callbacks) timer.Stop(check) if activeSpyChief == activator then activeSpyChief = nil end end local swapLastUseTimestamp = CurTime() local swapCooldown = 10 local swapAggressive = 1 local chainSwap = false local function retrieveSwapTargets() local SwapTargets = {} for _, entity in pairs (ents.FindAllByClass("tf_zombie")) do if entity.m_iTeamNum == activator.m_iTeamNum then table.insert(SwapTargets, entity) end end for _, player in pairs(ents.GetAllPlayers()) do if player.m_iTeamNum == activator.m_iTeamNum and player.m_iClass == 8 and player:IsAlive() and player.m_szNetname == "Saboteur?" then table.insert(SwapTargets, player) end end return SwapTargets end local function swapWithTargetEntity(swapTarget) local targetPosition = swapTarget:GetAbsOrigin() local targetAngles = swapTarget:GetAbsAngles() local teleParticle2 = ents.CreateWithKeys("info_particle_system", { effect_name = "teleportedin_blue", start_active = 1, flag_as_weather = 0, }, true, true) teleParticle2:SetAbsOrigin(activator:GetAbsOrigin()) teleParticle2:Start() local teleParticle1 = ents.CreateWithKeys("info_particle_system", { effect_name = "teleportedin_blue", start_active = 1, flag_as_weather = 0, }, true, true) teleParticle1:SetAbsOrigin(targetPosition) teleParticle1:Start() swapTarget:SetAbsOrigin(activator:GetAbsOrigin()) swapTarget:SetAbsAngles(activator:GetAbsAngles()) activator:SetAbsOrigin(targetPosition) activator:SetAbsAngles(targetAngles) local allPlayers = ents.GetAllPlayers() for _, player in pairs(allPlayers) do player:AcceptInput("$PlaySoundToSelf", "weapons/teleporter_send.wav") end timer.Simple(1, function () teleParticle1:Remove() teleParticle2:Remove() end) --todo: add sound when this happens end local swapFunctionTable = { [1] = function() local swapTargets = retrieveSwapTargets() if type(next(swapTargets)) == "nil" then return false end local swapTargetsFiltered = {} local activatorAbsOrigin = activator:GetAbsOrigin() for _, entity in pairs (swapTargets) do if activatorAbsOrigin:Distance(entity:GetAbsOrigin()) < 400 then table.insert(swapTargetsFiltered, entity) end end if type(next(swapTargetsFiltered)) ~= "nil" then swapWithTargetEntity(swapTargets[math.random(#swapTargetsFiltered)]) return true else return false end end, [2] = function() local swapTargets = retrieveSwapTargets() if type(next(swapTargets)) == "nil" then return false end local redTeam = {} for _, player in pairs(ents.GetAllPlayers()) do if player.m_iTeamNum == 2 and player:IsAlive() then table.insert(redTeam, player) end end local furthestTargetFromSelf = nil local closestEnemyToFurthestTargetFromSelf = nil local closestTargetToEnemy = nil local furthestDistanceFromSelf = 0 local lowestDistanceToEnemy = 9999 local activatorAbsOrigin = activator:GetAbsOrigin() local averageDistanceFromSelf = 0 local averageDistanceToEnemy = 0 for _, entity in pairs (swapTargets) do local entityOrigin = entity:GetAbsOrigin() local distanceFromSelf = entityOrigin:Distance(activatorAbsOrigin) local closestEnemyToTargetDistance = 9999 for _, player in pairs(redTeam) do local playerAbsOrigin = player:GetAbsOrigin() local distanceToEnemy = playerAbsOrigin:Distance(entityOrigin) if distanceToEnemy < lowestDistanceToEnemy then lowestDistanceToEnemy = distanceToEnemy closestTargetToEnemy = entity closestEnemyToFurthestTargetFromSelf = player end if distanceToEnemy < closestEnemyToTargetDistance then closestEnemyToTargetDistance = distanceToEnemy end end if distanceFromSelf > furthestDistanceFromSelf then furthestTargetFromSelf = entity furthestDistanceFromSelf = distanceFromSelf end averageDistanceFromSelf = averageDistanceFromSelf + distanceFromSelf averageDistanceToEnemy = averageDistanceToEnemy + closestEnemyToTargetDistance end averageDistanceFromSelf = averageDistanceFromSelf / #swapTargets averageDistanceToEnemy = averageDistanceToEnemy / #swapTargets if closestTargetToEnemy:GetAbsOrigin():Distance(activatorAbsOrigin) > averageDistanceFromSelf then swapWithTargetEntity(closestTargetToEnemy) elseif furthestTargetFromSelf:GetAbsOrigin():Distance(closestEnemyToFurthestTargetFromSelf:GetAbsOrigin()) < averageDistanceToEnemy then swapWithTargetEntity(furthestTargetFromSelf) else local coinFlip = math.random(1,2) coinFlipTable = {closestTargetToEnemy, furthestTargetFromSelf} swapWithTargetEntity(coinFlipTable[coinFlip]) end return true end, } local phase2Health = activator.m_iHealth * 0.5 local phase3Health = activator.m_iHealth * 0.25 check = timer.Create(0.5, function() if not IsValid(activator) or not activator:IsAlive() then terminate() return end if CurTime() > (swapLastUseTimestamp + swapCooldown) and activator:InCond(7) == false then if chainSwap == true then for i=0,math.random(2,4),1 do timer.Simple(0.8 + (i * 0.5), function() swapFunctionTable[swapAggressive]() end) end swapLastUseTimestamp = CurTime() else if swapFunctionTable[swapAggressive]() == false then swapLastUseTimestamp = swapLastUseTimestamp + 3 else swapLastUseTimestamp = CurTime() end end end if activator.m_iHealth <= phase2Health and activator.m_iHealth > phase3Health then swapAggressive = 2 swapCooldown = 8.5 end if activator.m_iHealth <= phase3Health then chainSwap = true swapCooldown = 9.5 end end, 0) activeSpyChief = activator callbacks.died = activator:AddCallback(ON_DEATH, function() terminate() end) callbacks.removed = activator:AddCallback(ON_REMOVE, function() terminate() end) callbacks.spawned = activator:AddCallback(ON_SPAWN, function() terminate() end) --65% resistance to knife damage while taunting callbacks.damaged = activator:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(_, damageinfo) if not damageinfo.Weapon then return end if activator:InCond(7) and damageinfo.Weapon.m_iClassname == "tf_weapon_knife" then damageinfo.Damage = damageinfo.Damage * 0.35 return true end return end) end function SpyDecoyTeleport(_, activator) if activeSpyChief ~= nil then activator:SetAbsOrigin(activeSpyChief:GetAbsOrigin()) end end