-- Hi, hi. -- I added this nut file for the ease of reading my popfile. -- since Floro said you can't add weapon rebalances, anymore -- most of these are just QoL -- No Crumpkin -- No Zombie Model -- Metro-specific Upgrade Station Music -- and changes current Mission name to Subtle Machination -- DEBUG. DEBUG. DEBUG. Help me. Someone please. -- I called out to the void, but nobody came! :c -- try { IncludeScript("sif_metro.nut") } -- catch (e) { ClientPrint(null,3,"Can't parse sif_metro.nut.. Additional content will not be loaded.") } debug = false -- AAAA ;w; -- This part was used in beta_debugging which allows me to respawn faster with ungodly amount of HP. Taken from Pea's testing on decay. --for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) --{ -- local player = PlayerInstanceFromIndex(i) -- -- if (player == null) continue -- If there is a player, continue.. -- if (player.IsFakeClient()) -- ..and that player on RED is not a bot, continue.. -- if (debug) -- If debug is true, then.. -- { -- for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) -- If the server is currently local, then.. -- { -- local player = PlayerInstanceFromIndex(i) -- Look for player name in the Index range -- if (NetProps.GetPropString(player, "m_szNetworkIDString") == "[U:1:221747537]") -- That says SiF -- { -- player.SetHealth(621621621) -- Set their heealth to.. -- player.SetMoveType(8, 0) -- Allow them to noclip.. -- player.AddCurrency(10000) -- Give this amount of credits to them.. -- } -- } -- } --} -- This was from Lite or idk honestly. -- Mimicry Players as I would call it. -- Look for Reds function GetAllPlayersOfType(iTeamNums = null, bAlive = null, bBot = null) { local Players = [] local bCheckTeamNum = iTeamNums != null local bCheckAlive = bAlive != null local bCheckBot = bBot != null for(local i = 1; i <= MAX_CLIENTS; i++) { local hPlayer = PlayerInstanceFromIndex(i) if(hPlayer && (bCheckTeamNum ? iTeamNums.find(hPlayer.GetTeam()) != null : true) && (bCheckAlive ? hPlayer.IsAlive() == bAlive : true) && (bCheckBot ? hPlayer.IsBotOfType(TF_BOT_TYPE) == bBot : true)) Players.append(hPlayer) } return Players } -- Pull a random one function GetRandomPlayer(iTeamNums = null, bAlive = null, bBot = null) { local Players = GetAllPlayersOfType(iTeamNums, bAlive, bBot) local ArrayLength = Players.len() if(ArrayLength > 0) return Players[RandomInt(0, ArrayLength - 1)] else return null } -- and make sure they are RED SelectedFromShuffle = [] function GetRandomPlayerShuffle(iTeamNums = null, bAlive = null, bBot = null) { local Players = GetAllPlayersOfType(iTeamNums, bAlive, bBot) local Delete = [] foreach(hPlayer in SelectedFromShuffle) { local Index = Players.find(hPlayer) if(Index != null) Players.remove(Index) } local ArrayLength = Players.len() if(ArrayLength > 0) { local hSelectedPlayer = Players[RandomInt(0, ArrayLength - 1)] SelectedFromShuffle.append(hSelectedPlayer) return hSelectedPlayer } else if(SelectedFromShuffle.len() == 0) return null else { SelectedFromShuffle.clear() return GetRandomPlayerShuffle(iTeamNums, bAlive, bBot) } } function SetDoppelganger(hBot, hPlayer) { if(!hPlayer && hBot) { hBot.TakeDamage(hBot.GetHealth() + 10, DMG_ALWAYSGIB, hBot); return } else if(!hBot) return local iClass = hPlayer.GetPlayerClass() local sClassIcon = GetPropString(hBot, "m_PlayerClass.m_iszClassIcon") local bGiant = hBot.IsMiniBoss() local bHealthBar = GetPropBool(hBot, "m_bUseBossHealthBar") local vecOrigin = hBot.GetOrigin() local angRotation = hBot.EyeAngles() SetPropInt(hBot, "m_Shared.m_iDesiredPlayerClass", iClass) hBot.SetPlayerClass(iClass) hBot.DispatchSpawn() local OldItems = [] for(local hChild = hBot.FirstMoveChild(); hChild; hChild = hChild.NextMovePeer()) if(HasProp(hChild, "m_AttributeManager") && hChild.GetClassname() != "tf_wearable") OldItems.append(hChild) foreach(hItem in OldItems) hItem.Kill() hBot.SetAbsOrigin(vecOrigin) hBot.SnapEyeAngles(angRotation) SetPropString(hBot, "m_PlayerClass.m_iszClassIcon", sClassIcon) hBot.SetIsMiniBoss(bGiant) hBot.SetUseBossHealthBar(bHealthBar) SetFakeClientConVarValue(hBot, "name", GetPropString(hPlayer, "m_szNetname") + "็" + " (Dead)") hBot.SetHealth(hBot.GetMaxHealth()) hBot.SetCustomModelWithClassAnimations(hPlayer.GetModelName()) local hWeapon = hPlayer.GetActiveWeapon() if(!hWeapon) return local iCurrentSlot = hWeapon.GetSlot() local CopyAttributes = [ "always crit" "blast radius increased" "minicrits become crits" "mod_maxhealth_drain_rate" "mult bleeding delay" "mult bleeding dmg" "mult crit dmg" "mult_player_movespeed_active" "speed_boost_on_hit" "stickybomb charge rate" "unique craft index" "airblast pushback scale" "ammo regen" "applies snare effect" "armor piercing" "attack projectiles" "bidirectional teleport" "bleeding duration" "building instant upgrade" "canteen specialist" "charge recharge rate increased" "clip size bonus upgrade" "clip size upgrade atomic" "critboost on kill" "damage bonus" "damage force reduction" -- "dmg taken from blast reduced" -- "dmg taken from bullets reduced" -- "dmg taken from crit reduced" -- "dmg taken from fire reduced" "effect bar recharge rate increased" "engy building health bonus" "engy dispenser radius increased" "engy disposable sentries" "engy sentry fire rate increased" "explode_on_ignite" "explosive sniper shot" "falling_impact_radius_stun" "faster reload rate" "fire rate bonus" "fire rate bonus" "generate rage on damage" "generate rage on heal" "heal on kill" "healing mastery" "health regen" "increase buff duration" "mad milk syringes" "mark for death" "max health additive bonus" "maxammo grenades1 increased" "maxammo metal increased" "maxammo primary increased" "maxammo secondary increased" "melee attack rate bonus" "move speed bonus" "mult_item_meter_charge_rate" "overheal expert" "projectile penetration heavy" "projectile penetration" "projectile speed increased" "robo sapper" "rocket specialist" "SRifle Charge rate increased" "thermal_thruster_air_launch" "uber duration bonus" "ubercharge rate bonus" "weapon burn dmg increased" "weapon burn time increased" "attach particle effect static" "attach particle effect" "custom_paintkit_seed_hi" "custom_paintkit_seed_lo" "is australium item" "item style override" "killstreak effect" "killstreak idleeffect" "killstreak tier" "paintkit_proto_def_index" "set item tint RGB 2" "set item tint RGB" "set_item_texture_wear" "style changes on strange level" ] local GiveItem = function(hPlayer, sClassname, iItemIndex) { local bWearable = !startswith(sClassname, "tf_weapon") local iItemIndexReal = iItemIndex local sClassnameReal = sClassname if(bWearable) { iItemIndex = 1101 sClassname = "tf_weapon_parachute" } local hItem = CreateByClassname(sClassname) SetPropInt(hItem, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", iItemIndex) SetPropBool(hItem, "m_AttributeManager.m_Item.m_bInitialized", true) SetPropBool(hItem, "m_bValidatedAttachedEntity", true) hItem.SetTeam(hPlayer.GetTeam()) hItem.DispatchSpawn() if(bWearable) { hPlayer.Weapon_Equip(hItem) local hWearable = GetPropEntity(hItem, "m_hExtraWearable") hItem.Kill() SetPropString(hWearable, "m_iClassname", sClassnameReal) SetPropInt(hWearable, "m_nModelIndex", 0) SetPropInt(hWearable, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", iItemIndexReal) SetPropBool(hWearable, "m_AttributeManager.m_Item.m_bInitialized", true) hWearable.DispatchSpawn() SetPropBool(hWearable, "m_bForcePurgeFixedupStrings", true) hWearable.ValidateScriptScope() hWearable.GetScriptScope().Think <- function() { if("Shield" in this) Shield() if(!hPlayer.IsAlive()) { SetPropString(self, "m_iszScriptThinkFunction", "") EntFireByHandle(self, "RunScriptCode", "self.Kill()", 0.033, null, null) } return -1 } if(sClassnameReal == "tf_wearable_demoshield") { hWearable.AddAttribute("Attack not cancel charge", 1, -1) hWearable.GetScriptScope().Shield <- function() { if(GetPropInt(hPlayer, "m_nButtons") & IN_ATTACK && GetPropFloat(hPlayer, "m_Shared.m_flChargeMeter") >= 100) hPlayer.AddCond(TF_COND_SHIELD_CHARGE) } } AddThinkToEnt(hWearable, "Think") hItem = hWearable } else { hPlayer.Weapon_Equip(hItem) } return hItem } local WeaponBlacklist = [ "tf_weapon_builder" "tf_weapon_sapper" "tf_weapon_pda_engineer_build" "tf_weapon_pda_engineer_destroy" "tf_weapon_jar_milk" "tf_weapon_lunchbox" "tf_weapon_lunchbox_drink" "tf_weapon_buff_item" "tf_weapon_rocketpack" 265 ] local hPlayerManager = FindByClassname(null, "tf_player_manager") local iUserID = GetPropIntArray(hPlayerManager, "m_iUserID", hBot.entindex()) for(local hChild = hPlayer.FirstMoveChild(); hChild; hChild = hChild.NextMovePeer()) if(HasProp(hChild, "m_AttributeManager")) { local iWeaponSlot = "GetSlot" in hChild ? hChild.GetSlot() : -1 local sClassname = hChild.GetClassname() local iItemIndex = GetPropInt(hChild, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") if(WeaponBlacklist.find(sClassname) != null || WeaponBlacklist.find(iItemIndex) != null) continue if(sClassname == "tf_weapon_laser_pointer" && iItemIndex == 0) continue local hItem local flAttribute = hChild.GetAttribute("is commodity", 0) if(flAttribute < 0) continue local bIsCustomWeapon = flAttribute != 0 // we applied this to all custom weapons, no real way to check for a custom weapon without it if(bIsCustomWeapon) { hChild.KeyValueFromString("targetname", "whatisyouritemname") local hLua = CreateByClassname("$script_manager") hLua.AcceptInput("$ExecuteScript", format("ents.GetPlayerByUserId(%i):GiveItem(ents.FindByName('whatisyouritemname'):GetItemName()):SetName('heresdoppelsweaponcopy')", iUserID), null, null) hLua.Kill() hChild.KeyValueFromString("targetname", "") hItem = FindByName(null, "heresdoppelsweaponcopy") hItem.KeyValueFromString("targetname", "") } else { hItem = GiveItem(hBot, sClassname, iItemIndex) hItem.EnableDraw() } if(iWeaponSlot != -1 && hItem.GetSlot() == iCurrentSlot) { hBot.Weapon_Switch(hItem) hBot.AddCustomAttribute("disable weapon switch", 1, -1) } foreach(sAttr in CopyAttributes) { local Attr = hChild.GetAttribute(sAttr, 1337) if(Attr != 1337) hItem.AddAttribute(sAttr, Attr, -1) } if(sClassname == "tf_weapon_cannon") hItem.AddAttribute("grenade launcher mortar mode", 0, -1) if(sClassname == "tf_weapon_medigun" && iClass == TF_CLASS_CIVILIAN) hItem.AcceptInput("SetBodyGroup", "1", null, null) } foreach(sAttr in CopyAttributes) { local Attr = hPlayer.GetCustomAttribute(sAttr, 1337) if(Attr != 1337) hBot.AddCustomAttribute(sAttr, Attr, -1) } local ZombieCosmetics = [ 5617 5617 5625 5618 5620 5622 5619 5624 5623 5621 5621 ] local hZombie = GiveItem(hBot, "tf_wearable", ZombieCosmetics[iClass]) hZombie.GetScriptScope().CopyThink <- function() { if(!hPlayer || !hPlayer.IsValid() || !hPlayer.IsAlive()) return local hWeapon = hBot.GetActiveWeapon() local hPlayerWeapon = hPlayer.GetActiveWeapon() if(hWeapon && hPlayerWeapon) { local iSlot = hWeapon.GetSlot() local iPlayerSlot = hPlayerWeapon.GetSlot() if(iSlot != iPlayerSlot) { hBot.RemoveCustomAttribute("disable weapon switch") hBot.AcceptInput("$WeaponSwitchSlot", iPlayerSlot.tostring(), null, null) hBot.AddCustomAttribute("disable weapon switch", 1, -1) } } } if(iClass == TF_CLASS_CIVILIAN) { hZombie.AddAttribute("never gib", 1, -1) SetPropBool(hBot, "m_bForcedSkin", true) hZombie.DisableDraw() hZombie.GetScriptScope().Think <- function() { CopyThink() SetPropInt(hBot, "m_nForcedSkin", 3) if(!hBot.IsAlive()) { SetPropString(self, "m_iszScriptThinkFunction", "") SetPropBool(hBot, "m_bForcedSkin", false) SetPropInt(hBot, "m_nForcedSkin", 0) EntFireByHandle(self, "RunScriptCode", "self.Kill()", 0.033, null, null) } return -1 } } else { SetPropInt(hBot, "m_iPlayerSkinOverride", 1) hZombie.GetScriptScope().Think <- function() { CopyThink() if(!hBot.IsAlive()) { SetPropString(self, "m_iszScriptThinkFunction", "") SetPropInt(hBot, "m_iPlayerSkinOverride", 0) EntFireByHandle(self, "RunScriptCode", "self.Kill()", 0.033, null, null) } return -1 } } SendGlobalGameEvent("post_inventory_application", { userid = iUserID }) } -- This part changes the Mission Name once the mission loads in. --local ent = Entities.FindByClassname(null, "tf_objective_resource") --if (ent) --{ -- NetProps.SetPropString(ent, "m_iszMvMPopfileName", "Subtle Machination (Advanced)") --} function OnGameEvent_player_death(params) { local player = GetPlayerFromUserID(params.userid) local ent = null; while( ent = Entities.FindByClassname(ent, "tf_ammo_pack") ) { if (ent.GetEFlags() == 44302336) continue ent.SetEFlags(44302336) ent.SetMoveType(6, 0) ent.SetModel("models/items/ammopack_medium.mdl") } } -- This part plays music on both upgrade station -- credits to function spawnradiostation() { local radiostation1 = SpawnEntityFromTable("ambient_generic", { targetname = "radiostation1" message = "#upgradestation.mp3" origin = Vector(1018 4636 -115) -- I haven't changed this. health = 10 -- You can't kill this without console command, I've tried. spawnflags = 32 -- Loop this audio radius = 750 -- This will be heard up to this HU }) radiostation1.ValidateScriptScope() radiostation1.GetScriptScope().playtrack <- function() { EntFire("radiostation1", "playsound") return 61 } AddThinkToEnt (radiostation1, "playtrack") } function spawnradiostation2() { local radiostation2 = SpawnEntityFromTable("ambient_generic", { targetname = "radiostation2" message = "#upgradestation.mp3" origin = Vector(-78 4642 -35) -- Unchanged! health = 10 spawnflags = 32 radius = 750 }) radiostation2.ValidateScriptScope() radiostation2.GetScriptScope().playtrack <- function() { EntFire("radiostation2", "playsound") return 61 } AddThinkToEnt (radiostation2, "playtrack") } -- This part spawns the ambient_generic entity from the table, just like Hammer! spawnradiostation() spawnradiostation2() -- This part removes crumpkins. Credit to pea/ml team idk honestly. RemoveCrumpkins_Think = function() { for (local ent; ent = Entities.FindByModel(ent, "models/props_halloween/pumpkin_loot.mdl"); ) ent.Kill() } -- and this part removes Zombie models. -- What the hell does these code means? I don't hecking know, ask the ML team. CleanUpZombies_Think = function() { if (NetProps.GetPropBool(objective_resource_entity, "m_bMannVsMachineBetweenWaves")) return -1 zombies_active = 0 for (local player; player = Entities.FindByClassname(player, "player"); ) { if (player == null) continue if (player.IsFakeClient() && player.GetTeam() == 2) zombies_active = zombies_active + 1 } -- skipping slot 0 since it's always occupied by the zombies for (local i = 1; i <= 11; i++) { local flags = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags", i) local amounts = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts", i) if ((flags == 1 || flags == 9) && amounts != 0) return -1 } for (local i = 1; i <= 11; i++) { local flags = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassFlags2", i) local amounts = NetProps.GetPropIntArray(objective_resource_entity, "m_nMannVsMachineWaveClassCounts2", i) if ((flags == 1 || flags == 9) && amounts != 0) return -1 } } fire = Entities.CreateByClassname("tf_weapon_flamethrower") } AssignThinkToThinksTable("RemoveCrumpkins_Think") AssignThinkToThinksTable("CleanUpZombies_Think") __CollectGameEventCallbacks(this) -- This part is a remnant of the cut tweaks from beta 3 of this mission -- -- I have decided to leave the gas passer effect. -- -- UNUSED from BETA 3 --rebeltweak_wpn_ids = [] -- BETA 3 -- Rework LEFTOVER -- cba to delete these -- FEBRUARY 20 y 2024 -- Backscatter -> On BackHit: Target takes Critical, instead of minicrit. Fulfill the flank gimmick, drops med with no bs. -- Force-a-Nature -> On Hit: Target is slowed. -10% DMG penalty is still there, (Planned to be sodaPopper sidegrade.) -- PEPBlaster -> On Hit: Gain speed. No longer loses speed when shot, but your avg jump height is lower. -- Pistol -> Reworked to nailgun with KOK. -- Bonk -> While under PHASE effect, you are no longer slowed. (But You still lose milk, so your point?) -- Crit-a-Cola -> While under DMGBuff effect, gain speed boost. -- Guillotine -> On Hit: Target is Marked, If they are not currently burning, crit them for 150 damage -- Atomizer -> On Hit: Steal target's movement speed; Speedboost yourself. -- Bat -> Third Hit always crit for 105. -- Basher / Rune -> On Hit: Bleed and Debuffed. No longer able to hurt yourself, but you swing and switch slower. -- CandyCane -> Heal 50% more from credits and packs. -- Sandman -> On Hit: Stun (Slowed to a cripple). Stunned target takes more damage from you. -- Sun-on-a-Stick -> Deal target's current total afterburn as CRIT and extinguish them (Inspired by DD2's Plague Doctor's "Cause of Death") -- WrapAssasin -> On Hit: Target Loses 10% of their cloak / charges and Bleeds. Removed Damage Penalty. -- ^ i.e. spy would flicker, medic can't uber. -- LibertyLauncher -> Reworked to RPG that shoots slower, but hits hard -- RocketJumper -> Fires from Reserve Ammo, similar to beggar (Why are you using this anyway?) -- Bison -> +50% DMG bonus, projectile travels and fires a bit faster. -- BASEJumper -> Able to redeploy and gain increased air control. -- Buff Banner -> Increased switch speed (Added a buff since it was the only banner to not have passive) -- Gunboats -> Fall damage immunity, increases credit pickup radius. -- Mantreads -> On Stomped: Stun target for xsecs -- PanicAttack -> Reverted to old ver, Reload 4 shells and auto-fire when full -- Shotgun -> On Kill: Gain guaranteed Minicrit for xsecs.(it's still so bad) -- ReserveShooter -> Reworked to Para-Shotgun that becomes accurate and shoots faster while you are airborne -- Shovel -> Third Hit always crit for 195 + longer banner duration -- Equalizer -> +90% DMG bonus (Base 65 instead of 33 ). Blocks healing while active, reverted to Beta Equalizer. -- MarketGardener -> On Hit, whilst airborne: Target takes 300% more damage and their healer is also hit. -- PainTrain -> On Kill: Gain Speedboost, melee range increased. -- Zatoichi -> On Kill: Gain Critboost -- Degreaser -> Reworked to Afterburner that, airblast cost less and reflected projectile will CRIT, but your main DMG comes from afterburn -- Napalmer -> Reworked to Conductor that, Crits if wet, but Airblast no longer pushes target. -- Gas Passer -> Coated target will take up to (minicrit) 5x afterburn damage -- ManMelter -> +80% DMG bonus. If target is already burning, CRIT. -- <> Okay to be fair with you, Pyro melees suck if they don't give any passive / niche use. They excels at close range anyway!<> -- Axtinguisher -> On Hit: Apply current afterburn as Crit (191-371 DMG), -66 % less damage if target is not burning. -- FireAx -> On Kill: Gain Speedboost and Minicrit -- Homewreck/Maul -> Gain knockback resist and slight immunity while active. -- HotHand -> On Hit on Ally / Enemy: Gain Speedboost, range increased. -- NeonAnnihilator -> On Hit: Target Loses 15% their charge, On Kill: Gain Critboost. (because neon zaps robots, get it?) -- Volcano Fragment -> On Hit: Gain up to +25 HP, afterburn damage is upped -- GrenadeLauncher -> Reworked to Overloader that plays similarly to beggars, for variety -- LooseCannon -> On Hit: Cannonball Crits and Burn on impact 180 (instead of launching them airborne and it didn't kill anyway! like wtf?) -- Booty -> Fall damage immunity and increased resist. -- Bottle -> On Hit, whilst airborne: Deal Crit damage -- Caber -> Blast damage increased, No knockback -- HHHHeadtaker -> On Kill: Gain increased melee damage and speed -- Persuader -> 10% move speed bonus while charging, higher knockback resist (while doing so) -- Tomislav -> Damage pierces resist (?) -- IronCurtain -> Reworked to Ludmilla, that heals on hit but gain less overheal. -- BuffaloSteak -> Removed the -20% damage vulnerability (You are too hecking slow to dodge in the first place) -- Eviction -> On Hit: Crits (Pretend the increased swing speed funny or something) -- Fist -> Third hit crits? Wh- why would you use stock when KGB exist? -- Holiday Punch -> Always Crit, but deploy slower -- Pomson -> Projectile travels faster and penetrates, like how it should have been. -- Classic -> Headshot no longer requires 3s action of holding Mouse1. Why was it there? -- SMG -> On Kill: Gain Minicrits rebeltweak_wpn_ids = [1180] RebelTweak = function () { for (local i = 0; i <= rebeltweak_wpn_ids.len() - 1; i++) -- Logic 1, If the weak is up, then.. { for (local j = 0; j < 7; j++) -- Logic 2, Checking for Item slots 1 to 7 { local weapon = NetProps.GetPropEntityArray(self, "m_hMyWeapons", j) -- Check if the player has the following equipped if (weapon == null) continue -- They don't have any? Continue.. local weaponid = NetProps.GetPropInt(weapon, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") -- Let's see if they have.. if (weaponid == rebeltweak_wpn_ids[i]) -- Look up the list above, which is just gas passer { switch (weaponid) { case 1180: -- if they have Gas Passer active, { weapon.AddAttribute("attach particle effect", 12, -1.0) -- Attach massed Flies to their weapon -- weapon.AddAttribute("minicrit vs burning player", 1, -1.0) -- If target is coated, minicrit them -- weapon.AddAttribute("weapon burn dmg increased", 5, -1.0) -- If coated, afterburn is upped from 4 to 20 } } } break } } } -- BETA 4 -- -- Ha, you have nothing but Massed Flies Gas Passer! -- That's how depressed I feel honestly about this whole thing.