--[[Design thoughts (subjective) Roguelikes in games typicallly follow a standard loop of progressing through a level giving the players power spikes and maintaining survival as the winning condition There are some parallels that can be applied to typical MvM (forgoing death as a lose condition), or you can choose to opt for a total gamemode replacement Some games to take inspiration from: Risk of Rain 2 Vampire Survivors (and heavily inspired Holocure, 20 Minutes Til Dawn) Hades The Binding of Issac Enter The Gungeon The most important thing to consider is how much control you want to give the players in terms of progression Currently this is done by the number of upgrades and rerolls given, but you can also come up with other methods Such as introducing another currency, or keeping the regular upgrade menu, or limiting which upgrades appear until a certain wave, or perhaps even introducing a "refund and craft upgrade system" Any mechanic you can think is possible in lua Some features I wanted to implement but got lazy: Picking upgrades from RNG based on what loadout you have Using ItemAttributes instead of CharacterAttributes Some sort of sensible refund/respec that isn't completely overpowered Possible form of "weighted RNG" to allow RNG manipulation and more nuanced upgrading choices "Style2" refers to the upgrade menu being rerolled after every purchase, there should be no duplicate upgrades in the shop so as not to waste slots Think Vampire Survivors/Hades "Style1" was when the upgrade menu behaved more similar to the regular shop, you could buy any choice of upgrades and it only rerolled on wave end ]] --[[Global variables MenuCapacity - How many upgrades can be stored in the menu, keep as integer Note that the sourcemod menu has a 512 byte limit, try to keep names/descriptions short Byte limit as opposed to a character limit means that inserting unicode characters which contain more than 1 byte will use up more of the limit You can use special characters like \n in sourcemod menus If you go above 7 selections (6+1 reroll selections) the sourcemod menu will display the Next and Previous buttons Personally I find this to be a bit clunky so I would stick with using a MenuCapacity of 6, 7 if you want to prevent accidental rerolls TotalUpgradePoints - Determines the starting amount of upgrade points on wave 1, and for any late joiners, keep as integer TotalRerollPoints - Determines the starting amount of upgrade points on wave 1, and for any late joiners, keep as integer]] MenuCapacity = 6 TotalUpgradePoints = 6 TotalRerollPoints = 1 UpgradePointsPerWave = 3 RerollPointsPerWave = 1 UpgradeCost = 500 RerollCost = 100 CanteenCritCost = 100 CanteenUberCost = 100 CanteenAmmoCost = 25 CanteenBuildingCost = 100 --[[AllShops is a table that controls what upgrades are shown to players, based on what class they are Note that it uses the game's interal reference for classes, which is different from their class selection screen order Each class can have any number of subtables or sub categories, I use this to define four different rarities You can also go for a shared upgrade pool between all classes, or Demo and Soldier etc.]] --attributes are defined as text on menu, attribute name, min, increment, max --[[The 1st field is actually the most important, as it used to uniquely identify upgrades, this allows the second field to exist beyond just attributes, and you can utilize "custom" to write a function that can do anything, as shown in Max Ammo and Mixed Concoction On Hit Note that max is typicallly optional for attributes, and if you're using "custom", min increment and max are also optional and can be defined in the AddUpgrade function instead]] AllShops = { ["RU"] = { [1] = --Scout Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, {"Обойма +50%", "clip size bonus",1,0.5}, -- {"Скорострельность +10%", "fire rate bonus",1,-0.1,0.1}, {"Скорострельность +20%", "firerate",1,0.2}, -- {"Скорость перезарядки +20%", "faster reload rate",1,-0.2,0.1}, {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +35", "max health additive bonus",0,35}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1,1.3}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Перезарядка расходника +15%", "effect bar recharge rate increased",1,0.15}, {"Резисты +15%", "resistance",1,-0.15,0.1}, -- {"Реген хп +2", "health regen",0,2}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, {"(RARE) Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Липкое молоко", "applies snare effect",1,-0.35,0.65}, {"(RARE) Точность +10%", "weapon spread bonus",1,-0.1,0.1}, {"(RARE) Резист к замедлению +50%", "mult stun resistance",1,-0.5,0}, -- {"(RARE) Урон вблизи +30%", "custom",1,0.3}, }, EpicAttribute = { {"[EPIC] Пуль за выстрел +50%", "bullets per shot bonus",1,0.5}, {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Продолжительность эффекта +50%", "mult effect duration",1,0.5}, {"[EPIC] Крит урон +30%", "mult crit dmg",1,0.3}, {"[EPIC] Невидим для турелей", "ignored by enemy sentries",0,1,1}, {"[EPIC] Доп. прыжок +1", "air dash count",0,1}, -- {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, }, LegendaryAttribute = { -- {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 Урон в воздухе +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 Урон по гигантам +100%", "mult dmg vs giants",1,1}, {"【LEGENDARY】 Урон кровотока +900%", "mult bleeding dmg",0,10}, {"【LEGENDARY】 75% Шанс уклониться от урона", "add cond when active",0,79,79}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [3] = --Soldier Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, --{"Primary: Clip Size +2", "clip size upgrade atomic",0,2}, {"Обойма +50%", "clip size bonus",1,0.5}, {"Скорострельность +20%", "firerate",1,0.2}, {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +40", "max health additive bonus",0,40}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, {"Радиус взрыва +25%", "Blast radius increased",1,0.25}, {"Скорость ракет +25%", "Projectile speed increased",1,0.25}, {"Баннеры: Длительность +25%", "increase buff duration",1,0.25}, -- {"Баннеры: Зарядка +25%", "rage giving scale",1,0.25}, {"Многразовый парашют", "parachute redeploy",0,1,1}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, {"(RARE) Спец по ракетам", "rocket specialist",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Иммун к падению", "cancel falling damage",0,1,1}, {"(RARE) Урон на аиршотах +50%", "mult dmg vs airborne",1,0.5}, {"(RARE) Само-урон -40%", "blast dmg to self increased",1,-0.4,0.2}, {"(RARE) Ракеты нельзя отразить", "projectile no deflect",0,1,1}, }, EpicAttribute = { {"[EPIC] Баннеры: радиус +25%", "mod soldier buff range",1,0.25}, {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, -- {"[EPIC] Быстрая смена оружия в рокет джампе", "mult rocketjump deploy time",1,-0.9,0.1}, {"[EPIC] Крит урон +30%", "mult crit dmg",1,0.3}, {"[EPIC] Урон за каждую цель внутри взрыва +10%", "add damage per target",0,0.1}, }, LegendaryAttribute = { {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Криты когда рокет джампишь", "mod crit while airborne",0,1,1}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Урон в воздухе +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 Скорострел. при рокет джампе +100%", "rocketjump attackrate bonus",1,-0.5,0.5}, {"【LEGENDARY】 Самонавод. ракеты", "homing",0,1,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [7] = --Pyro Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, {"Урон +25%", "damage bonus",1,0.25}, -- {"Урон +25%", "damage bonus",1,0.25}, {"Доп.: Обойма +50%", "clip size bonus",1,0.5}, {"Доп.: Скорострельность +20%", "firerate",1,0.2}, {"Доп.: Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +50", "max health additive bonus",0,50}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +2 health", "heal on hit for rapidfire",0,2}, -- {"Расход патронов -25%", "flame ammopersec decreased",1,-0.25,0}, {"Урон догорания +200%", "weapon burn dmg increased",1,2}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Флееры: Скорость снаряда +25%", "Projectile speed increased",1,0.25}, {"Джетпак: повтор. запуск", "thermal_thruster_air_launch",0,1,1}, {"Джетпак: Стан при приземлении", "falling_impact_radius_stun",0,1,1}, {"Сжатый воздух ускоряет союзников", "airblast_give_teammate_speed_boost",0,5,5}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, -- {"(RARE) Флог: Ммфф зарядка +50%", "rage giving scale",1,0.50}, {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Скор. отраженных снарядов +100%", "mult reflect velocity",1,1,2}, -- {"(RARE) Flame Size +50%", "flame size bonus",1,0.50}, -- {"(RARE) Flame Distance +50%", "flame life bonus",1,0.50}, {"(RARE) Расход патронов на аирбласт -25%", "airblast cost decreased",1,-0.25,0}, {"(RARE) Замедление при попадании", "slow enemy on hit",0,1,1}, {"(RARE) Огнемет: +20% дальность", "flame_speed",0,490}, {"(RARE) Сила аирбалста +30%", "airblast pushback scale",1,0.3}, }, EpicAttribute = { {"[EPIC] Дракон + Доп.: Перезарядка +15%", "mult_item_meter_charge_rate",1,-0.15,0.1}, {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Огнемет: Крит в спину", "mod flamethrower back crit",0,1,1}, {"[EPIC] Перезарядка аирбалста -50%", "mult airblast refire time",1,-0.5,0.5}, {"[EPIC] Урон в воздухе +30%", "mult dmg while midair",1,0.30}, }, LegendaryAttribute = { {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Крит урон +100%", "mult crit dmg",1,1}, {"【LEGENDARY】 Крит урон +100%", "mult crit dmg",1,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, }, Contraband = { {"/// CAUTION!! /// Взрывной газ", "explode_on_ignite",0,1,1}, } }, [4] = --Demoman Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, --{"Primary: Clip Size +2", "clip size upgrade atomic",0,2}, {"Обойма +50%", "clip size bonus",1,0.5}, {"Скорострельность +20%", "firerate",1,0.2}, {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +40", "max health additive bonus",0,40}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Щит: Перезарядка рывка +100%", "charge recharge rate increased",1,1}, {"Щит: Урон тарана +100%", "charge impact damage increased",1,1}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, {"Радиус взрыва +25%", "Blast radius increased",1,0.25}, {"Скорость снарядов +25%", "Projectile speed increased",1,0.25}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Липучки: Макс липучек +2", "max pipebombs increased",1,2}, {"Липучки: Скорость заряда +25%", "stickybomb charge rate",1,-0.25,0}, {"Липучки: Время готовности -0.2 сек.", "sticky arm time bonus",0,-0.2,-0.8}, {"Многразовый парашют", "parachute redeploy",0,1,1}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, {"(RARE) Ширина мили атаки +50%", "melee bounds multiplier",1,0.5}, {"(RARE) Дальность мили +25%", "melee range multiplier",1,0.25}, {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Иммун к падению", "cancel falling damage",0,1,1}, {"(RARE) Щиты: Время рывка +1 сек.", "charge time increased",1,1}, {"(RARE) Гранатомет: Взрыв при импакте", "grenade explode on impact",0,1,1}, {"(RARE) Мили отражает снаряды", "melee airblast",0,1,1}, {"(RARE) Само-урон -40%", "blast dmg to self increased",1,-0.4,0.2}, }, EpicAttribute = { {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, -- {"[EPIC] Щиты: Полный контроль", "full charge turn control",0,1,1}, {"[EPIC] Липучки: Урон при зарядке до +35%", "stickybomb_charge_damage_increase",1,0.35}, {"[EPIC] Мили бьет по области", "melee cleave attack",0,1,1}, {"[EPIC] Снаряды нельзя отразить", "projectile no deflect",0,1,1}, {"[EPIC] Крит урон +30%", "mult crit dmg",1,0.3}, }, LegendaryAttribute = { {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Криты когда рокет джампишь", "mod crit while airborne",0,1,1}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Урон в воздухе +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [6] = --Heavy Shop { CommonAttribute = { {"Доп.: Обойма +50%", "clip size bonus",1,0.5}, {"Скорострельность +20%", "firerate",1,0.2}, {"Доп.: Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Перезарядка бутера +20%", "effect bar recharge rate increased",1,-0.20,0.4}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +50", "max health additive bonus",0,50}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +2 health", "heal on hit for rapidfire",0,2}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Скорость раскрутки +15%", "minigun spinup time decreased",1,-0.15,0}, {"Скорость когда раскручен +20%", "aiming movespeed increased",1,0.20,1.6}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Урон +25%", "damage bonus",1,0.25}, {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Уничтожение снарядов", "attack projectiles",0,1,2}, {"(RARE) Ярость", "generate rage on damage",0,1,3}, {"(RARE) Можно убрать раскрученный пулемет", "mod minigun can holster while spinning",0,1,1}, {"(RARE) Замедление при попадании", "slow enemy on hit",0,1,1}, {"(RARE) Урон в воздухе +30%", "mult dmg while midair",1,0.3}, {"(RARE) Точность +10%", "weapon spread bonus",1,-0.1,0.1}, }, EpicAttribute = { {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Кольцо огня", "ring of fire while aiming",0,25,25}, {"[EPIC] Пуль за выстрел +25%", "bullets per shot bonus",1,0.25}, {"[EPIC] Пуль за выстрел +25%", "bullets per shot bonus",1,0.25}, {"[EPIC] Резист с раскрученным* пулеметом +20%", "spunup_damage_resistance",1,-0.2,0.4}, {"[EPIC] Крит урон +30%", "mult crit dmg",1,0.3}, }, LegendaryAttribute = { {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 +100% Урон по горящим", "damage bonus vs burning",1,1}, {"【LEGENDARY】 Урон +80% когда вас лечат", "mod medic healed damage bonus",1,0.8}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [9] = --Engineer Shop { CommonAttribute = { {"Оружия: Урон +25%", "damage bonus",1,0.25}, {"Оружия: Обойма +50%", "clip size bonus",1,0.5}, {"Оружия: Скорострельность +20%", "firerate",1,0.2}, {"Оружия: Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +35", "max health additive bonus",0,35}, {"Оружия: Макс патроны +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +70%", "deploy time decreased",1,-0.70,0.3}, {"Резисты +15%", "resistance",1,-0.15,0.1}, -- {"Реген хп +2", "health regen",0,2}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Макс метал +50%", "maxammo metal increased",1,0.50}, {"Хп построек +100%", "engy building health bonus",1,1}, {"Хп построек +100%", "engy building health bonus",1,1}, -- {"Скорострел. турели +10%", "engy sentry fire rate increased",1,-0.1,0}, {"Скорострел. турели +20%", "sentryfirerate",1,0.2}, {"Дальность диспака +100%", "engy dispenser radius increased",1,1}, {"Расходная турель +1", "engy disposable sentries",0,1}, -- {"2-сторонний тп", "bidirectional teleport",0,1,1}, {"Реген металла +100", "metal regen",0,100}, {"Макс патроны турели +50%", "mvm sentry ammo",1,0.50}, -- {"Скорость постройки +30%", "build rate bonus",1,-0.3,0.1}, -- {"Скорость постройки ключем +30%", "Construction rate increased",1,0.3}, {"Скорость улучшения +40%", "upgrade rate decrease",1,0.4}, -- {"Получаемый метал +25%", "metal_pickup_decreased",1,0.25}, -- {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { -- {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Оружия: Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Урон турели +25%", "engy sentry damage bonus",1,0.25}, --no buff to custom sentry weapons {"(RARE) Дальность турели +25%", "engy sentry radius increased",1,0.25}, {"(RARE) Сила раздатчика +50%", "mult dispenser rate",1,0.5}, {"(RARE) Сила починки +100%", "Repair rate increased",1,1}, {"(RARE) Само-урон -40%", "dmg taken from self reduced",1,-0.4,0.2}, }, EpicAttribute = { {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Пуль за выстрел +50%", "bullets per shot bonus",1,0.5}, -- {"[EPIC] Скорострел. ракет турели +25%", "mult firerocket rate",1,-0.25,0}, {"[EPIC] Скорострел. ракет турели +50%", "sentryrocketfirerate",1,0.5}, -- {"[EPIC] Перезаряд телепорта +50%", "mult teleporter recharge rate",1,-0.5,0}, -- {"[EPIC] Телепорт ускоряет", "mod teleporter speed boost",0,1,1}, {"[EPIC] Урон против цели турели +50%", "damage bonus bullet vs sentry target",1,0.5}, {"[EPIC] Урон в воздухе +35%", "mult dmg while midair",1,0.35}, {"[EPIC] Быстрая турель", "sentry rapid fire",0,1,1}, }, LegendaryAttribute = { {"【LEGENDARY】 Мини-криты за убийство +3 сек.", "minicritboost on kill",0,3}, {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, -- {"【LEGENDARY】 Стоимость построек -80%", "building cost reduction",1,-0.8,0.2}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, -- {"【LEGENDARY】 Турель стреляет микро-ракетами", "custom",0,1,1}, --regular bullets outpace micro-rockets in damage {"【LEGENDARY】 Усиленные ракеты турели", "sentryrockets",0,1,1}, --effectively +300% damage, even if doesn't scale {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [5] = --Medic Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, {"Обойма +50%", "clip size bonus",1,0.5}, --{"Clip Size +2", "clip size upgrade atomic",0,2}, {"Скорострельность +20%", "firerate",1,0.2}, {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +35", "max health additive bonus",0,35}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +70%", "deploy time decreased",1,-0.70,0.3}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +6 health", "heal on hit for rapidfire",0,6}, {"Зарядка убера +25%", "ubercharge rate bonus",1,0.25}, {"Длительность убера +2 сек", "uber duration bonus",0,2}, {"Мастер лечения", "healing mastery",0,1}, {"Эксперт оверхила", "overheal expert",0,1}, -- {"Overheal Duration +50%", "overheal bonus",1,0.25}, -- {"Скорость возрождений +25%", "revive rate",1,0.25}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Щит", "generate rage on heal",0,1,2}, {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Убер за попадание +1%", "add uber charge on hit",0,0.01}, -- {"(RARE) Молочные шприцы", "mad milk syringes",0,1,1}, {"(RARE) Дальность медигана +25%", "mult medigun range",1,0.25}, {"(RARE) Медиган дамажит врагов", "medigun attack enemy",0,1,1}, {"(RARE) Спец по флягам", "canteen specialist",0,1,3}, }, EpicAttribute = { {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Криты за убийство +2 сек.", "critboost on kill",0,2}, {"[EPIC] Плохие жидкости при попадании", "concoction",0,1,1}, {"[EPIC] Хил построек +50% Лечения", "medic machinery beam",0,5}, {"[EPIC] Мили бьет по области", "melee cleave attack",0,1,1}, -- {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Урон в воздухе +35%", "mult dmg while midair",1,0.35}, {"[EPIC] Зарядка убера с оверхилом +25%", "ubercharge overheal rate penalty",1,0.25}, {"[EPIC] Накопление оверхила +35%", "overheal fill rate reduced",1,0.35}, }, LegendaryAttribute = { {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Неуязвимость при уроне шанс 10%", "uber on damage taken",0,0.1,0.1}, -- {"【LEGENDARY】 Убер не спадает с пациента", "medigun keep charged effect",0,1,1}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Лечение +100%", "heal rate bonus",1,1,}, {"【LEGENDARY】 Макс Оверхил +100%", "overheal bonus",1,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [2] = --Sniper Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, {"СМГ: обойма +50%", "clip size bonus",1,0.5}, {"Скорострельность +20%", "firerate",1,0.2}, -- {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +35", "max health additive bonus",0,35}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, {"Перезарядка расходника +15%", "effect bar recharge rate increased",1,0.15}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Скорость заряда +25%", "SRifle Charge rate increased",1,0.25}, {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, {"(RARE) Доп. прыжок +1", "air dash count",0,1}, -- {"(RARE) Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Липкое Джарате", "applies snare effect",1,-0.35,0.65}, {"(RARE) Урон по всей цепочке медигана", "damage all connected",0,1,1}, {"(RARE) Стабильный прицел", "no damage view flinch",0,1,1}, {"(RARE) Урон при полной зарядке +35%", "sniper full charge damage bonus",1,0.35}, {"(RARE) СМГ: Точность +100%", "weapon spread bonus",1,-1,0}, {"(RARE) СМГ: Хэдшоты", "can headshot",0,1,1}, {"(RARE) Огненные стрелы", "arrow ignite",0,1,1}, {"(RARE) Лук: Мастер стрел", "arrow mastery",0,1}, }, EpicAttribute = { {"[EPIC] Урон по танку +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Продолжительность эффекта +50%", "mult effect duration",1,0.5}, {"[EPIC] Взрывной хэдшот", "explosive sniper shot",0,1}, {"[EPIC] Взрывной хэдшот", "explosive sniper shot",0,1}, {"[EPIC] Взрывные патроны", "explosive bullets",0,147,147}, {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Лук: Самонавод. стрелы", "homingbow",0,1,1}, }, LegendaryAttribute = { {"【LEGENDARY】 Мини-криты становятся Критами", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 Урон блида и взрыв. хэд +200%", "mult bleeding dmg",1,2}, {"【LEGENDARY】 Урон по гигантам +100%", "mult dmg vs giants",1,1}, {"【LEGENDARY】 Хэдшот урон +100%", "headshot damage increase",1,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } }, [8] = --Spy Shop { CommonAttribute = { {"Урон +25%", "damage bonus",1,0.25}, {"Обойма +50%", "clip size bonus",1,0.5}, {"Скорострельность +20%", "firerate",1,0.2}, {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Хил за убийство +25", "heal on kill",0,25}, {"Макс хп +45", "max health additive bonus",0,45}, {"Запас патронов +50%", "maxammo",1,0.5}, {"Скорость +10%", "move speed bonus",1,0.1}, {"Прыжок +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, -- {"Перезарядка жучка +15%", "charge recharge rate increased",1,0.15}, {"Резисты +15%", "resistance",1,-0.15,0.1}, {"Реген хп +5", "health regen",0,5}, {"Реген патронов +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Сила жучка", "robo sapper",0,1,3}, {"Пробой брони", "armor piercing",0,25,100}, -- {"Длительность невидемости +20%", "cloak consume rate decreased",1,-0.2}, {"Перезарядка невидемости +50%", "mult cloak meter regen rate",1,0.5}, {"Невидемость за попадание +30%", "add cloak on hit",0,30}, --{"Add Cloak On Kill +30%", "add cloak on kill",0,30}, -- {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Урон по всей цепочке медигана", "damage all connected",0,1,1}, {"(RARE) Точность +100%", "weapon spread bonus",1,-1,0}, {"(RARE) Хэдшоты", "can headshot",0,1,1}, {"(RARE) Скорость выхода из невидемости +50%", "mult decloak rate",1,-0.49,0.02}, }, EpicAttribute = { {"[EPIC] Шанс избежать смерти +25%", "teleport instead of die",0,0.25,1}, -- {"[EPIC] Длительность жучка +50%", "mult effect duration",1,0.5}, {"[EPIC] Спид буст за убийство", "speed_boost_on_kill",0,5,5}, --{"[EPIC] Last Bullet Is A Crit", "last shot crits",0,1,1}, {"[EPIC] Иммун к жидкостям", "wet immunity",0,1,1}, {"[EPIC] Иммун к догоранию", "afterburn immunity",0,1,1}, {"[EPIC] Урон когда замаскирован +50%", "damage bonus while disguised",1,0.5}, {"[EPIC] Урон в воздухе +30%", "mult dmg while midair",1,0.3}, {"[EPIC] Резист +50% когда замаскирован", "disguise damage reduction",1,-0.5,0.5}, {"[EPIC] Невидим для турелей", "ignored by enemy sentries",0,1,1}, }, LegendaryAttribute = { -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Урон по танку +300%", "mult dmg vs tanks",1,3}, {"【LEGENDARY】 Револьвер не сбрасывает маскировку", "keep disguise on attack",0,1,1}, --{"【LEGENDARY】 Disguise On Backstab", "disguise on backstab",0,1,1}, -- {"【LEGENDARY】 Бэкстабы копят криты", "sapper kills collect crits",0,1,1}, {"【LEGENDARY】 Криты за убийство +3 сек.", "critboost on kill",0,3}, {"【LEGENDARY】 Мили атаки дает убер +0.5 сек.", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Килы дают незаметность +1 сек.", "stealth",0,1,1}, {"【LEGENDARY】 Супер кровотечение +1 сек.", "superbleed",0,1}, {"【LEGENDARY】 Скидка -30%", "bot medic uber health threshold",1,-0.3,0.1}, } } }, ["EN"] = { [1] = --Scout Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, {"Clip size +50%", "clip size bonus",1,0.5}, -- {"Скорострельность +10%", "fire rate bonus",1,-0.1,0.1}, {"Fire rate +20%", "firerate",1,0.2}, -- {"Скорость перезарядки +20%", "faster reload rate",1,-0.2,0.1}, {"Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +35", "max health additive bonus",0,35}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1,1.3}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Consumable recharge speed +15%", "effect bar recharge rate increased",1,0.15}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, -- {"Реген хп +2", "health regen",0,2}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, {"(RARE) Projectile penetration", "projectile penetration",0,1,1}, {"(RARE) Milk slows down enemies", "applies snare effect",1,-0.35,0.65}, {"(RARE) Accuracy +10%", "weapon spread bonus",1,-0.1,0.1}, {"(RARE) Slow resistance +50%", "mult stun resistance",1,-0.5,0}, -- {"(RARE) Урон вблизи +30%", "custom",1,0.3}, }, EpicAttribute = { {"[EPIC] Bullets per shot +50%", "bullets per shot bonus",1,0.5}, {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Effect duration +50%", "mult effect duration",1,0.5}, {"[EPIC] Crit damage +30%", "mult crit dmg",1,0.3}, {"[EPIC] Invisible to Sentry Guns", "ignored by enemy sentries",0,1,1}, {"[EPIC] Mid-air jumps +1", "air dash count",0,1}, -- {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, }, LegendaryAttribute = { -- {"【LEGENDARY】 Криты за убийство +2 сек.", "critboost on kill",0,2}, {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Mark for death on hit", "mark for death",0,1,1}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 Damage while mid-air +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 Damage to giants +100%", "mult dmg vs giants",1,1}, {"【LEGENDARY】 Bleed damage +900%", "mult bleeding dmg",0,10}, {"【LEGENDARY】 75% Chance to dodge damage", "add cond when active",0,79,79}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [3] = --Soldier Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, --{"Primary: Clip Size +2", "clip size upgrade atomic",0,2}, {"Clip size +50%", "clip size bonus",1,0.5}, {"Fire rate +20%", "firerate",1,0.2}, {"Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +40", "max health additive bonus",0,40}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, {"Blast radius +25%", "Blast radius increased",1,0.25}, {"Rocket speed +25%", "Projectile speed increased",1,0.25}, {"Banners: Duration +25%", "increase buff duration",1,0.25}, -- {"Баннеры: Зарядка +25%", "rage giving scale",1,0.25}, {"Parachute re-deploy", "parachute redeploy",0,1,1}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, {"Heal +15 health from cash", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, {"(RARE) Rocket specialist", "rocket specialist",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Fall damage immunity", "cancel falling damage",0,1,1}, {"(RARE) Damage on airshots +50%", "mult dmg vs airborne",1,0.5}, {"(RARE) Self-damage -40%", "blast dmg to self increased",1,-0.4,0.2}, {"(RARE) Rockets cannot be deflected", "projectile no deflect",0,1,1}, }, EpicAttribute = { {"[EPIC] Banners: radius +25%", "mod soldier buff range",1,0.25}, {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, -- {"[EPIC] Быстрая смена оружия в рокет джампе", "mult rocketjump deploy time",1,-0.9,0.1}, {"[EPIC] Crit damage +30%", "mult crit dmg",1,0.3}, {"[EPIC] Damage for every target within blast radius +10%", "add damage per target",0,0.1}, }, LegendaryAttribute = { {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Crits while Blast Jumping", "mod crit while airborne",0,1,1}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Damage while mid-air +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 Fire rate while blast jumping +100%", "rocketjump attackrate bonus",1,-0.5,0.5}, {"【LEGENDARY】 Homing Projectiles", "homing",0,1,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [7] = --Pyro Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, {"Damage +25%", "damage bonus",1,0.25}, -- {"Урон +25%", "damage bonus",1,0.25}, {"Secondary: Clip size +50%", "clip size bonus",1,0.5}, {"Secondary: Fire rate +20%", "firerate",1,0.2}, {"Secondary: Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +50", "max health additive bonus",0,50}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +2 health", "heal on hit for rapidfire",0,2}, -- {"Расход патронов -25%", "flame ammopersec decreased",1,-0.25,0}, {"Afterburn damage +200%", "weapon burn dmg increased",1,2}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Flares: Projectile speed +25%", "Projectile speed increased",1,0.25}, {"Jetpack: Re-launch mid-air", "thermal_thruster_air_launch",0,1,1}, {"Jetpack: Stun on landing", "falling_impact_radius_stun",0,1,1}, {"Airblast speedboosts allies", "airblast_give_teammate_speed_boost",0,5,5}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, {"Heal +15 health from cash", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, -- {"(RARE) Флог: Ммфф зарядка +50%", "rage giving scale",1,0.50}, {"(RARE) Mid-air jumps +1", "air dash count",0,1}, {"(RARE) Speed of reflected Projectiles +100%", "mult reflect velocity",1,1,2}, -- {"(RARE) Flame Size +50%", "flame size bonus",1,0.50}, -- {"(RARE) Flame Distance +50%", "flame life bonus",1,0.50}, {"(RARE) Ammo consumption per airblast -25%", "airblast cost decreased",1,-0.25,0}, {"(RARE) Slow enemy on hit", "slow enemy on hit",0,1,1}, {"(RARE) Flamethrower: +20% Range", "flame_speed",0,490}, {"(RARE) Airblast Strength +30%", "airblast pushback scale",1,0.3}, }, EpicAttribute = { {"[EPIC] Dragon + Secondary: Recharge speed +15%", "mult_item_meter_charge_rate",1,-0.15,0.1}, {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, {"[EPIC] Flamethrower: Crit from behind", "mod flamethrower back crit",0,1,1}, {"[EPIC] Airblast recharge time -50%", "mult airblast refire time",1,-0.5,0.5}, {"[EPIC] Damage while mid-air +30%", "mult dmg while midair",1,0.30}, }, LegendaryAttribute = { {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Healing recieved +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Crit damage +100%", "mult crit dmg",1,1}, {"【LEGENDARY】 Crit damage +100%", "mult crit dmg",1,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, }, Contraband = { {"/// CAUTION!! /// Explode on ignite", "explode_on_ignite",0,1,1}, } }, [4] = --Demoman Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, --{"Primary: Clip Size +2", "clip size upgrade atomic",0,2}, {"Clip size +50%", "clip size bonus",1,0.5}, {"Fire rate +20%", "firerate",1,0.2}, {"Reload rate +50%", "reloadrate",1,0.5}, {"Heal on kill +25", "heal on kill",0,25}, {"Max health +40", "max health additive bonus",0,40}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Shield: recharge speed +100%", "charge recharge rate increased",1,1}, {"Shield: Shieldbash damage +100%", "charge impact damage increased",1,1}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,15}, {"Blast radius +25%", "Blast radius increased",1,0.25}, {"Projectile speed +25%", "Projectile speed increased",1,0.25}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Stickies: Max stickies +2", "max pipebombs increased",1,2}, {"Stickies: Charge speed +25%", "stickybomb charge rate",1,-0.25,0}, {"Stickies: Arm time -0.2 seconds", "sticky arm time bonus",0,-0.2,-0.8}, {"Parachute re-deploy", "parachute redeploy",0,1,1}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, {"Heal +15 health from cash", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, {"(RARE) Melee bounds +50%", "melee bounds multiplier",1,0.5}, {"(RARE) Melee Range +25%", "melee range multiplier",1,0.25}, {"(RARE) Mid-air jumps +1", "air dash count",0,1}, {"(RARE) Fall damage immunity", "cancel falling damage",0,1,1}, {"(RARE) Shield: Charge time +1 seconds", "charge time increased",1,1}, {"(RARE) Grenade Launcher: Explode on impact", "grenade explode on impact",0,1,1}, {"(RARE) Melee reflects projectiles", "melee airblast",0,1,1}, {"(RARE) Self-damage -40%", "blast dmg to self increased",1,-0.4,0.2}, }, EpicAttribute = { {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, -- {"[EPIC] Щиты: Полный контроль", "full charge turn control",0,1,1}, {"[EPIC] Stickies: Damage for charging up to +35%", "stickybomb_charge_damage_increase",1,0.35}, {"[EPIC] Melee Attacks Cleave All Targets", "melee cleave attack",0,1,1}, {"[EPIC] Projectiles cannot be deflected", "projectile no deflect",0,1,1}, {"[EPIC] Crit damage +30%", "mult crit dmg",1,0.3}, }, LegendaryAttribute = { {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Healing recieved +100%", "healing received penalty",1,1}, -- {"【LEGENDARY】 Метка при попадании", "mark for death",0,1,1}, {"【LEGENDARY】 Crits while Blast Jumping", "mod crit while airborne",0,1,1}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Damage while mid-air +50%", "mult dmg while midair",1,0.5}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [6] = --Heavy Shop { CommonAttribute = { {"Secondary: Clip size +50%", "clip size bonus",1,0.5}, {"Fire rate +20%", "firerate",1,0.2}, {"Secondary: Reload rate +50%", "reloadrate",1,0.5}, {"Sandvich recharge speed +20%", "charge recharge rate increased",1,-0.20,0.4}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +50", "max health additive bonus",0,50}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +2 health", "heal on hit for rapidfire",0,2}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Spinup speed +15%", "minigun spinup time decreased",1,-0.15,0}, {"Move speed while spun up +20%", "aiming movespeed increased",1,0.20,1.6}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Damage +25%", "damage bonus",1,0.25}, {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Projectile penetration", "projectile penetration",0,1,1}, {"(RARE) Destroy projectiles", "attack projectiles",0,1,2}, {"(RARE) Knockback Rage", "generate rage on damage",0,1,3}, {"(RARE) Can holster minigun while spun up", "mod minigun can holster while spinning",0,1,1}, {"(RARE) Slow enemies on hit", "slow enemy on hit",0,1,1}, {"(RARE) Damage while mid-air +30%", "mult dmg while midair",1,0.3}, {"(RARE) Accuracy +10%", "weapon spread bonus",1,-0.1,0.1}, }, EpicAttribute = { {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, {"[EPIC] Fire ring", "ring of fire while aiming",0,25,25}, {"[EPIC] Bullets per shot +25%", "bullets per shot bonus",1,0.25}, {"[EPIC] Bullets per shot +25%", "bullets per shot bonus",1,0.25}, {"[EPIC] +20% Damage resistance while spun up*", "spunup_damage_resistance",1,-0.2,0.4}, {"[EPIC] Crit damage +30%", "mult crit dmg",1,0.3}, }, LegendaryAttribute = { {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Healing recieved +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Mark for death on hit", "mark for death",0,1,1}, {"【LEGENDARY】 +100% Damage to burning", "damage bonus vs burning",1,1}, {"【LEGENDARY】 +80% Damage while healed", "mod medic healed damage bonus",1,0.8}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [9] = --Engineer Shop { CommonAttribute = { {"Weapons: Damage +25%", "damage bonus",1,0.25}, {"Weapons: Clip size +50%", "clip size bonus",1,0.5}, {"Weapons: Fire rate +20%", "firerate",1,0.2}, {"Weapons: Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +35", "max health additive bonus",0,35}, {"Weapons: Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +70%", "deploy time decreased",1,-0.70,0.3}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, -- {"Реген хп +2", "health regen",0,2}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Max metal +50%", "maxammo metal increased",1,0.50}, {"Building health +100%", "engy building health bonus",1,1}, {"Building health +100%", "engy building health bonus",1,1}, -- {"Скорострел. турели +10%", "engy sentry fire rate increased",1,-0.1,0}, {"Sentry fire rate +20%", "sentryfirerate",1,0.2}, {"Dispenser range +100%", "engy dispenser radius increased",1,1}, {"Disposable Sentry +1", "engy disposable sentries",0,1}, -- {"2-сторонний тп", "bidirectional teleport",0,1,1}, {"Metal regen +100", "metal regen",0,100}, {"Max sentrygun ammo +50%", "mvm sentry ammo",1,0.50}, -- {"Скорость постройки +30%", "build rate bonus",1,-0.3,0.1}, -- {"Скорость постройки ключем +30%", "Construction rate increased",1,0.3}, {"Upgrade rate +40%", "upgrade rate decrease",1,0.4}, -- {"Получаемый метал +25%", "metal_pickup_decreased",1,0.25}, -- {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { -- {"(RARE) Мал. аптечка при убийстве", "drop health pack on kill",0,1,1}, -- {"(RARE) Доп. прыжок +1", "air dash count",0,1}, {"(RARE) Weapons: Projectile penetration", "projectile penetration",0,1,1}, {"(RARE) Sentry damage +25%", "engy sentry damage bonus",1,0.25}, --no buff to custom sentry weapons {"(RARE) Sentry range +25%", "engy sentry radius increased",1,0.25}, {"(RARE) Dispenser Strength +50%", "mult dispenser rate",1,0.5}, {"(RARE) Repair rate +100%", "Repair rate increased",1,1}, {"(RARE) Self-damage -40%", "dmg taken from self reduced",1,-0.4,0.2}, }, EpicAttribute = { {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, {"[EPIC] Weapons: Bullets per shot +50%", "bullets per shot bonus",1,0.5}, -- {"[EPIC] Скорострел. ракет турели +25%", "mult firerocket rate",1,-0.25,0}, {"[EPIC] Sentry rocket fire rate +50%", "sentryrocketfirerate",1,0.5}, -- {"[EPIC] Перезаряд телепорта +50%", "mult teleporter recharge rate",1,-0.5,0}, -- {"[EPIC] Телепорт ускоряет", "mod teleporter speed boost",0,1,1}, {"[EPIC] Damage against sentry target +50%", "damage bonus bullet vs sentry target",1,0.5}, {"[EPIC] Damage while mid-air +35%", "mult dmg while midair",1,0.35}, {"[EPIC] Fast sentry gun", "sentry rapid fire",0,1,1}, }, LegendaryAttribute = { {"【LEGENDARY】 Minicrits on Kill +3 сек.", "minicritboost on kill",0,3}, {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Mark for death on hit", "mark for death",0,1,1}, -- {"【LEGENDARY】 Стоимость построек -80%", "building cost reduction",1,-0.8,0.2}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, -- {"【LEGENDARY】 Турель стреляет микро-ракетами", "custom",0,1,1}, --regular bullets outpace micro-rockets in damage {"【LEGENDARY】 Enhanced sentry rockets", "sentryrockets",0,1,1}, --effectively +300% damage, even if doesn't scale {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [5] = --Medic Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, {"Clip size +50%", "clip size bonus",1,0.5}, --{"Clip Size +2", "clip size upgrade atomic",0,2}, {"Fire rate +20%", "firerate",1,0.2}, {"Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +35", "max health additive bonus",0,35}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +70%", "deploy time decreased",1,-0.70,0.3}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +6 health", "heal on hit for rapidfire",0,6}, {"Ubercharge rate +25%", "ubercharge rate bonus",1,0.25}, {"Ubercharge duration +2 seconds", "uber duration bonus",0,2}, {"Healing Mastery", "healing mastery",0,1}, {"Overheal Expert", "overheal expert",0,1}, -- {"Overheal Duration +50%", "overheal bonus",1,0.25}, -- {"Скорость возрождений +25%", "revive rate",1,0.25}, --{"Push Force -30%", "damage force reduction",1,-0.3,0}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Projectile Shield", "generate rage on heal",0,1,2}, {"(RARE) Mid-air jumps +1", "air dash count",0,1}, {"(RARE) Ubercharge on hit +1%", "add uber charge on hit",0,0.01}, -- {"(RARE) Молочные шприцы", "mad milk syringes",0,1,1}, {"(RARE) Medigun range +25%", "mult medigun range",1,0.25}, {"(RARE) Medigun can damage enemies", "medigun attack enemy",0,1,1}, {"(RARE) Canteen Specialist", "canteen specialist",0,1,3}, }, EpicAttribute = { {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Crit on Kill +2 seconds", "critboost on kill",0,2}, {"[EPIC] Mixed Concoction on Hit", "concoction",0,1,1}, {"[EPIC] Heal Buildings +50% healing", "medic machinery beam",0,5}, {"[EPIC] Melee Attacks Cleave All Targets", "melee cleave attack",0,1,1}, -- {"[EPIC] Спид буст за убийство +5 сек.", "speed_boost_on_kill",0,5,5}, {"[EPIC] Damage while mid-air +35%", "mult dmg while midair",1,0.35}, {"[EPIC] Ubercharge rate on Overhealed +25%", "ubercharge overheal rate penalty",1,0.25}, {"[EPIC] Overheal rate +35%", "overheal fill rate reduced",1,0.35}, }, LegendaryAttribute = { {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, {"【LEGENDARY】 Healing received +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Invulnerable on Taking Damage +10% Chance", "uber on damage taken",0,0.1,0.1}, -- {"【LEGENDARY】 Убер не спадает с пациента", "medigun keep charged effect",0,1,1}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Healing rate +100%", "heal rate bonus",1,1,}, {"【LEGENDARY】 Maximum overheal +100%", "overheal bonus",1,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [2] = --Sniper Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, {"SMG: Clip size +50%", "clip size bonus",1,0.5}, {"Fire rate +20%", "firerate",1,0.2}, -- {"Скорость перезарядки +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +35", "max health additive bonus",0,35}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Weapon deploy speed +35%", "deploy time decreased",1,-0.35,0}, {"Consumable recharge speed +15%", "charge recharge rate increased",1,0.15}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Faster Charge +25%", "SRifle Charge rate increased",1,0.25}, {"Bleed on hit +8 seconds", "bleeding duration",0,8,8}, -- {"Хил с денег +15", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, {"(RARE) Mid-air jumps +1", "air dash count",0,1}, -- {"(RARE) Пробойные пули", "projectile penetration",0,1,1}, {"(RARE) Jarate slows down enemies", "applies snare effect",1,-0.35,0.65}, {"(RARE) Damage All Targets Connected By Medigun", "damage all connected",0,1,1}, {"(RARE) No damage flinching", "no damage view flinch",0,1,1}, {"(RARE) Damage when fully charged +35%", "sniper full charge damage bonus",1,0.35}, {"(RARE) SMG: Accuracy +100%", "weapon spread bonus",1,-1,0}, {"(RARE) SMG: Headshots Enabled", "can headshot",0,1,1}, {"(RARE) Self igniting arrows", "arrow ignite",0,1,1}, {"(RARE) Bow: Arrow mastery", "arrow mastery",0,1}, }, EpicAttribute = { {"[EPIC] Damage to tanks +50%", "mult dmg vs tanks",1,0.5}, {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, {"[EPIC] Effect duration +50%", "mult effect duration",1,0.5}, {"[EPIC] Explosive Headshots", "explosive sniper shot",0,1}, {"[EPIC] Explosive Headshots", "explosive sniper shot",0,1}, {"[EPIC] Explosive Bullets", "explosive bullets",0,147,147}, {"[EPIC] Speed boost on Kill +5 seconds", "speed_boost_on_kill",0,5,5}, {"[EPIC] Bow: Homing arrows", "homingbow",0,1,1}, }, LegendaryAttribute = { {"【LEGENDARY】 Minicrits become Crits", "minicrits become crits",0,1,1}, -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Mark for death on hit", "mark for death",0,1,1}, -- {"【LEGENDARY】 Мили атаки дает убер +1 сек.", "melee grants protection",0,1}, {"【LEGENDARY】 Explosive Headshot and Bleed Damage +200%", "mult bleeding dmg",1,2}, {"【LEGENDARY】 Damage to giants +100%", "mult dmg vs giants",1,1}, {"【LEGENDARY】 Headshot Damage +100%", "headshot damage increase",1,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } }, [8] = --Spy Shop { CommonAttribute = { {"Damage +25%", "damage bonus",1,0.25}, {"Clip Size +50%", "clip size bonus",1,0.5}, {"Fire rate +20%", "firerate",1,0.2}, {"Reload rate +50%", "reloadrate",1,0.5}, {"Heal on Kill +25", "heal on kill",0,25}, {"Max health +45", "max health additive bonus",0,45}, {"Max ammo +50%", "maxammo",1,0.5}, {"Move speed +10%", "move speed bonus",1,0.1}, {"Jump height +20%", "increased jump height",1,0.2}, {"Скор. смены оруж. +35%", "deploy time decreased",1,-0.35,0}, -- {"Перезарядка жучка +15%", "charge recharge rate increased",1,0.15}, {"Damage resistances +15%", "resistance",1,-0.15,0.1}, {"Health regen +5", "health regen",0,5}, {"Ammo regen +20%", "ammo regen",0,0.2,1}, --{"Heal On Hit +15 health", "heal on hit for rapidfire",0,3}, {"Robo sapper power", "robo sapper",0,1,3}, {"Armor penetration", "armor piercing",0,25,100}, -- {"Длительность невидемости +20%", "cloak consume rate decreased",1,-0.2}, {"Cloak recharge rate +50%", "mult cloak meter regen rate",1,0.5}, {"Add cloak on hit +30%", "add cloak on hit",0,30}, --{"Add Cloak On Kill +30%", "add cloak on kill",0,30}, -- {"Кровотечение +8 сек.", "bleeding duration",0,8,8}, {"Heal +15 health from cash", "health from credits",0,15}, }, RareAttribute = { {"(RARE) Drop a small medkit on kill", "drop health pack on kill",0,1,1}, {"(RARE) Mid-air jumps +1", "air dash count",0,1}, {"(RARE) Projectile penetration", "projectile penetration",0,1,1}, {"(RARE) Damage all targets connected by Medigun", "damage all connected",0,1,1}, {"(RARE) Accuracy +100%", "weapon spread bonus",1,-1,0}, {"(RARE) Headshots Enabled", "can headshot",0,1,1}, {"(RARE) Decloak sped +50%", "mult decloak rate",1,-0.49,0.02}, }, EpicAttribute = { {"[EPIC] Chance to avoid Death +25%", "teleport instead of die",0,0.25,1}, -- {"[EPIC] Длительность жучка +50%", "mult effect duration",1,0.5}, {"[EPIC] Speed boost on Kill", "speed_boost_on_kill",0,5,5}, --{"[EPIC] Last Bullet Is A Crit", "last shot crits",0,1,1}, {"[EPIC] Wet Immunity", "wet immunity",0,1,1}, {"[EPIC] Afterburn Immunity", "afterburn immunity",0,1,1}, {"[EPIC] Damage while Disguised +50%", "damage bonus while disguised",1,0.5}, {"[EPIC] Damage while mid-air +30%", "mult dmg while midair",1,0.3}, {"[EPIC] Damage resistance +50% while disguised", "disguise damage reduction",1,-0.5,0.5}, {"[EPIC] Invisible to sentry guns", "ignored by enemy sentries",0,1,1}, }, LegendaryAttribute = { -- {"【LEGENDARY】 Весь получаемый хил +100%", "healing received penalty",1,1}, {"【LEGENDARY】 Damage to tanks +300%", "mult dmg vs tanks",1,3}, {"【LEGENDARY】 Revlover retains disguise", "keep disguise on attack",0,1,1}, --{"【LEGENDARY】 Disguise On Backstab", "disguise on backstab",0,1,1}, -- {"【LEGENDARY】 Бэкстабы копят криты", "sapper kills collect crits",0,1,1}, {"【LEGENDARY】 Crit on Kill +2 seconds", "critboost on kill",0,2}, {"【LEGENDARY】 Melee attacks grants protection +0.5 seconds", "melee grants protection",0,0.5,0.5}, {"【LEGENDARY】 Kills give Stealth +1 seconds", "stealth",0,1,1}, {"【LEGENDARY】 Super Bleed +1 seconds", "superbleed",0,1}, {"【LEGENDARY】 -30% Discount", "bot medic uber health threshold",1,-0.3,0.1}, } } } } --Used for returning the class name classIndices_Internal = { [1] = "Scout", [3] = "Soldier", [7] = "Pyro", [4] = "Demoman", [6] = "Heavy", [9] = "Engineer", [5] = "Medic", [2] = "Sniper", [8] = "Spy", } baseClassHealth = { [1] = 125, [3] = 200, [7] = 175, [4] = 175, [6] = 300, [9] = 125, [5] = 150, [2] = 125, [8] = 125, } --[[Adds the OnSpawn callback so that everytime a player spawns their upgrades are reapplied and Select your language when first spawning in Bots recieve buff depending on current Wave]] function OnPlayerConnected( player ) if player:IsRealPlayer() then player:AddCallback( ON_SPAWN, function( ent ) InitUserId(player) ReAddPurchasedUpgrades(player) --[[Select your language when first spawning in]] -- ent:AcceptInput("$DisplayTextChat", "{yellow}ON_SPAWN CallBack.") if ent.Lang == nil and ent.LangSelected ~= true and ent.m_iClass > 0 and ent.m_iClass < 10 then local Lang_Menu = { timeout = 0, title = "Select Language\nВыберите Язык", itemsPerPage = 2, flags = nil, onSelect = nil, onCancel = nil, } Lang_Menu[1] = { text = "Русский", value = "RU", disabled = false } Lang_Menu[2] = { text = "English", value = "EN", disabled = false } Lang_Menu["onSelect"] = function(player, index, value) player.Lang = value player.LangSelected = true player:SetAttributeValue("move speed penalty", nil) player:HideMenu() player:AcceptInput("$DisplayTextChat", "{green}You can always change language using !lang or !translate") end Lang_Menu["onCancel"] = function(player, index, value) timer.Simple(0.05, function() if ( player ) and ( player:IsValid() ) and ( player ~= nil ) then player:DisplayMenu(Lang_Menu) end end) end ent:SetAttributeValue("move speed penalty", 0.0001) ent:DisplayMenu(Lang_Menu) end end) else player:AddCallback( ON_SPAWN, function( ent ) timer.Simple(0.05, function() if ent.m_bUseBossHealthBar ~= 1 then local ScalingFactor = ents.FindByClass('tf_objective_resource').m_nMannVsMachineWaveCount - 1 local HealthMult = (1 + ScalingFactor*0.125)^4 -- local myOldHealth = ent.m_iHealth local myOldMaxHealth = 0 if ent:GetAttributeValue("hidden maxhealth non buffed") ~= nil then myOldMaxHealth = ent:GetAttributeValue("hidden maxhealth non buffed") + baseClassHealth[ent.m_iClass] else myOldMaxHealth = ent.m_iMaxHealth end if ent.m_bIsMiniBoss ~= 1 then for i = 0, 3, 1 do if IsValid(ent:GetPlayerItemBySlot(i)) and ent:GetPlayerItemBySlot(i):GetClassname() ~= "tf_wearable" then if ent:GetPlayerItemBySlot(i):GetClassname() == "tf_weapon_medigun" then --[[Common Medic scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 2.5 | 5 | 7.5 | 10 | 12.5| 15 | 17.5| 20 | 22.5|]] local healrate = ent:GetPlayerItemBySlot(i):GetAttributeValue("heal rate bonus") or 1 ent:GetPlayerItemBySlot(i):SetAttributeValue("heal rate bonus", math.max(healrate * ScalingFactor*2.5, healrate)) elseif i == 2 then --[[Common Melee scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 1.2 | 1.4 | 1.9 | 2.2 | 2.5 | 3.4 | 3.8 | 4.2 | 4.6 |]] if ScalingFactor < 3 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.2) elseif ScalingFactor < 6 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.3) else ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.4) end elseif i == 3 and ent.m_iClass == 9 then --[[Engineer scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 1.15| 1.3 | 1.6 | 1.8 | 2 | 2.5 | 2.75| 3 | 3.25|]] if ScalingFactor < 3 then ent:GetPlayerItemBySlot(i):SetAttributeValue("engy sentry damage bonus", 1 + ScalingFactor*0.15) elseif ScalingFactor < 6 then ent:GetPlayerItemBySlot(i):SetAttributeValue("engy sentry damage bonus", 1 + ScalingFactor*0.2) else ent:GetPlayerItemBySlot(i):SetAttributeValue("engy sentry damage bonus", 1 + ScalingFactor*0.25) end ent:GetPlayerItemBySlot(i):SetAttributeValue("engy building health bonus", HealthMult) else --[[Common scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 1.15| 1.3 | 1.6 | 1.8 | 2 | 2.5 | 2.75| 3 | 3.25|]] if ScalingFactor < 3 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.15) elseif ScalingFactor < 6 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.2) else ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.25) end end if ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on kill") ~= nil then ent:GetPlayerItemBySlot(i):SetAttributeValue("heal on kill", ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on kill") * HealthMult) end if ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on hit for rapidfire") ~= nil then ent:GetPlayerItemBySlot(i):SetAttributeValue("heal on hit for rapidfire", ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on hit for rapidfire") * HealthMult) end end end else for i = 0, 2, 1 do if IsValid(ent:GetPlayerItemBySlot(i)) and ent:GetPlayerItemBySlot(i):GetClassname() ~= "tf_wearable" then if ent:GetPlayerItemBySlot(i):GetClassname() == "tf_weapon_medigun" then --[[Giant Medic scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 2.5 | 5 | 7.5 | 10 | 12.5| 15 | 17.5| 20 | 22.5|]] local healrate = ent:GetPlayerItemBySlot(i):GetAttributeValue("heal rate bonus") or 1 ent:GetPlayerItemBySlot(i):SetAttributeValue("heal rate bonus", math.max(healrate * ScalingFactor*2.5, healrate)) elseif i == 2 then --[[Giant Melee scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 1.2 | 1.4 | 2.05| 2.4 | 2.75| 4 | 4.5 | 5 | 5.5 |]] if ScalingFactor < 3 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.2) elseif ScalingFactor < 6 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.35) else ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.5) end else --[[Giant scaling: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | | 1 | 1.2 | 1.4 | 1.75| 2 | 2.25| 2.8 | 3.1 | 3.4 | 3.7 |]] if ScalingFactor < 3 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.2) elseif ScalingFactor < 6 then ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.25) else ent:GetPlayerItemBySlot(i):SetAttributeValue("CARD: damage bonus", 1 + ScalingFactor*0.3) end end if ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on kill") ~= nil then ent:GetPlayerItemBySlot(i):SetAttributeValue("heal on kill", ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on kill") * HealthMult) end if ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on hit for rapidfire") ~= nil then ent:GetPlayerItemBySlot(i):SetAttributeValue("heal on hit for rapidfire", ent:GetPlayerItemBySlot(i):GetAttributeValue("heal on hit for rapidfire") * HealthMult) end end end end local myNewHealth = myOldMaxHealth * HealthMult -- ent:SetAttributeValue("max health additive bonus", myNewHealth - myOldMaxHealth) ent:SetAttributeValue("hidden maxhealth non buffed", myNewHealth - baseClassHealth[ent.m_iClass]) ent.m_iHealth = myNewHealth if ent:GetAttributeValue("bot medic uber health threshold") ~= nil then local botPop = ent:GetAttributeValue("bot medic uber health threshold") ent:SetAttributeValue("bot medic uber health threshold", botPop * HealthMult) end if ent:GetAttributeValue("health regen") ~= nil then local lregen = ent:GetAttributeValue("health regen") ent:SetAttributeValue("health regen", lregen * HealthMult) end local damageforce = ent:GetAttributeValue("damage force reduction") or 1 ent:SetAttributeValue("damage force reduction", damageforce * (1/(1 + ScalingFactor*0.33))) local airblastvuln = ent:GetAttributeValue("airblast vulnerability multiplier") or 1 ent:SetAttributeValue("airblast vulnerability multiplier", airblastvuln * (1/(1 + ScalingFactor*0.175))) local airblastvuln2 = ent:GetAttributeValue("airblast vertical vulnerability multiplier") or 1 ent:SetAttributeValue("airblast vertical vulnerability multiplier", airblastvuln2 * (1/(1 + ScalingFactor*0.05))) end end) end) end end --[[This table is essential, it will store the SteamID3 of a player and act as a "save file" for the player, Things that are stored in here for each player: UpgradePoints - how many upgrade points the player has, persists between classes RerollPoints - how many rerolls the player has, persists between classes An index from [1] to [9] which will represent the player's class Inside the index, each class has its own hasRolled - boolean, used as a flag if the player has rolled for upgrades on that class PurchasedUpgrades - table, which upgrades have been purchased for that player on that class MaxedUpgrades - table, which upgrades are maxed for that player on that class UpgradeMenu - table, show a unique upgrade menu for that player on that class ]] UniqueAccountIDs = {} --[[Also very important, this table is akin to an emulator's "save state" where it will copy everything from UniqueAccountIDs, TotalUpgradePoints, and TotalRerollPoints. In the case that players lose a wave, this table is used to store save states]] WaveState = {} function WeaponAllowed( weapon, list ) if ( not weapon ) or ( weapon == nil ) then return false end if ( not list ) or ( list == nil ) then return true end if ( tostring(type(weapon)) ~= "table" ) and ( weapon:IsPlayer() ) then weapon = { weapon:GetPlayerItemBySlot(0), weapon:GetPlayerItemBySlot(1) } end if tostring(type(list)) == "table" then if tostring(type(weapon)) == "table" then local result = {} for i, wep in pairs( weapon ) do if ( list[wep:GetItemName()] ~= nil ) or ( list[string.lower(wep:GetItemName())] ~= nil ) or ( list[string.upper(wep:GetItemName())] ~= nil ) then result[i] = ( list[wep:GetItemName()] or list[string.lower(wep:GetItemName())] or list[string.upper(wep:GetItemName())] ) or false elseif ( list[wep:GetClassname()] ~= nil ) or ( list[string.lower(wep:GetClassname())] ~= nil ) or ( list[string.upper(wep:GetClassname())] ~= nil ) then result[i] = ( list[wep:GetClassname()] or list[string.lower(wep:GetClassname())] or list[string.upper(wep:GetClassname())] ) or false else --failsafe result[i] = ( false ) end end return result else if ( list[weapon:GetItemName()] ~= nil ) or ( list[string.lower(weapon:GetItemName())] ~= nil ) or ( list[string.upper(weapon:GetItemName())] ~= nil ) then return ( list[weapon:GetItemName()] or list[string.lower(weapon:GetItemName())] or list[string.upper(weapon:GetItemName())]) or false elseif ( list[weapon:GetClassname()] ~= nil ) or ( list[string.lower(weapon:GetClassname())] ~= nil ) or ( list[string.upper(weapon:GetClassname())] ~= nil ) then return ( list[weapon:GetClassname()] or list[string.lower(weapon:GetClassname())] or list[string.upper(weapon:GetClassname())] ) or false else --failsafe return false end end else if tostring(type(weapon)) == "table" then local result = {} for i, wep in pairs( weapon ) do if wep:GetClassname() == list or ( wep:GetItemName() == list ) then result[i] = true else result[i] = false end end return result else if weapon:GetClassname() == list or ( weapon:GetItemName() == list ) then return true else return false end end end return false end function HasTrue( tbl ) if tostring(type( tbl )) == "table" then for i, v in pairs( tbl ) do if v == true then return true end end else return tbl end return false end --[[Finds all func_upgradestation's on the map and lets the player interact with them for bringing up the menu]] function EnableUpgradeStations() for _, v in pairs(ents.FindAllByClass("func_upgradestation")) do v:AddCallback(ON_START_TOUCH, function(_,player) if player:IsRealPlayer() then RollUpgrades(player) ShowUpgradeMenu(player) player:Print(2, "Weclome to the Randomizer Upgrade Station!") end end) v:AddCallback(ON_END_TOUCH, function(_,player) if player:IsRealPlayer() then CloseUpgradeMenu(player) --probably redundnant player:Print(2, "You have left the Randomizer Upgrade Station.") end end) end end --[[If the player joins the server for the first time, their SteamID3 is added to UniqueAccountIDs Note that the function for purchasing upgrades is stored here]] function InitUserId(activator) local player = (ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1] if UniqueAccountIDs[player] == nil then UniqueAccountIDs[player] = { UpgradePoints = TotalUpgradePoints, RerollPoints = TotalRerollPoints, } end local class = activator.m_iClass if UniqueAccountIDs[player][class] == nil then UniqueAccountIDs[player][class] = { hasRolled = false, PurchasedUpgrades = {}, --Stored as key [Upgrade name] with value equal to how many times it was purchased RePurchasedUpgrades = {}, --MaxedUpgrades = {}, --Used as a temporary table, similar to PurchasedUpgrades, probably not needed in style2 UpgradeMenu = { timeout = 0, title = "Select an upgrade - ", itemsPerPage = nil, flags = MENUFLAG_BUTTON_EXIT, onSelect = function(activator, index, value) --Responsible for subtracting upgrade/reroll points, disabling purchased upgrades local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass local purchased = player[class].PurchasedUpgrades local repurchased = player[class].RePurchasedUpgrades local menu = player[class].UpgradeMenu local playername = activator.m_szNetname local localize = activator.Lang if localize == nil then localize = "RU" activator:AcceptInput("$DisplayTextChat", "{red}Yo, your language setting is nil, using RU.") end if value == "buyupgrade" then local discount = activator:GetAttributeValue("bot medic uber health threshold") or 1 local UpgradeCostFinal = math.floor((UpgradeCost * discount) + 0.5) activator:RemoveCurrency( UpgradeCostFinal ) player.UpgradePoints = player.UpgradePoints + 1 activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value == "buyreroll" then local discount = activator:GetAttributeValue("bot medic uber health threshold") or 1 local RerollCostFinal = math.floor((RerollCost * discount) + 0.5) activator:RemoveCurrency( RerollCostFinal ) player.RerollPoints = player.RerollPoints + 1 activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value == "buycanteencrit" then activator:RemoveCurrency( CanteenCritCost ) local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if playerAction:GetAttributeValue("critboost") == 1 then playerAction:SetAttributeValue("powerup charges",canteenCharges + 1) playerAction.m_usNumCharges = canteenCharges + 1 else playerAction:SetAttributeValue("critboost",1) playerAction:SetAttributeValue("ubercharge",nil) playerAction:SetAttributeValue("refill_ammo",nil) playerAction:SetAttributeValue("building instant upgrade",nil) playerAction:SetAttributeValue("powerup charges",1) playerAction.m_usNumCharges = 1 end activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value == "buycanteenuber" then activator:RemoveCurrency( CanteenUberCost ) local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if playerAction:GetAttributeValue("ubercharge") == 1 then playerAction:SetAttributeValue("powerup charges",canteenCharges + 1) playerAction.m_usNumCharges = canteenCharges + 1 else playerAction:SetAttributeValue("critboost",nil) playerAction:SetAttributeValue("ubercharge",1) playerAction:SetAttributeValue("refill_ammo",nil) playerAction:SetAttributeValue("building instant upgrade",nil) playerAction:SetAttributeValue("powerup charges",1) playerAction.m_usNumCharges = 1 end activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value == "buycanteenammo" then activator:RemoveCurrency( CanteenAmmoCost ) local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if playerAction:GetAttributeValue("refill_ammo") == 1 then playerAction:SetAttributeValue("powerup charges",canteenCharges + 1) playerAction.m_usNumCharges = canteenCharges + 1 else playerAction:SetAttributeValue("critboost",nil) playerAction:SetAttributeValue("ubercharge",nil) playerAction:SetAttributeValue("refill_ammo",1) playerAction:SetAttributeValue("building instant upgrade",nil) playerAction:SetAttributeValue("powerup charges",1) playerAction.m_usNumCharges = 1 end activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value == "buycanteenbuilding" then activator:RemoveCurrency( CanteenBuildingCost ) local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if playerAction:GetAttributeValue("building instant upgrade") == 1 then playerAction:SetAttributeValue("powerup charges",canteenCharges + 1) playerAction.m_usNumCharges = canteenCharges + 1 else playerAction:SetAttributeValue("critboost",nil) playerAction:SetAttributeValue("ubercharge",nil) playerAction:SetAttributeValue("refill_ammo",nil) playerAction:SetAttributeValue("building instant upgrade",1) playerAction:SetAttributeValue("powerup charges",1) playerAction.m_usNumCharges = 1 end activator:PlaySound("=80|mvm/mvm_bought_upgrade.wav") elseif value ~= "reroll" then local upgradetable = {} for i in (string.gmatch(value, "[^,]+")) do upgradetable[#upgradetable + 1] = i end local upgrade = upgradetable[1] local attributename = upgradetable[2] if repurchased[value] == nil then repurchased[value] = 1 else repurchased[value] = repurchased[value] + 1 end if purchased[attributename] == nil then purchased[attributename] = 1 else purchased[attributename] = purchased[attributename] + 1 end -- print( purchased ) -- print( purchased[value] ) -- PrintTable(purchased) menu[index].disabled = true AddUpgrade(activator, value) if string.find(upgrade, "(RARE)",1,true) then if localize == "RU" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb Купил: " .. "\x074B69FF".. string.sub(upgrade,1,6) .. "\x07FFD700".. string.sub(upgrade,7,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) elseif localize == "EN" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb has purchased: " .. "\x074B69FF".. string.sub(upgrade,1,6) .. "\x07FFD700".. string.sub(upgrade,7,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) end elseif string.find(upgrade, "[EPIC]",1,true) then if localize == "RU" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb Купил: " .. "\x078847FF".. string.sub(upgrade,1,6) .. "\x07FFD700".. string.sub(upgrade,7,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) elseif localize == "EN" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb has purchased: " .. "\x078847FF".. string.sub(upgrade,1,6) .. "\x07FFD700".. string.sub(upgrade,7,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) end elseif string.find(upgrade, "【LEGENDARY】",1,true) then if localize == "RU" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb Купил: " .. "\x07EB4B4B".. string.sub(upgrade,1,15) .. "\x07FFD700".. string.sub(upgrade,16,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) elseif localize == "EN" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb has purchased: " .. "\x07EB4B4B".. string.sub(upgrade,1,15) .. "\x07FFD700".. string.sub(upgrade,16,#upgrade) .. "\x07fbeccb Level " .. purchased[attributename]) end else if localize == "RU" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb Купил: " .. "\x07FFD700" .. upgrade .. "\x07fbeccb Level " .. purchased[attributename]) elseif localize == "EN" then util.PrintToChatAll("\x07ff3d3d" .. playername .. "\x07fbeccb has purchased: " .. "\x07FFD700" .. upgrade .. "\x07fbeccb Level " .. purchased[attributename]) end end player.UpgradePoints = player.UpgradePoints - 1 player[class].hasRolled = false RollUpgrades(activator) --after purchasing an upgrade, reroll for new set of upgrades else RerollUpgrades(activator) end ShowUpgradeMenu(activator) end, onCancel = nil } } end end --[[Change language using chat commands]] COMMANDS_TABLE = { { name = "!Lang", type = "changelanguage" } , { name = "/Lang", type = "changelanguage" } , { name = "!Language", type = "changelanguage" } , { name = "/Language", type = "changelanguage" } , { name = "!Translate", type = "changelanguage" } , { name = "/Translate", type = "changelanguage" } } local function PlayerChat(event_table) local text = event_table.text local userid = event_table.userid local player = ents.GetPlayerByUserId(userid) if ( player ) and ( player:IsValid() ) and ( player ~= nil ) then -- pcall( OnPlayerChat, player, text ) for i,s in pairs(COMMANDS_TABLE) do if ( string.match(string.lower(text), string.lower(s.name)) ) then if s.type == "changelanguage" then if string.lower(player.Lang) == "ru" then player.Lang = "EN" player:AcceptInput("$DisplayTextChat", "{green}Changing to EN\nUpgrades will change language after rerolling") elseif string.lower(player.Lang) == "en" then player.Lang = "RU" player:AcceptInput("$DisplayTextChat", "{green}Changing to RU\nАпгрейды сменят язык после рерола") else player.Lang = "EN" player:AcceptInput("$DisplayTextChat", "{red}idk, your lang doesn't exist, setting to EN") end end end end end end AddEventCallback("player_say", PlayerChat) -- function OnPlayerChat( player, text ) -- end --[[Your random number generator, returns a float to allow for decimal probabilities In this example, it rolls for rarity first, then rolls a second time to pick an upgrade So the probability of a specific upgrade is based on two rng rolls]] function UpgradeRoulette(activator) local number = math.random() --returns float from 0 to 1 local class = activator.m_iClass local localize = activator.Lang if localize == nil then localize = "RU" activator:AcceptInput("$DisplayTextChat", "{red}Yo, your language setting is nil, using RU.") end local shop = AllShops[localize][class] local pool = {} if number < 0.80 then pool = shop.CommonAttribute elseif (number >= 0.80 and number < 0.95) then pool = shop.RareAttribute elseif (number >= 0.95 and number < 0.99) then pool = shop.EpicAttribute elseif number >= 0.99 then --probably should be less than 1% pool = shop.LegendaryAttribute end local index = math.random(1,(#pool)) --returns integer from 1 to number of upgrades in pool local upgrade = pool[index] return upgrade end --[[This function calls UpgradeRoulette and sends the chosen upgrades to the upgrade menu]] function RollUpgrades(activator) local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass local menu = player[class].UpgradeMenu local purchased = player[class].PurchasedUpgrades --local maxed = player[class].MaxedUpgrades if player[class].hasRolled ~= true then for index = 1, MenuCapacity, 1 do menu[index] = {} --maxed = {} end for index = 1, MenuCapacity, 1 do local upgrade = UpgradeRoulette(activator) --[[Used to prevent maxed out upgrades from reappearing in the shop]] function CheckMaxed(upgrade) local min = upgrade[3] local increment = upgrade[4] local max = upgrade[5] if max ~= nil then if purchased[table.concat(upgrade,",")] ~= nil then local value = min + purchased[table.concat(upgrade,",")] * increment if increment > 0 then return (math.floor(value*100)/100 >= (math.floor(max*100)/100)) --floating point issue else return (math.floor(value*100)/100 <= (math.floor(max*100)/100)) end end end end for i = 1, MenuCapacity, 1 do --If upgrade is duplicate or maxed, reroll if ((menu[i].text == upgrade[1]) or (CheckMaxed(upgrade) == true)) then while ((menu[i].text == upgrade[1]) or (CheckMaxed(upgrade) == true)) do upgrade = UpgradeRoulette(activator) end end end menu[index] = {text = upgrade[1], value = table.concat(upgrade,","), disabled = false} --value can't accept tables, only strings/numbers, do not change value key end player[class].hasRolled = true end end --Called when the reroll option is selected, subtracts a reroll point function RerollUpgrades(activator) local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass player.RerollPoints = player.RerollPoints - 1 player[class].hasRolled = false RollUpgrades(activator) end --Sets hasRolled to false for all players in the game, usually called on wave end function ResetRolls() for _, v in pairs(UniqueAccountIDs) do for i = 1, 9, 1 do if v[i] ~= nil then v[i].hasRolled = false end end end end --[[Apply upgrades to players using "custom" allows you do anything you define in the function as an upgrade meaning PointTemplate upgrades are possible]] function AddUpgrade(activator, value) local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass local purchased = player[class].PurchasedUpgrades local upgradetable = {} for i in string.gmatch(value, "[^,]+") do upgradetable[#upgradetable + 1] = i end local upgrade = upgradetable[1] local attributename = upgradetable[2] local min = tonumber(upgradetable[3]) local increment = tonumber(upgradetable[4]) local max = tonumber(upgradetable[5]) -- PrintTable(upgradetable) -- print( increment ) -- PrintTable(purchased) -- print( purchased[attributename] ) if attributename == "maxammo" then activator:SetAttributeValue("maxammo primary increased",min+increment*purchased[attributename]) activator:SetAttributeValue("maxammo secondary increased",min+increment*purchased[attributename]) activator:SetAttributeValue("maxammo grenades1 increased",min+increment*2*purchased[attributename]) elseif attributename == "concoction" then activator:SetAttributeValue("add cond on hit",123 + 27*256 + 24*65536) --123 = gas, 27 = milk, 24 = jarate, total is 1579899 activator:SetAttributeValue("add cond on hit duration",10) -- activator:SetAttributeValue("bleeding duration",10) elseif attributename == "resistance" then activator:SetAttributeValue("dmg taken from fire reduced",math.max(min+increment*purchased[attributename],max)) activator:SetAttributeValue("dmg taken from crit reduced",math.max(min+increment*purchased[attributename],max)) activator:SetAttributeValue("dmg taken from bullets reduced",math.max(min+increment*purchased[attributename],max)) activator:SetAttributeValue("dmg taken from blast reduced",math.max(min+increment*purchased[attributename],max)) activator:SetAttributeValue("dmg from melee increased",math.max(min+increment*purchased[attributename],max)) activator:SetAttributeValue("damage force reduction",math.max(min+increment*purchased[attributename]*0.66,max)) elseif attributename == "homing" then activator:SetAttributeValue("mod projectile heat seek power",45) activator:SetAttributeValue("mod projectile heat no predict target speed",1) activator:SetAttributeValue("projectile trail particle","eyeboss_projectile") activator:SetAttributeValue("mod projectile heat aim error",90) elseif attributename == "homingbow" then local activatorPrimary = activator:GetPlayerItemBySlot(0) if (activatorPrimary and activatorPrimary:GetClassname() == "tf_weapon_compound_bow") then activatorPrimary:SetAttributeValue("mod projectile heat seek power",45) activatorPrimary:SetAttributeValue("mod projectile heat no predict target speed",1) activatorPrimary:SetAttributeValue("projectile trail particle","eyeboss_projectile") activatorPrimary:SetAttributeValue("mod projectile heat aim error",135) activatorPrimary:SetAttributeValue("mod projectile heat aim start time",0.2) end elseif attributename == "stealth" then activator:GetPlayerItemBySlot(1):SetAttributeValue("add attributes on kill","ignored by bots|1|2") activator:GetPlayerItemBySlot(2):SetAttributeValue("add attributes on kill","ignored by bots|1|2") elseif attributename == "superbleed" then activator:GetPlayerItemBySlot(1):SetAttributeValue("bleeding duration",min+increment*purchased[attributename]) activator:GetPlayerItemBySlot(1):SetAttributeValue("mult bleeding delay",0.2) activator:GetPlayerItemBySlot(1):SetAttributeValue("mult bleeding dmg",10) activator:GetPlayerItemBySlot(2):SetAttributeValue("bleeding duration",min+increment*purchased[attributename]) activator:GetPlayerItemBySlot(2):SetAttributeValue("mult bleeding delay",0.2) activator:GetPlayerItemBySlot(2):SetAttributeValue("mult bleeding dmg",10) elseif attributename == "sentryrockets" then activator:SetAttributeValue("sentry rocket weapon","Sentry_Rocket_Legendary") elseif attributename == "firerate" then activator:SetAttributeValue("fire rate bonus",1/(min+increment*purchased[attributename])) elseif attributename == "reloadrate" then activator:SetAttributeValue("faster reload rate",1/(min+increment*purchased[attributename])) elseif attributename == "sentryfirerate" then activator:SetAttributeValue("engy sentry fire rate increased",1/(min+increment*purchased[attributename])) elseif attributename == "sentryrocketfirerate" then activator:SetAttributeValue("mult firerocket rate",1/(min+increment*purchased[attributename])) elseif attributename == "custom" then if upgrade == "【LEGENDARY】 Турель стреляет микро-ракетами" then activator:SetAttributeValue("sentry bullet weapon","Sentry_Bullet_Legendary") else activator:AcceptInput("$DisplayTextChat", "{FF0000}ERROR! Upgrade {yellow}"..upgrade.."{FF0000} not found!") end elseif attributename ~= "custom" then if max ~= nil then if increment > 0 then activator:SetAttributeValue(attributename,math.min(min+increment*purchased[attributename],max)) else activator:SetAttributeValue(attributename,math.max(min+increment*purchased[attributename],max)) end else activator:SetAttributeValue(attributename,min+increment*purchased[attributename]) end end end --Give all players specified amount of upgrade points, adds running total to TotalUpgradePoints for late joiners function AddUpgradePoints(number) for _, v in pairs(UniqueAccountIDs) do v.UpgradePoints = v.UpgradePoints + number end TotalUpgradePoints = TotalUpgradePoints + number end --Give all players specified amount of rerolls, adds running total to TotalRerollPoints for late joiners function AddRerollPoints(number) for _, v in pairs(UniqueAccountIDs) do v.RerollPoints = v.RerollPoints + number end TotalRerollPoints = TotalRerollPoints + number end --Set all players's upgrade points to specified value without adding or subtracting to TotalUpgradePoints function SetUpgradePoints(number) for _, v in pairs(UniqueAccountIDs) do v.UpgradePoints = number end end --Set all players's rerolls to specified value without adding or subtracting to TotalRerollPoints function SetRerollPoints(number) for _, v in pairs(UniqueAccountIDs) do v.RerollPoints = number end end --Iterates upon PurchasedUpgrades table and calls AddUpgrade for each upgrade, called OnSpawn of every player function ReAddPurchasedUpgrades(activator) local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass local purchased = player[class].RePurchasedUpgrades for k, _ in pairs(purchased) do AddUpgrade(activator, k) end activator:RefillAmmo() end --[[This function will display the shop menu It shows how many upgrade levels were purchased and the max if it exists It will also show the corresponding class you are playing as in the title Shows how many upgrade points are remaining Always adds the reroll option to the bottom of the list Will disable the shop if the player has no more upgrade points]] function ShowUpgradeMenu(activator) local player = UniqueAccountIDs[(ents.FindByClass("tf_player_manager", nil)).m_iAccountID[activator:GetNetIndex()+1]] local class = activator.m_iClass local menu = player[class].UpgradeMenu local purchased = player[class].PurchasedUpgrades local localize = activator.Lang if localize == nil then localize = "RU" activator:AcceptInput("$DisplayTextChat", "{red}Yo, your language setting is nil, using RU.") end local discount = activator:GetAttributeValue("bot medic uber health threshold") or 1 local UpgradeCostFinal = math.floor((UpgradeCost * discount) + 0.5) local RerollCostFinal = math.floor((RerollCost * discount) + 0.5) if localize == "RU" then menu[MenuCapacity+1] = {text="Рерол " .. classIndices_Internal[class] .. " Магаз\n " .. player.RerollPoints .. " реролов", value="reroll"} if player.RerollPoints == 1 then menu[MenuCapacity+1] = {text="Рерол " .. classIndices_Internal[class] .. " Магаз\n " .. player.RerollPoints .. " рерол", value="reroll"} elseif player.RerollPoints <= 0 then menu[MenuCapacity+1] = {text="Рерол " .. classIndices_Internal[class] .. " Магаз\n " .. player.RerollPoints .. " реролов", value="reroll", disabled = true} end if ( activator.m_nCurrency >= UpgradeCostFinal ) then menu[MenuCapacity+2] = {text="+1 " .. classIndices_Internal[class] .. " апгрейд: " .. UpgradeCostFinal .. "$", value="buyupgrade"} else menu[MenuCapacity+2] = {text="+1 " .. classIndices_Internal[class] .. " апгрейд: " .. UpgradeCostFinal .. "$", value="buyupgrade", disabled = true} end if ( activator.m_nCurrency >= RerollCostFinal ) then menu[MenuCapacity+3] = {text="+1 рерол: " .. RerollCostFinal .. "$", value="buyreroll"} else menu[MenuCapacity+3] = {text="+1 рерол: " .. RerollCostFinal .. "$", value="buyreroll", disabled = true} end local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) if (playerAction and playerAction:GetClassname() == "tf_powerup_bottle") then local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if ( activator.m_nCurrency >= CanteenCritCost and canteenCharges <3 ) then menu[MenuCapacity+4] = {text="+1 Крит фляга: " .. CanteenCritCost .. "$", value="buycanteencrit"} else menu[MenuCapacity+4] = {text="+1 Крит фляга: " .. CanteenCritCost .. "$", value="buycanteencrit", disabled = true} end if ( activator.m_nCurrency >= CanteenUberCost and canteenCharges <3 ) then menu[MenuCapacity+5] = {text="+1 Убер фляга: " .. CanteenUberCost .. "$", value="buycanteenuber"} else menu[MenuCapacity+5] = {text="+1 Убер фляга: " .. CanteenUberCost .. "$", value="buycanteenuber", disabled = true} end if ( activator.m_nCurrency >= CanteenAmmoCost and canteenCharges <3 ) then menu[MenuCapacity+6] = {text="+1 Фляга патронов: " .. CanteenAmmoCost .. "$", value="buycanteenammo"} else menu[MenuCapacity+6] = {text="+1 Фляга патронов: " .. CanteenAmmoCost .. "$", value="buycanteenammo", disabled = true} end if classIndices_Internal[class] == "Engineer" then if ( activator.m_nCurrency >= CanteenBuildingCost and canteenCharges <3 ) then menu[MenuCapacity+7] = {text="+1 Фляга пастроек: " .. CanteenBuildingCost .. "$", value="buycanteenbuilding"} else menu[MenuCapacity+7] = {text="+1 Фляга пастроек: " .. CanteenBuildingCost .. "$", value="buycanteenbuilding", disabled = true} end end end menu.title = classIndices_Internal[class] .. " Магаз\nВыберите\n" .. player.UpgradePoints .. " Осталось\n " if player.UpgradePoints == 1 then menu.title = classIndices_Internal[class] .. " Магаз\nВыберите\n" .. player.UpgradePoints .. " Осталось\n " for i = 1, MenuCapacity, 1 do menu[i].disabled = false end elseif player.UpgradePoints <= 0 then for i = 1, MenuCapacity+1, 1 do menu[i].disabled = true end end elseif localize == "EN" then menu[MenuCapacity+1] = {text="Reroll " .. classIndices_Internal[class] .. " Shop\n " .. player.RerollPoints .. " rerolls remaining", value="reroll"} if player.RerollPoints == 1 then menu[MenuCapacity+1] = {text="Reroll " .. classIndices_Internal[class] .. " Shop\n " .. player.RerollPoints .. " reroll remaining", value="reroll"} elseif player.RerollPoints <= 0 then menu[MenuCapacity+1] = {text="Reroll " .. classIndices_Internal[class] .. " Shop\n " .. player.RerollPoints .. " rerolls remaining", value="reroll", disabled = true} end if ( activator.m_nCurrency >= UpgradeCostFinal ) then menu[MenuCapacity+2] = {text="+1 " .. classIndices_Internal[class] .. " upgrade: " .. UpgradeCostFinal .. "$", value="buyupgrade"} else menu[MenuCapacity+2] = {text="+1 " .. classIndices_Internal[class] .. " upgrade: " .. UpgradeCostFinal .. "$", value="buyupgrade", disabled = true} end if ( activator.m_nCurrency >= RerollCostFinal ) then menu[MenuCapacity+3] = {text="+1 reroll: " .. RerollCostFinal .. "$", value="buyreroll"} else menu[MenuCapacity+3] = {text="+1 reroll: " .. RerollCostFinal .. "$", value="buyreroll", disabled = true} end local playerAction = activator:GetPlayerItemBySlot(LOADOUT_POSITION_ACTION) if (playerAction and playerAction:GetClassname() == "tf_powerup_bottle") then local canteenCharges = playerAction:GetAttributeValue("powerup charges") or 0 if ( activator.m_nCurrency >= CanteenCritCost and canteenCharges <3 ) then menu[MenuCapacity+4] = {text="+1 Crit Canteen: " .. CanteenCritCost .. "$", value="buycanteencrit"} else menu[MenuCapacity+4] = {text="+1 Crit Canteen: " .. CanteenCritCost .. "$", value="buycanteencrit", disabled = true} end if ( activator.m_nCurrency >= CanteenUberCost and canteenCharges <3 ) then menu[MenuCapacity+5] = {text="+1 Uber Canteen: " .. CanteenUberCost .. "$", value="buycanteenuber"} else menu[MenuCapacity+5] = {text="+1 Uber Canteen: " .. CanteenUberCost .. "$", value="buycanteenuber", disabled = true} end if ( activator.m_nCurrency >= CanteenAmmoCost and canteenCharges <3 ) then menu[MenuCapacity+6] = {text="+1 Ammo Canteen: " .. CanteenAmmoCost .. "$", value="buycanteenammo"} else menu[MenuCapacity+6] = {text="+1 Ammo Canteen: " .. CanteenAmmoCost .. "$", value="buycanteenammo", disabled = true} end if classIndices_Internal[class] == "Engineer" then if ( activator.m_nCurrency >= CanteenBuildingCost and canteenCharges <3 ) then menu[MenuCapacity+7] = {text="+1 Building Canteen: " .. CanteenBuildingCost .. "$", value="buycanteenbuilding"} else menu[MenuCapacity+7] = {text="+1 Building Canteen: " .. CanteenBuildingCost .. "$", value="buycanteenbuilding", disabled = true} end end end menu.title = classIndices_Internal[class] .. " Shop\nSelect an upgrade\n" .. player.UpgradePoints .. " upgrade points remaining\n " if player.UpgradePoints == 1 then menu.title = classIndices_Internal[class] .. " Shop\nSelect an upgrade\n" .. player.UpgradePoints .. " upgrade point remaining\n " for i = 1, MenuCapacity, 1 do menu[i].disabled = false end elseif player.UpgradePoints <= 0 then for i = 1, MenuCapacity+1, 1 do menu[i].disabled = true end end end for i = 1, MenuCapacity, 1 do local value = menu[i].value local upgradetable = {} for k in string.gmatch(value, "[^,]+") do upgradetable[#upgradetable + 1] = k end local attributename = upgradetable[2] local min = upgradetable[3] local increment = upgradetable[4] local max = upgradetable[5] if purchased[attributename] ~= nil then menu[i].text = menu[i].text .. "\n #: " .. purchased[attributename] else menu[i].text = menu[i].text .. "\n #: 0" end if max ~= nil then menu[i].text = menu[i].text .. " Max: " .. math.ceil((max-min)/increment) --big brain math end end activator:DisplayMenu(menu) for i = 1, MenuCapacity, 1 do local value = menu[i].value local upgradetable = {} for k in string.gmatch(value, "[^,]+") do upgradetable[#upgradetable + 1] = k end upgrade = upgradetable[1] menu[i].text = upgrade end end function CloseUpgradeMenu(activator) --probably redundnant activator:HideMenu() end function deepCopy(original) --special thx to https://developer.roblox.com local copy = {} for k, v in pairs(original) do if type(v) == "table" then v = deepCopy(v) end copy[k] = v end return copy end function OnWaveSuccess(wave) --adds however many upgrade points every wave, can also be edited to do other things AddUpgradePoints(UpgradePointsPerWave) AddRerollPoints(RerollPointsPerWave) end function OnWaveReset(wave) --on wave reset, load save state from WaveState if WaveState[wave] ~= nil then TotalUpgradePoints = WaveState[wave].TotalUpgradePoints TotalRerollPoints = WaveState[wave].TotalRerollPoints UniqueAccountIDs = deepCopy(WaveState[wave].UniqueAccountIDs) end end function OnWaveInit(wave) --on wave init, create save state in WaveState, reset rolls EnableUpgradeStations() --for wave 1 if WaveState[wave] == nil then WaveState[wave] = { TotalUpgradePoints = TotalUpgradePoints, TotalRerollPoints = TotalRerollPoints, UniqueAccountIDs = deepCopy(UniqueAccountIDs) } end ResetRolls() end