function DetermineGiantPlayer() { local PositivePriority = []; local NegativePriority = []; local NoPriorty = [] local Priority = { [1057] = PositivePriority, [1059] = NegativePriority } for (local ent; ent = FindByClassname(ent, "player");) { if (ent.GetTeam() != 3 && ent in NoPriorty || ent in Priority) continue for (local wearable = ent.FirstMoveChild(); wearable != null; wearable = wearable.NextMovePeer()) { local cosmetic_id = NetProps.GetPropInt(wearable, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") if(ent.GetTeam() == 3 && cosmetic_id in Priority) { Priority[cosmetic_id].append(ent); } else if (ent.GetTeam() == 3) { NoPriorty.append(ent) break } break } } PopExtUtil.PrintTable(Priority) PopExtUtil.PrintTable(NoPriorty) if (0 in PositivePriority) { local player = PositivePriority[RandomInt(0, PositivePriority.len() - 1)] printl("picked player is (+1 priority): "+player) BecomeGiant(player) } else if (0 in NoPriorty) { local player = NoPriorty[RandomInt(0, NoPriorty.len() - 1)] printl("picked player is (no priority): "+player) BecomeGiant(player) } else if (0 in NegativePriority) { local player = NegativePriority[RandomInt(0, NegativePriority.len() - 1)] printl("picked player is (-1 priority): "+player) BecomeGiant(player) } else { return } } function PickGiantWeaponFunc(player) { player.ValidateScriptScope() local scope = player.GetScriptScope() ::PickWeapon <- function() { local selector_buttons = NetProps.GetPropInt(self, "m_nButtons"); local selector_buttons_changed = selector_buttons_last ^ selector_buttons; local selector_buttons_pressed = selector_buttons_changed & selector_buttons; local selector_buttons_released = selector_buttons_changed & (~selector_buttons); //yeah chatgpt wrote this function //haters gonna hate function EquipLoadout(user) { local class_string = PopExtUtil.ClassesCaps[self.GetPlayerClass()]; // Get the player's class // Increment or reset giant_type if (giant_type < 2) { giant_type++; } else { giant_type = 0; } printl("giant type is: " + giant_type); // Define Giant Loadout Options local Giant_Loadout_Options = { "Scout" : { "Chief Scout" : { "ChiefType" : 0, "Tips": { "(i) A powerful, speedy duelist who specialises in taking on Giants." : 1, "(i) Applying Marked-for-Death with each shot to one enemy at a time, this Chief serves as a balance between power and speed." : 2, "(i) Players who consistently achieve high damage as Scout (or who play less support and more damage) should pick this Chief." : 3 }, "tf_weapon_scattergun" : { "WepID" : 200, "damage bonus" : 3, "fire rate penalty" : 2 "faster reload rate" : 0.5 "hold fire until full reload" : 1 "mark for death" : 1 } }, "Chief Sandman" : { "ChiefType" : 1, "Tips": { "(i) A much bulkier, supportive Chief who rapidly fires off explosive baseballs." : 1, "(i) Specialising in survival through vertical mobility and crowd control, getting consistent hits will be devastating!" : 2, "(i) Best for less skilled Scouts" : 3 }, "tf_weapon_bat_wood" : { "WepID" : 44, "dmg penalty vs players" : 2, "effect bar recharge rate increased" : 0.1 "max health additive penalty" : 0 "increased jump height" : 2 "move speed penalty" : 0.85 "cancel falling damage" : 1 //"damage bonus hidden" : 0.1556 "max health additive bonus" : 15000 } }, "Chief Burst" : { "ChiefType" : 2, "tf_weapon_scattergun" : { "WepID" : 45, "damage bonus" : 2, "faster reload rate" : 0.5 } } }, "Heavy" : { "Chief Heavy" : { "ChiefType" : 0, "tf_weapon_minigun" : { "WepID" : 202, "damage bonus" : 2 } } } }; PopExtUtil.StripWeapon(user, 0) PopExtUtil.StripWeapon(user, 1) PopExtUtil.StripWeapon(user, 2) // Iterate over the Giant_Loadout_Options to check the player's class foreach (giant_class, loadout in Giant_Loadout_Options) { // Check if the current class matches the player's class if (giant_class == class_string) { printl("We are playing as: " + class_string); // Loop over the chief class loadout foreach (chief_title, chief_data in loadout) { // Check if the ChiefType matches the current giant_type if (chief_data["ChiefType"] == giant_type) { printl("ChiefType matches giant_type: " + giant_type + " for " + chief_title); // Display the tips to the player using ClientPrint if ("Tips" in chief_data) { foreach (tip, line_number in chief_data["Tips"]) { ClientPrint(user, 3, tip); // Send the tip to the player printl("Displayed tip: " + tip); } } // Loop over the weapons in the chief's data to find the weapon details foreach (weapon_class, weapon_data in chief_data) { if (typeof weapon_data == "table" && "WepID" in weapon_data) { local className = weapon_class; // e.g., "tf_weapon_scattergun" local itemID = weapon_data["WepID"]; // e.g., 200 // Give the player the weapon local weapon = PopExtUtil.GiveWeapon(user, className, itemID); // Now apply each attribute (except for WepID) foreach (attrib_name, attrib_value in weapon_data) { // Skip WepID since it's not an actual attribute if (attrib_name != "WepID") { // Apply the attribute to the weapon weapon.AddAttribute(attrib_name, attrib_value, -1); printl("Applied attribute: " + attrib_name + " with value: " + attrib_value); } } printl("Gave player weapon: " + className + " with ID: " + itemID); } } } } } user.SetHealth(user.GetMaxHealth()) } } // When the reload button is pressed, check the giant_type and equip corresponding loadout if (selector_buttons_pressed & Constants.FButtons.IN_RELOAD) { printl("Player pressed reload"); EquipLoadout(self); } // Fallback: If giant_type is -1, equip the loadout if (giant_type == -1) { EquipLoadout(self); } selector_buttons_last = selector_buttons; } scope.selector_buttons_last <- 0 scope.giant_type <- -1 PopExtUtil.AddThinkToEnt(player, "PickWeapon") } function BecomeGiant(ent) { NetProps.SetPropBool(ent, "m_bUseBossHealthBar", true) ent.SetIsMiniBoss(true) ent.SetModelScale(1.75, -1) ent.AddCustomAttribute("healing received penalty", 0.5, -1) //cannot remove attribs, override resistences with this ent.AddCustomAttribute("dmg taken from fire reduced", 1, -1) ent.AddCustomAttribute("dmg taken from crit reduced", 1, -1) ent.AddCustomAttribute("dmg taken from blast reduced", 1, -1) ent.AddCustomAttribute("dmg taken from bullets reduced", 1, -1) local giant_classes = { "Scout" : { "max health additive bonus" : 15000 "damage force reduction" : 0.7 "airblast vulnerability multiplier" : 0.7 "crit mod disabled" : 0 } "Soldier" : { "max health additive bonus" : 15000 "damage force reduction" : 0.4 "airblast vulnerability multiplier" : 0.4 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 } "Pyro" : { "max health additive bonus" : 12500 "damage force reduction" : 0.6 "airblast vulnerability multiplier" : 0.6 "move speed penalty" : 0.5 "no_jump" : 1 "crit mod disabled" : 0 "no_duck" : 1 } "Demoman" : { "max health additive bonus" : 12500 "damage force reduction" : 0.5 "airblast vulnerability multiplier" : 0.5 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 } "Heavy" : { "max health additive bonus" : 60000 "damage force reduction" : 0.2 "airblast vulnerability multiplier" : 0.2 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 } "Engineer" : { "max health additive bonus" : 10000 "damage force reduction" : 0.5 "airblast vulnerability multiplier" : 0.5 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 } "Medic" : { "max health additive bonus" : 17500 "damage force reduction" : 0.5 "airblast vulnerability multiplier" : 0.5 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 "heal rate bonus" : 200 } "Sniper" : { "max health additive bonus" : 10000 "damage force reduction" : 0.5 "airblast vulnerability multiplier" : 0.5 "move speed penalty" : 0.5 "no_duck" : 1 "no_jump" : 1 "crit mod disabled" : 0 } "Spy" : { "max health additive bonus" : 10000 "damage force reduction" : 0.5 "airblast vulnerability multiplier" : 0.5 "move speed penalty" : 0.5 // "no_duck" : 1 // "no_jump" : 1 "crit mod disabled" : 0 } } local sound_range = (40 + (20 * log10(300 / 36.0))).tointeger(); ClientPrint(ent, 4, "!!! YOU ARE THE VIP. DO NOT DIE. !!!") ent.EmitSound("items/powerup_pickup_team_revenge.wav") ent.Teleport(true, ent.GetOrigin() + Vector(0, 0, 25), true, ent.EyeAngles(), false, Vector(0, 0, 0)) ent.SetHealth(ent.GetMaxHealth()) foreach(player_class, attribs in giant_classes) { local get_class_string = ["", "Scout", "Sniper", "Soldier", "Demoman", "Medic", "Heavy", "Pyro", "Spy", "Engineer", "Civilian"] local get_cur_class = get_class_string[ent.GetPlayerClass()] local health = ent.GetMaxHealth() if (player_class == get_cur_class) { foreach (attrib_name, attrib_value in attribs) { if (attrib_name == "max health additive bonus") { //ensure that health bonus/health penalty weapons dont cause weird values ent.AddCustomAttribute(attrib_name, attrib_value - health, -1) } else { ent.AddCustomAttribute(attrib_name, attrib_value, -1) } } break } } PickGiantWeaponFunc(ent) } ::HavanaWave2_Namespace <- { Cleanup = function() { // cleanup any persistent changes here // keep this at the end delete ::HavanaWave2_Namespace } // mandatory events OnGameEvent_recalculate_holidays = function(_) { if (GetRoundState() == 3) Cleanup() } OnGameEvent_mvm_wave_complete = function(_) { Cleanup() } OnScriptHook_OnTakeDamage = function(params) { local victim = params.const_entity local weapon = params.weapon local attacker = params.attacker local entity = params.inflictor local damage = params.damage local dmgtype = params.damage_type local dmg_special = params.damage_stats local item_name_id = NetProps.GetPropInt(weapon, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") if (attacker.GetTeam() == 3 && attacker.IsMiniBoss() && dmg_special == 22) { local factor = 1.0 local damagetype = 64 //dmg_acid causes damage to be auto multiplied? if (dmgtype & DMG_ACID) { if (IsMiniCritAttacker(attacker) || IsMiniCritVictim(victim)) { //if the attacker is critboosted and the victim is minicritted, use crit dmg calcs if (IsCritAttacker(attacker) && IsMiniCritVictim(victim)) { //factor = 3.0 damagetype = damagetype + 1048576 } else { //factor = 1.35 damagetype = damagetype + 1048576 } } else { //factor = 3.0 damagetype = damagetype + 1048576 } } DispatchParticleEffect("ExplosionCore_MidAir", victim.GetOrigin() + Vector(0, 0, 50), Vector(0, 0, 0)) for (local player; player = FindByClassnameWithin(player, "player", victim.GetOrigin(), 200);) { if (player.GetTeam() != attacker.GetTeam() && player.GetTeam() != TEAM_SPECTATOR) { if (!(dmgtype & 128)) return player.TakeDamageEx(null, attacker, null, Vector(0, 0, 0), player.GetOrigin(), 45, damagetype) } } victim.RemoveCondEx(15, true) } } }; __CollectGameEventCallbacks(HavanaWave2_Namespace)