diff --git a/CHANGELOG.md b/CHANGELOG.md index eeb4967a3c..d1905f2930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,86 @@ # Changelog +## Version 8.98 (August 10, 2023) + +### Bug Fixes + +#### Core Plugin +- Fixed the `Health` and `Refill` rewards not rewarding recipients with health properly. (Thanks to `xcd222` for reporting!) [Fixed in `v8.97`.] + +#### Config Files +- Fixed custom config Mutant Tank types overlapping with main config Mutant Tank types. (Thanks to `xcd222` for reporting!) + +#### Settings +- Fixed the `Reward Visual` setting's limit. (Thanks to `swofleswof` for testing and reporting!) + +#### Abilities +- Gunner: Fixed an error that caused the server to crash. (Thanks to `Mi.Cura` for testing and reporting!) +- Item, Kamikaze, Rocket, Smash, Smite: Fixed survivor ragdolls being erased by all Mutant Tank types. (Thanks to `George Rex` for reporting!) [Fixed in `v8.97`.] +- Throw: Fixed Mutant Tank types not being able to throw cars and special infected. (Thanks to `xcd222` for reporting!) [Fixed in `v8.97`.] + +### Changes + +#### Core Plugin +- The godmode reward now prevents recipients from being pinned by any special infected. + +#### ConVars +- Added the `mt_configfile` convar. (Requested by `zonbarbar`.) +- Added a lock mechanism to enforce temporary values across maps for the core plugin's convars. (Thanks to `NgBUCKWANGS` for the code!) + - Use `-l-` in front of the new value to enforce that value for the convar. (Example: `mt_configfile "-l-myconfig.cfg"`) + - Use `-u-` in front of the new value to allow the convar to accept new values. (Example: `mt_configfile "-u-myconfig.cfg"`) + +#### Game Data +- Added signatures for the following functions: + - `CTerrorPlayer::GrabVictimWithTongue` + - `CTerrorPlayer::OnLeptOnSurvivor` + - `CTerrorPlayer::OnPouncedOnSurvivor` + - `CTerrorPlayer::OnStartCarryingVictim` + - `CTerrorPlayer::QueuePummelVictim` + +#### Settings +- Added the `Prioritize Throws` setting under the `Plugin Settings->Competitive` and `Tank #->Competitive` sections. (Requested by `xcd222`.) [Thanks to `Silvers` for the help!] + +### Files + +#### General +- The pre-compiled plugins included in the package are: + - Compiled without any of the optional dependencies. + - Compiled with the `SourceMod 1.12.0.6985` compiler. + +#### Updates +- Updated config files. +- Updated gamedata file. +- Updated include file. +- Updated translation files. +- Updated updater file. + ## Version 8.97 (May 21, 2023) +
+ Click to expand! ### Bug Fixes +
+ General #### General - Fixed an issue where some RNG-based events happen too often. (Thanks to `ddd123` for reporting!) - Fixed an issue where Witches take a long time to die from fires. (Thanks to `ddd123` for reporting!) - Fixed rare array index errors. +
+
+ Core Plugin #### Core Plugin - Fixed Tank death messages not appearing when a survivor solos a Tank. +
+
+ Config Files #### Config Files - Fixed Mutant Tank type settings not being read properly under combined sections. +
+
+ Abilities #### Abilities - Gunner @@ -21,41 +88,65 @@ - Fixed the ability targeting the Tank itself. - Quiet: Fixed the sound hook blocking other sound hooks. - Rocket: Fixed an issue where survivor ragdolls will not disappear if the player goes afk and is replaced by a survivor bot. (Thanks to `Slaven555` for testing and reporting!) +
### Changes +
+ General #### General - Mutant Tanks and its sub-plugins now properly support the [`[L4D & L4D2] Lagged Movement - Plugin Conflict Resolver`](https://forums.alliedmods.net/showthread.php?t=340345) plugin. +
+
+ Commands #### Commands - Added a 4th parameter for the `sm_tank` command. (Usage: `sm_tank <1-500> <0: spawn on crosshair|1: spawn automatically> <0: not blind|1: blind>`) +
+
+ Game Data #### Game Data - L4D2: Updated some signatures and offsets for the `2.2.2.7` update. +
+
+ Settings + +#### Settings +- Added the `Footstep Shake` setting under the `Plugin Settings->Enhancements`, `Tank #->Enhancements`, and `STEAM_ID->Enhancements` sections. (Thanks to `Silvers` for the code!) +- Added the `Refill Percent Reward` setting under the `Plugin Settings->Rewards`, `Tank #->Rewards`, and `STEAM_ID->Rewards` sections. (Thanks to `DARG367` for suggesting!) +- Updated the `Stack Limits` setting to accept an `8th` value. +
+
+ Abilities #### Abilities - Gravity - Added the `Gravity Radius` setting. - Added the `Gravity Rock Break` setting. (Thanks to `JustMadMan` for the idea!) - Added the `Gravity Rock Chance` setting. (Thanks to `JustMadMan` for the idea!) - -#### Settings -- Added the `Footstep Shake` setting under the `Plugin Settings->Enhancements`, `Tank #->Enhancements`, and `STEAM_ID->Enhancements` sections. (Thanks to `Silvers` for the code!) -- Added the `Refill Percent Reward` setting under the `Plugin Settings->Rewards`, `Tank #->Rewards`, and `STEAM_ID->Rewards` sections. (Thanks to `DARG367` for suggesting!) -- Updated the `Stack Limits` setting to accept an `8th` value. +
+
+ Translations #### Translations - Updated English translations. - Updated Simplified Chinese translations. - Updated Hungarian translations. - Updated Russian translations. +
### Files +
+ General #### General - The pre-compiled plugins included in the package are: - Compiled without any of the optional dependencies. - Compiled with the `SourceMod 1.12.0.6985` compiler. +
+
+ Updates #### Updates - Updated config files. @@ -63,6 +154,8 @@ - Updated include file. - Updated translation files. - Updated updater file. +
+
## Version 8.96 (December 25, 2022)
diff --git a/INFORMATION.md b/INFORMATION.md index 8bab7b4141..b0316dc99d 100644 --- a/INFORMATION.md +++ b/INFORMATION.md @@ -631,7 +631,7 @@ // 32: Item reward // - Receive up to five items. // 64: God mode reward (temporary) - // - Automatically kill all special infected attackers. + // - Automatically prevent attacks from and kill all special infected attackers. // - Immune to all types of damage. // - Cannot be flung away by Chargers. // - Cannot be pushed around. @@ -733,7 +733,7 @@ // 32: Item reward // - Receive up to five items. // 64: God mode reward (temporary) - // - Automatically kill all special infected attackers. + // - Automatically prevent attacks from and kill all special infected attackers. // - Immune to all types of damage. // - Cannot be flung away by Chargers. // - Cannot be pushed around. @@ -874,21 +874,22 @@ // Add up numbers together for different results. // -- // Minimum value for each: 0 - // Maximum value for each: 63 + // Maximum value for each: 127 // -- // 0: OFF // 1: Screen color // 2: Particle effect // 4: Looping voiceline - // 8: Light color - // 16: Body color - // 32: Glow outline (Only available in Left 4 Dead 2.) + // 8: Voice pitch + // 16: Light color + // 32: Body color + // 64: Glow outline (Only available in Left 4 Dead 2.) // -- // 1st number = Visual effect for killers. // 2nd number = Visual effect for assistants. // 3rd number = Visual effect for teammates. // 4th number = Visual effect for assistant killers. - "Reward Visual" "63,63,63,63" + "Reward Visual" "127,127,127,127" // Default is "63" on Left 4 Dead 1. // Enable the "sm_mt_prefs" command and notify players about it. // Note: This setting can be used for standard Tanks. @@ -1896,6 +1897,16 @@ // Maximum: 99999.0 "Force Spawn" "0.0" + // (Co-Op modes only) Mutant Tanks should prioritize throwing rocks. + // Note: Tanks only prioritize throwing rocks on Advanced and Expert modes by default. + // Note: Do not change this setting if you are unsure of how it works. + // Note: This setting can be used for standard Tanks. + // Note: This setting can be overridden for each Mutant Tank under the "Competitive" section of their settings. + // -- + // 0/"disabled"/"false"/"off"/"no": OFF, let the game determine Mutant Tanks' attack. + // 1/"enabled"/"true"/"on"/"yes": ON, force Mutant Tanks to prioritize throwing rocks. + "Prioritize Throws" "0" + // The stasis mode of Mutant Tanks when spawning. // Note: Do not change this setting if you are unsure of how it works. // Note: This setting can be used for standard Tanks. @@ -3013,7 +3024,7 @@ // 32: Item reward // - Receive up to five items. // 64: God mode reward (temporary) - // - Automatically kill all special infected attackers. + // - Automatically prevent attacks from and kill all special infected attackers. // - Immune to all types of damage. // - Cannot be flung away by Chargers. // - Cannot be pushed around. @@ -3115,7 +3126,7 @@ // 32: Item reward // - Receive up to five items. // 64: God mode reward (temporary) - // - Automatically kill all special infected attackers. + // - Automatically prevent attacks from and kill all special infected attackers. // - Immune to all types of damage. // - Cannot be flung away by Chargers. // - Cannot be pushed around. @@ -3256,15 +3267,16 @@ // Add up numbers together for different results. // -- // Minimum value for each: 0 - // Maximum value for each: 63 + // Maximum value for each: 127 // -- // 0: OFF // 1: Screen color // 2: Particle effect // 4: Looping voiceline - // 8: Light color - // 16: Body color - // 32: Glow outline (Only available in Left 4 Dead 2.) + // 8: Voice pitch + // 16: Light color + // 32: Body color + // 64: Glow outline (Only available in Left 4 Dead 2.) // -- // 1st number = Visual effect for killers. // 2nd number = Visual effect for assistants. @@ -4260,6 +4272,15 @@ // 0/"disabled"/"false"/"off"/"no": OFF, let the game determine the Mutant Tank's initial behavior. // 1/"enabled"/"true"/"on"/"yes": ON, force the Mutant Tank to attack immediately. "Auto Aggravate" "0" + + // (Co-Op modes only) The Mutant Tank should prioritize throwing rocks. + // Note: Tanks only prioritize throwing rocks on Advanced and Expert modes by default. + // Note: Do not change this setting if you are unsure of how it works. + // Note: This setting overrides the same setting under the "Plugin Settings/Competitive" section. + // -- + // 0/"disabled"/"false"/"off"/"no": OFF, let the game determine Mutant Tanks' attack. + // 1/"enabled"/"true"/"on"/"yes": ON, force Mutant Tanks to prioritize throwing rocks. + "Prioritize Throws" "0" } "Glow" { diff --git a/README.md b/README.md index 5f023bc8a2..1e8ed2f8af 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,13 @@ sm_mt_zombie - View information about the Zombie ability. // Maximum: "1.000000" mt_autoupdate "0" +// The config filename used by Mutant Tanks to read settings from. +// Empty: None +// Not empty: The custom config filename to use. +// - +// Default: "mutant_tanks.cfg" +mt_configfile "mutant_tanks.cfg" + // Disable Mutant Tanks in these game modes. // Separate by commas. // Empty: None @@ -2754,9 +2761,9 @@ Set the values in `Execute Config Types`. **ReCreator, SilentBr, Neptunia, Zytheus, huwong, Tank Rush, Tonblader, TheStarRocker, Maku, Shadowart, saberQAQ, Shao, xcd222** - For reporting issues and suggesting ideas. -**Princess LadyRain, Nekrob, fig101, BloodyBlade, user2000, MedicDTI, ben12398, AK978, ricksfishin, Voevoda, ur5efj, What, moekai, weffer, AlexAlcala, ddd123, GL_INS, Slaven555, Neki93, kot4404, KadabraZz, Krufftys Killers, thewintersoldier97, Balloons, George Rex** - For reporting issues. +**Princess LadyRain, Nekrob, fig101, BloodyBlade, user2000, MedicDTI, ben12398, AK978, ricksfishin, Voevoda, ur5efj, What, moekai, weffer, AlexAlcala, ddd123, GL_INS, Slaven555, Neki93, kot4404, KadabraZz, Krufftys Killers, thewintersoldier97, Balloons, George Rex, swofleswof** - For reporting issues. -**Electr000999, foquaxticity, foxhound27, sxslmk, FatalOE71, zaviier, RDiver, BHaType, HarryPotter, jeremyvillanueva, DonProof, XXrevoltadoXX, XYZC, moschinovac, JustMadMan, DARG367** - For suggesting ideas. +**Electr000999, foquaxticity, foxhound27, sxslmk, FatalOE71, zaviier, RDiver, BHaType, HarryPotter, jeremyvillanueva, DonProof, XXrevoltadoXX, XYZC, moschinovac, JustMadMan, DARG367, zonbarbar** - For suggesting ideas. **Marttt** - For helping with many things and the pull requests. diff --git a/README_RU.md b/README_RU.md index 53c659338e..4210dd8b19 100644 --- a/README_RU.md +++ b/README_RU.md @@ -202,6 +202,13 @@ sm_mt_zombie - Просмотр информации о способности // Максимум: "1.000000" mt_autoupdate "0" +// Имя файла конфигурации, из которого плагин считывает настройки. +// Пусто: нет +// Не пусто: Имя файла пользовательской конфигурации для использования. +// - +// По умолчанию: "mutant_tanks.cfg" +mt_configfile "mutant_tanks.cfg" + // Отключить Танков-мутантов в этих режимах игры. // Через запятую. // Пусто: Нет @@ -2754,9 +2761,9 @@ Overrides **ReCreator, SilentBr, Neptunia, Zytheus, huwong, Tank Rush, Tonblader, TheStarRocker, Maku, Shadowart, saberQAQ, Shao, xcd222** - За сообщения о проблемах и предложения идей. -**Princess LadyRain, Nekrob, fig101, BloodyBlade, user2000, MedicDTI, ben12398, AK978, ricksfishin, Voevoda, ur5efj, What, moekai, weffer, AlexAlcala, ddd123, GL_INS, Slaven555, Neki93, kot4404, KadabraZz, Krufftys Killers, thewintersoldier97, Balloons, George Rex** - За сообщения о проблемах. +**Princess LadyRain, Nekrob, fig101, BloodyBlade, user2000, MedicDTI, ben12398, AK978, ricksfishin, Voevoda, ur5efj, What, moekai, weffer, AlexAlcala, ddd123, GL_INS, Slaven555, Neki93, kot4404, KadabraZz, Krufftys Killers, thewintersoldier97, Balloons, George Rex, swofleswof** - За сообщения о проблемах. -**Electr000999, foquaxticity, foxhound27, sxslmk, FatalOE71, zaviier, RDiver, BHaType, HarryPotter, jeremyvillanueva, DonProof, XXrevoltadoXX, XYZC, moschinovac, JustMadMan, DARG367** - За предложения идей. +**Electr000999, foquaxticity, foxhound27, sxslmk, FatalOE71, zaviier, RDiver, BHaType, HarryPotter, jeremyvillanueva, DonProof, XXrevoltadoXX, XYZC, moschinovac, JustMadMan, DARG367, zonbarbar** - За предложения идей. **Marttt** - За помощь во многих вещах и pull request'ы. diff --git a/addons/sourcemod/data/mutant_tanks/backup_config/format1/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/backup_config/format1/mutant_tanks.cfg index c8a01d91d5..863c0b8e6e 100644 --- a/addons/sourcemod/data/mutant_tanks/backup_config/format1/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/backup_config/format1/mutant_tanks.cfg @@ -60,7 +60,7 @@ "Reward Effect" "15,15,15,15" "Reward Notify" "3,3,3,3" "Reward Percentage" "10.0,10.0,10.0,10.0" - "Reward Visual" "63,63,63,63" + "Reward Visual" "127,127,127,127" "Prefs Notify" "1,1,1,1" "Share Rewards" "0,0,0,0" "Teammate Limit" "0" @@ -117,12 +117,13 @@ "Auto Aggravate" "Enabled" "Credit Igniters" "True" "Force Spawn" "Min" - "Stasis Mode" "No" + "Prioritize Throws" "No" + "Stasis Mode" "Off" "Survival Delay" "Min" } "Difficulty" { - "Scale Damage" "Off" + "Scale Damage" "Disabled" "Difficulty Damage" "0.0,0.0,0.0,0.0" } "Health" @@ -165,7 +166,7 @@ "Human Support" { "Human Cooldown" "600" - "Master Control" "Disabled" + "Master Control" "False" "Spawn Mode" "Yes" } "Waves" @@ -177,7 +178,7 @@ "Regular Interval" "300.0" "Regular Limit" "99999" "Regular Type" "1-127" - "Regular Wave" "False" + "Regular Wave" "No" "Finale Amount" "Min" "Finale Types" "1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127" "Finale Waves" "0,0,0,0,0,0,0,0,0,0,0" @@ -198,7 +199,7 @@ } "Custom" { - "Enable Custom Configs" "No" + "Enable Custom Configs" "Off" "Create Config Types" "Min" "Execute Config Delay" "5.0" "Execute Config Types" "Min" diff --git a/addons/sourcemod/data/mutant_tanks/backup_config/format2/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/backup_config/format2/mutant_tanks.cfg index f730573562..8553fbabb0 100644 --- a/addons/sourcemod/data/mutant_tanks/backup_config/format2/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/backup_config/format2/mutant_tanks.cfg @@ -60,7 +60,7 @@ MutantTanks RewardEffect 15,15,15,15 RewardNotify 3,3,3,3 RewardPercentage 10.0,10.0,10.0,10.0 - RewardVisual 63,63,63,63 + RewardVisual 127,127,127,127 PrefsNotify 1,1,1,1 ShareRewards 0,0,0,0 TeammateLimit 0 @@ -117,12 +117,13 @@ MutantTanks AutoAggravate Enabled CreditIgniters True ForceSpawn Min - StasisMode No + PrioritizeThrows No + StasisMode Off SurvivalDelay Min } Difficulty { - ScaleDamage Off + ScaleDamage Disabled DifficultyDamage 0.0,0.0,0.0,0.0 } Health @@ -165,7 +166,7 @@ MutantTanks HumanSupport { HumanCooldown 600 - MasterControl Disabled + MasterControl False SpawnMode Yes } Waves @@ -198,7 +199,7 @@ MutantTanks } Custom { - EnableCustomConfigs No + EnableCustomConfigs Off CreateConfigTypes Min ExecuteConfigDelay 5.0 ExecuteConfigTypes Min diff --git a/addons/sourcemod/data/mutant_tanks/backup_config/format3/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/backup_config/format3/mutant_tanks.cfg index 47d1410e5d..13ee6b10df 100644 --- a/addons/sourcemod/data/mutant_tanks/backup_config/format3/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/backup_config/format3/mutant_tanks.cfg @@ -60,7 +60,7 @@ Mutant_Tanks Reward_Effect 15,15,15,15 Reward_Notify 3,3,3,3 Reward_Percentage 10.0,10.0,10.0,10.0 - Reward_Visual 63,63,63,63 + Reward_Visual 127,127,127,127 Prefs_Notify 1,1,1,1 Share_Rewards 0,0,0,0 Teammate_Limit 0 @@ -117,12 +117,13 @@ Mutant_Tanks Auto_Aggravate Enabled Credit_Igniters True Force_Spawn Min - Stasis_Mode No + Prioritize_Throws No + Stasis_Mode Off Survival_Delay Min } Difficulty { - Scale_Damage Off + Scale_Damage Disabled Difficulty_Damage 0.0,0.0,0.0,0.0 } Health @@ -165,7 +166,7 @@ Mutant_Tanks Human_Support { Human_Cooldown 600 - Master_Control Disabled + Master_Control False Spawn_Mode Yes } Waves @@ -177,7 +178,7 @@ Mutant_Tanks Regular_Interval 300.0 Regular_Limit 99999 Regular_Type 1-127 - Regular_Wave False + Regular_Wave No Finale_Amount Min Finale_Types 1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127 Finale_Waves 0,0,0,0,0,0,0,0,0,0,0 @@ -198,7 +199,7 @@ Mutant_Tanks } Custom { - Enable_Custom_Configs No + Enable_Custom_Configs Off Create_Config_Types Min Execute_Config_Delay 5.0 Execute_Config_Types Min diff --git a/addons/sourcemod/data/mutant_tanks/backup_config/format4/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/backup_config/format4/mutant_tanks.cfg index 625120e956..b86079d5ab 100644 --- a/addons/sourcemod/data/mutant_tanks/backup_config/format4/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/backup_config/format4/mutant_tanks.cfg @@ -60,7 +60,7 @@ mtanks effect 15,15,15,15 rnotify 3,3,3,3 percent 10.0,10.0,10.0,10.0 - visual 63,63,63,63 + visual 127,127,127,127 pnotify 1,1,1,1 share 0,0,0,0 teamlimit 0 @@ -117,12 +117,13 @@ mtanks autoaggro enabled credit true force min - stasis no + priothrow no + stasis off survdelay min } diff { - scaledmg off + scaledmg disabled diffdmg 0.0,0.0,0.0,0.0 } health @@ -165,7 +166,7 @@ mtanks human { cooldown 600 - master disabled + master false spawnmode yes } waves @@ -177,7 +178,7 @@ mtanks reginterval 300.0 reglimit 99999 regtype 1-127 - regwave false + regwave no finamount min fintypes 1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127 finwaves 0,0,0,0,0,0,0,0,0,0,0 @@ -198,7 +199,7 @@ mtanks } custom { - cenabled no + cenabled off create min delay 5.0 execute min diff --git a/addons/sourcemod/data/mutant_tanks/backup_config/format5/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/backup_config/format5/mutant_tanks.cfg index 2ab24fe101..f5eac47c8b 100644 --- a/addons/sourcemod/data/mutant_tanks/backup_config/format5/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/backup_config/format5/mutant_tanks.cfg @@ -60,7 +60,7 @@ mt effect 15,15,15,15 rnotify 3,3,3,3 percent 10.0,10.0,10.0,10.0 - visual 63,63,63,63 + visual 127,127,127,127 pnotify 1,1,1,1 share 0,0,0,0 teamlimit 0 @@ -117,12 +117,13 @@ mt autoaggro enabled credit true force min - stasis no + priothrow no + stasis off survdelay min } diff { - scaledmg off + scaledmg disabled diffdmg 0.0,0.0,0.0,0.0 } health @@ -165,7 +166,7 @@ mt human { cooldown 600 - master disabled + master false spawnmode yes } waves @@ -177,7 +178,7 @@ mt reginterval 300.0 reglimit 99999 regtype 1-127 - regwave false + regwave no finamount min fintypes 1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127 finwaves 0,0,0,0,0,0,0,0,0,0,0 @@ -198,7 +199,7 @@ mt } custom { - cenabled no + cenabled off create min delay 5.0 execute min diff --git a/addons/sourcemod/data/mutant_tanks/mutant_tanks.cfg b/addons/sourcemod/data/mutant_tanks/mutant_tanks.cfg index 9b5ab25311..e8eea53702 100644 --- a/addons/sourcemod/data/mutant_tanks/mutant_tanks.cfg +++ b/addons/sourcemod/data/mutant_tanks/mutant_tanks.cfg @@ -60,7 +60,7 @@ "Reward Effect" "15,15,15,15" "Reward Notify" "3,3,3,3" "Reward Percentage" "10.0,10.0,10.0,10.0" - "Reward Visual" "63,63,63,63" + "Reward Visual" "127,127,127,127" "Prefs Notify" "1,1,1,1" "Share Rewards" "0,0,0,0" "Teammate Limit" "0" @@ -117,12 +117,13 @@ "Auto Aggravate" "Enabled" "Credit Igniters" "True" "Force Spawn" "Min" - "Stasis Mode" "No" + "Prioritize Throws" "No" + "Stasis Mode" "Off" "Survival Delay" "Min" } "Difficulty" { - "Scale Damage" "Off" + "Scale Damage" "Disabled" "Difficulty Damage" "0.0,0.0,0.0,0.0" } "Health" @@ -165,7 +166,7 @@ "Human Support" { "Human Cooldown" "600" - "Master Control" "Disabled" + "Master Control" "False" "Spawn Mode" "Yes" } "Waves" @@ -177,7 +178,7 @@ "Regular Interval" "300.0" "Regular Limit" "99999" "Regular Type" "1-127" - "Regular Wave" "False" + "Regular Wave" "No" "Finale Amount" "Min" "Finale Types" "1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127,1-127" "Finale Waves" "0,0,0,0,0,0,0,0,0,0,0" @@ -198,7 +199,7 @@ } "Custom" { - "Enable Custom Configs" "No" + "Enable Custom Configs" "Off" "Create Config Types" "Min" "Execute Config Delay" "5.0" "Execute Config Types" "Min" diff --git a/addons/sourcemod/data/mutant_tanks/mutant_tanks_detours.cfg b/addons/sourcemod/data/mutant_tanks/mutant_tanks_detours.cfg index 420ab5a2ea..8170232bcc 100644 --- a/addons/sourcemod/data/mutant_tanks/mutant_tanks_detours.cfg +++ b/addons/sourcemod/data/mutant_tanks/mutant_tanks_detours.cfg @@ -272,6 +272,14 @@ "Pre-Hook" "2" "Post-Hook" "0" } + "MTDetour_CTerrorPlayer::GrabVictimWithTongue" + { + "Log" "0" + "Cvar Check" "left4dhooks_version" + "Type" "4" + "Pre-Hook" "2" + "Post-Hook" "0" + } "MTDetour_CTerrorPlayer::OnBeginChangeLevel" { "Log" "0" @@ -333,6 +341,14 @@ "Pre-Hook" "1" "Post-Hook" "1" } + "MTDetour_CTerrorPlayer::OnPouncedOnSurvivor" + { + "Log" "0" + "Cvar Check" "left4dhooks_version" + "Type" "4" + "Pre-Hook" "2" + "Post-Hook" "0" + } "MTDetour_CTerrorPlayer::OnRevived" { "Log" "0" @@ -433,6 +449,13 @@ "Pre-Hook" "0" "Post-Hook" "2" } + "MTDetour_TankAttack::TryToThrowRock" + { + "Log" "0" + "Type" "3" + "Pre-Hook" "1" + "Post-Hook" "1" + } "MTDetour_TankBehavior::InitialContainedAction" { "Log" "0" @@ -549,6 +572,30 @@ "Pre-Hook" "2" "Post-Hook" "0" } + "MTDetour_CTerrorPlayer::OnLeptOnSurvivor" + { + "Log" "0" + "Cvar Check" "left4dhooks_version" + "Type" "4" + "Pre-Hook" "2" + "Post-Hook" "0" + } + "MTDetour_CTerrorPlayer::OnStartCarryingVictim" + { + "Log" "0" + "Cvar Check" "left4dhooks_version" + "Type" "4" + "Pre-Hook" "2" + "Post-Hook" "0" + } + "MTDetour_CTerrorPlayer::QueuePummelVictim" + { + "Log" "0" + "Cvar Check" "left4dhooks_version" + "Type" "4" + "Pre-Hook" "2" + "Post-Hook" "0" + } "MTDetour_CTerrorPlayer::SelectWeightedSequence" { "Log" "0" diff --git a/addons/sourcemod/data/mutant_tanks/mutant_tanks_patches.cfg b/addons/sourcemod/data/mutant_tanks/mutant_tanks_patches.cfg index 6f5b851633..5c4891508a 100644 --- a/addons/sourcemod/data/mutant_tanks/mutant_tanks_patches.cfg +++ b/addons/sourcemod/data/mutant_tanks/mutant_tanks_patches.cfg @@ -522,6 +522,50 @@ "Patch" "\xC2\x04\x00" } } + "MTPatch_TankAttackDifficulty" + { + "Log" "0" + "Type" "1" + "Signature" "TankAttack::TryToThrowRock" + "Offset" "TankAttack::TryToThrowRock::GetDifficulty" + "Linux" + { + "Verify" "\x0F\x85" + "Patch" "\x0F\x8D" + } + "Mac" + { + "Verify" "\x74" + "Patch" "\xEB" + } + "Windows" + { + "Verify" "\x74" + "Patch" "\xEB" + } + } + "MTPatch_TankAttackDifficulty2" + { + "Log" "0" + "Type" "1" + "Signature" "TankAttack::TryToThrowRock" + "Offset" "TankAttack::TryToThrowRock::GetDifficulty2" + "Linux" + { + "Verify" "\x0F\x85" + "Patch" "\x0F\x8D" + } + "Mac" + { + "Verify" "\x75" + "Patch" "\xEB" + } + "Windows" + { + "Verify" "\x75" + "Patch" "\xEB" + } + } "MTPatch_TankFinaleBehavior" { "Log" "0" @@ -994,6 +1038,50 @@ "Patch" "\xE9\x1A\x01\x00\x00" } } + "MTPatch_TankAttackDifficulty" + { + "Log" "0" + "Type" "1" + "Signature" "TankAttack::TryToThrowRock" + "Offset" "TankAttack::TryToThrowRock::GetDifficulty" + "Linux" + { + "Verify" "\x0F\x85" + "Patch" "\x0F\x8D" + } + "Mac" + { + "Verify" "\x74" + "Patch" "\xEB" + } + "Windows" + { + "Verify" "\x74" + "Patch" "\xEB" + } + } + "MTPatch_TankAttackDifficulty2" + { + "Log" "0" + "Type" "1" + "Signature" "TankAttack::TryToThrowRock" + "Offset" "TankAttack::TryToThrowRock::GetDifficulty2" + "Linux" + { + "Verify" "\x0F\x85" + "Patch" "\x0F\x8D" + } + "Mac" + { + "Verify" "\x75" + "Patch" "\xEB" + } + "Windows" + { + "Verify" "\x75" + "Patch" "\xEB" + } + } "MTPatch_TankFinaleBehavior" { "Log" "0" diff --git a/addons/sourcemod/gamedata/mutant_tanks.txt b/addons/sourcemod/gamedata/mutant_tanks.txt index 686e0f0996..e6925c20ee 100644 --- a/addons/sourcemod/gamedata/mutant_tanks.txt +++ b/addons/sourcemod/gamedata/mutant_tanks.txt @@ -350,6 +350,26 @@ "this" "entity" } + /** + * CTerrorPlayer::GrabVictimWithTongue(CTerrorPlayer*) + * + * Note: Detouring as a pre-hook for blocking Smoker attacks. + **/ + "MTDetour_CTerrorPlayer::GrabVictimWithTongue" + { + "signature" "CTerrorPlayer::GrabVictimWithTongue" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "victim" + { + "type" "cbaseentity" + } + } + } + /** * CTerrorPlayer::OnBeginChangeLevel(char const*) * @@ -488,6 +508,26 @@ "this" "entity" } + /** + * CTerrorPlayer::OnPouncedOnSurvivor(CTerrorPlayer*) + * + * Note: Detouring as a pre-hook for blocking Hunter attacks. + **/ + "MTDetour_CTerrorPlayer::OnPouncedOnSurvivor" + { + "signature" "CTerrorPlayer::OnPouncedOnSurvivor" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "victim" + { + "type" "cbaseentity" + } + } + } + /** * CTerrorPlayer::OnRevived() * @@ -734,6 +774,27 @@ "this" "entity" } + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Detouring as a pre-hook for patching attack choice per Tank. + * Note: Detouring as a post-hook for removing patch for attack choice. + **/ + "MTDetour_TankAttack::TryToThrowRock" + { + "signature" "TankAttack::TryToThrowRock" + "callconv" "thiscall" + "return" "void" + "this" "address" + "arguments" + { + "tank" + { + "type" "cbaseentity" + } + } + } + /** * TankBehavior::InitialContainedAction(Tank *) * @@ -1868,6 +1929,46 @@ "windows" "11924" } + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Patches the first condition for choosing between punching and throw a rock. + * + * How to find on Linux: + * 1. Look for the six-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the if statement that determines whether the Tank should be punch or throw a rock. + * + * How to find on Mac/Windows: + * 1. Look for the two-byte jump (JZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the if statement that determines whether the Tank should be punch or throw a rock. + **/ + "TankAttack::TryToThrowRock::GetDifficulty" + { + "linux" "133" // start at "0F 85" and patch the "85" with "8D" to always force the jump to the next instruction. + "mac" "64" // start at 74 and patch 1 byte with a short jump (0xEB) to skip instruction + "windows" "48" // start at 75 and patch 1 byte with a short jump (0xEB) to skip instruction + } + + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Patches the second condition for choosing between punching and throw a rock. + * + * How to find on Linux: + * 1. Look for the six-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the second call to the "GetDifficulty" function. + * + * How to find on Mac/Windows: + * 1. Look for the two-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the second call to the "GetDifficulty" function. + **/ + "TankAttack::TryToThrowRock::GetDifficulty2" + { + "linux" "1515" // start at "0F 85" and patch the "85" with "8D" to always force the jump to the next instruction. + "mac" "74" // start at 74 and patch 1 byte with a short jump (0xEB) to skip instruction + "windows" "58" // start at 75 and patch 1 byte with a short jump (0xEB) to skip instruction + } + /** * TankBehavior::InitialContainedAction(Tank *) * @@ -2669,6 +2770,24 @@ /* ? ? ? ? ? ? 8B ? 8B ? 8B 90 ? ? ? ? 8B 9E */ } + /** + * CTerrorPlayer::GrabVictimWithTongue(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for the "Tongue grab starting." string. + * 2. The string can only be found in this function. + **/ + "CTerrorPlayer::GrabVictimWithTongue" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer20GrabVictimWithTongueEPS_" + "mac" "@_ZN13CTerrorPlayer20GrabVictimWithTongueEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x53\x55\x56\x8B" + /* ? ? ? ? ? ? ? ? 83 ? ? ? 53 55 56 8B */ + } + /** * CTerrorPlayer::MaterializeFromGhost() * @@ -2859,6 +2978,26 @@ /* ? ? ? ? ? ? 8B ? E8 ? ? ? ? 8B ? E8 ? ? ? ? 6A ? 8B ? E8 ? ? ? ? 8B ? E8 ? ? ? ? 83 */ } + /** + * CTerrorPlayer::OnPouncedOnSurvivor(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for any of the following strings (they can each only be found in this function): + * - "%s pounced on %s, %d damage interrupts\n" + * - "Tongue letting go on victim getting pounced." + * - "Pounce by %s dealt %0.1f damage from a 2d distance of %.0f\n" + **/ + "CTerrorPlayer::OnPouncedOnSurvivor" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer19OnPouncedOnSurvivorEPS_" + "mac" "@_ZN13CTerrorPlayer19OnPouncedOnSurvivorEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x81\xEC\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x53\x56" + /* ? ? ? ? ? ? A1 ? ? ? ? 81 EC ? ? ? ? 83 ? ? ? 53 56 */ + } + /** * CTerrorPlayer::OnRevived() * @@ -3294,6 +3433,24 @@ /* ? ? ? ? ? ? ? ? ? ? 0F 84 ? ? ? ? 83 ? ? ? 74 ? 0F */ } + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Used for detouring/finding the function. + * + * How to find on Windows: + * 1. Search for the "Throwing rock" string. + * 2. The string can only be found in this function. + **/ + "TankAttack::TryToThrowRock" + { + "library" "server" + "linux" "@_ZN10TankAttack14TryToThrowRockEP4Tank" + "mac" "@_ZN10TankAttack14TryToThrowRockEP4Tank" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x57\x8B\x2A\x89\x2A\x2A\x2A\x0F" + /* ? ? ? ? ? ? ? ? 83 ? ? ? 57 8B ? 89 ? ? ? 0F */ + } + /** * TankBehavior::InitialContainedAction(Tank *) * @@ -3611,6 +3768,70 @@ } } + /** + * CTerrorPlayer::OnLeptOnSurvivor(CTerrorPlayer*) + * + * Note: Detouring as a pre-hook for blocking Jockey attacks. + **/ + "MTDetour_CTerrorPlayer::OnLeptOnSurvivor" + { + "signature" "CTerrorPlayer::OnLeptOnSurvivor" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "victim" + { + "type" "cbaseentity" + } + } + } + + /** + * CTerrorPlayer::OnStartCarryingVictim(CTerrorPlayer*) + * + * Note: Detouring as a pre-hook for blocking Charger attacks. + **/ + "MTDetour_CTerrorPlayer::OnStartCarryingVictim" + { + "signature" "CTerrorPlayer::OnStartCarryingVictim" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "victim" + { + "type" "cbaseentity" + } + } + } + + /** + * CTerrorPlayer::QueuePummelVictim(CTerrorPlayer*, float) + * + * Note: Detouring as a pre-hook for blocking Charger attacks. + **/ + "MTDetour_CTerrorPlayer::QueuePummelVictim" + { + "signature" "CTerrorPlayer::QueuePummelVictim" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "attacker" + { + "type" "cbaseentity" + } + "a2" + { + "type" "float" + } + } + } + /** * CTerrorPlayer::SelectWeightedSequence(Activity) * @@ -4498,6 +4719,46 @@ "windows" "17204" } + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Patches the first condition for choosing between punching and throw a rock. + * + * How to find on Linux: + * 1. Look for the six-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the if statement that determines whether the Tank should be punch or throw a rock. + * + * How to find on Mac/Windows: + * 1. Look for the two-byte jump (JZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the if statement that determines whether the Tank should be punch or throw a rock. + **/ + "TankAttack::TryToThrowRock::GetDifficulty" + { + "linux" "952" // start at "0F 85" and patch the "85" with "8D" to always force the jump to the next instruction. + "mac" "67" // start at 74 and patch 1 byte with a short jump (0xEB) to skip instruction + "windows" "50" // start at 74 and patch 1 byte with a short jump (0xEB) to skip instruction + } + + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Patches the second condition for choosing between punching and throw a rock. + * + * How to find on Linux: + * 1. Look for the six-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the second call to the "GetDifficulty" function. + * + * How to find on Mac/Windows: + * 1. Look for the two-byte jump (JNZ) instruction under the first call to the "GetDifficulty" function. + * 2. The instruction refers to the second call to the "GetDifficulty" function. + **/ + "TankAttack::TryToThrowRock::GetDifficulty2" + { + "linux" "2105" // start at "0F 85" and patch the "85" with "8D" to always force the jump to the next instruction. + "mac" "77" // start at 75 and patch 1 byte with a short jump (0xEB) to skip instruction + "windows" "60" // start at 75 and patch 1 byte with a short jump (0xEB) to skip instruction + } + /** * TankBehavior::InitialContainedAction(Tank *) * @@ -5551,6 +5812,24 @@ /* ? ? ? ? ? ? 53 56 57 8B ? 8B ? 8B 90 ? ? ? ? 8B */ } + /** + * CTerrorPlayer::GrabVictimWithTongue(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for the "Tongue grab starting." string. + * 2. The string can only be found in this function. + **/ + "CTerrorPlayer::GrabVictimWithTongue" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer20GrabVictimWithTongueEPS_" + "mac" "@_ZN13CTerrorPlayer20GrabVictimWithTongueEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x83\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x56\x8B\x2A\x57\x89\x2A\x2A\x0F\x85" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 83 ? ? A1 ? ? ? ? 83 ? ? ? 56 8B ? 57 89 ? ? 0F 85 */ + } + /** * CTerrorPlayer::MaterializeFromGhost() * @@ -5763,6 +6042,42 @@ /* ? ? ? ? ? ? A1 ? ? ? ? 53 56 57 33 ? 89 ? ? 89 ? ? 8B ? 39 ? ? 74 ? 8B ? ? 68 ? ? ? ? 8B ? ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 57 57 57 57 8D ? ? 51 50 FF ? A1 ? ? ? ? 83 ? ? 8B ? ? 8B ? ? 8B ? ? 6A ? 57 68 ? ? ? ? 57 89 ? ? 8B 0D ? ? ? ? 68 ? ? ? ? 89 ? ? 89 ? ? FF 15 ? ? ? ? 8B ? ? 8B */ } + /** + * CTerrorPlayer::OnLeptOnSurvivor(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for the "SurvivorJockeyed" or "SurvivorJockeyedOther" string. + * 2. The string can only be found in this function. + **/ + "CTerrorPlayer::OnLeptOnSurvivor" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer16OnLeptOnSurvivorEPS_" + "mac" "@_ZN13CTerrorPlayer16OnLeptOnSurvivorEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x2A\x57\x8B\x2A\x0F\x85\x2A\x2A\x2A\x2A\x56" + /* ? ? ? ? ? ? ? ? 83 ? ? 83 ? ? ? 57 8B ? 0F 85 ? ? ? ? 56 */ + } + + /** + * CTerrorPlayer::OnPouncedOnSurvivor(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for the "%s pounced on %s, %d damage interrupts\n" or "Pounce by %s dealt %0.1f damage from a 2d distance of %.0f\n" string. + * 2. The string can only be found in this function. + **/ + "CTerrorPlayer::OnPouncedOnSurvivor" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer19OnPouncedOnSurvivorEPS_" + "mac" "@_ZN13CTerrorPlayer19OnPouncedOnSurvivorEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x56\x57\x8B" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 81 EC ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? A1 ? ? ? ? 83 ? ? ? 56 57 8B */ + } + /** * CTerrorPlayer::OnRevived() * @@ -5843,6 +6158,24 @@ /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 83 ? ? 56 57 8B ? E8 ? ? ? ? 84 ? 0F 85 ? ? ? ? 8B ? 8B */ } + /** + * CTerrorPlayer::OnStartCarryingVictim(CTerrorPlayer*) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Search for the "charger_carry_start" string. + * 2. The string can only be found in this function. + **/ + "CTerrorPlayer::OnStartCarryingVictim" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer21OnStartCarryingVictimEPS_" + "mac" "@_ZN13CTerrorPlayer21OnStartCarryingVictimEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x2A\x2A\x6A\x2A\x6A\x2A\x68\x2A\x2A\x2A\x2A\xFF\x2A\x8B\x2A\x85\x2A\x74\x2A\x8B\x2A\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x2A\x50\x8B\x2A\x2A\xFF\x2A\x8B\x2A\x50\x8B\x2A\x2A\x68\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x8B\x2A\x2A\x8B" + /* ? ? ? ? ? ? 8B ? 8B 0D ? ? ? ? 8B ? 8B ? ? 6A ? 6A ? 68 ? ? ? ? FF ? 8B ? 85 ? 74 ? 8B ? ? 8B 0D ? ? ? ? 8B ? 50 8B ? ? FF ? 8B ? 50 8B ? ? 68 ? ? ? ? 8B ? FF ? 8B ? ? 8B */ + } + /** * CTerrorPlayer::OnTakeDamage_Alive(CTakeDamageInfo const&) * @@ -5906,6 +6239,30 @@ /* ? ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 56 57 8B ? E8 ? ? ? ? 8B ? E8 */ } + /** + * CTerrorPlayer::QueuePummelVictim(CTerrorPlayer*, float) + * + * Note: Used for detouring the function. + * + * How to find on Windows: + * 1. Find the "CCharge::HandleCustomCollision" function's offsets with asherkin's VTable dump. + * 2. In IDA Pro, go to the ".rdata" section of the Windows binary. + * 3. Search for "CCharge::`vftable'" to jump to the "CCharge" vtable. + * 4. Compare your dump's offsets with asherkin's dump's offsets to find the target function. + * 5. Look for the target function in the Windows binary. + * 6. Look for a function call that passes four parameters, with the last parameters being "1" and "0". + * 7. That function should be the "CTerrorPlayer::OnSlammedSurvivor" function. + * 8. The last function call in the "CTerrorPlayer::OnSlammedSurvivor" function should be this function. + **/ + "CTerrorPlayer::QueuePummelVictim" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer17QueuePummelVictimEPS_f" + "mac" "@_ZN13CTerrorPlayer17QueuePummelVictimEPS_f" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x56\x57\x8B\x2A\x85\x2A\x74\x2A\x8B\x2A\x8B\x2A\x2A\x8B\x2A\xFF\x2A\x8B\x2A\x83" + /* ? ? ? ? ? ? ? 56 57 8B ? 85 ? 74 ? 8B ? 8B ? ? 8B ? FF ? 8B ? 83 */ + } + /** * CTerrorPlayer::RoundRespawn() * @@ -6145,6 +6502,24 @@ /* ? ? ? ? ? ? ? ? ? ? ? 8D B7 ? ? ? ? 74 ? 8B 86 ? ? ? ? 8B 90 ? ? ? ? 8D 8E ? ? ? ? 56 FF ? C6 ? ? 8B ? 8B 90 ? ? ? ? 8B */ } + /** + * TankAttack::TryToThrowRock(Tank *) + * + * Note: Used for detouring/finding the function. + * + * How to find on Windows: + * 1. Search for the "Throwing rock" string. + * 2. The string can only be found in this function. + **/ + "TankAttack::TryToThrowRock" + { + "library" "server" + "linux" "@_ZN10TankAttack14TryToThrowRockEP4Tank" + "mac" "@_ZN10TankAttack14TryToThrowRockEP4Tank" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x57\x8B\x2A\x89\x2A\x2A\x0F\x84" + /* ? ? ? ? ? ? A1 ? ? ? ? 83 ? ? ? 57 8B ? 89 ? ? 0F 84 */ + } + /** * TankBehavior::InitialContainedAction(Tank *) * diff --git a/addons/sourcemod/mutant_tanks_updater.txt b/addons/sourcemod/mutant_tanks_updater.txt index 765237a38a..4090c5a268 100644 --- a/addons/sourcemod/mutant_tanks_updater.txt +++ b/addons/sourcemod/mutant_tanks_updater.txt @@ -4,50 +4,42 @@ { "Version" { - "Latest" "8.97" - "Previous" "8.96" + "Latest" "8.98" + "Previous" "8.97" } "Notes" "AlliedModders forum thread: https://forums.alliedmods.net/showthread.php?t=302140" "Notes" "GitHub repository: https://github.com/Psykotikism/Mutant_Tanks" - "Notes" "Release date: 5-21-2023" - "Notes" "Changes in v8.97:" + "Notes" "Release date: 8-10-2023" + "Notes" "Changes in v8.98:" "Notes" "Bug Fixes:" - "Notes" "General:" - "Notes" "- Fixed an issue where some RNG-based events happen too often. (Thanks to \"ddd123\" for reporting!)" - "Notes" "- Fixed an issue where Witches take a long time to die from fires. (Thanks to \"ddd123\" for reporting!)" - "Notes" "- Fixed rare array index errors." "Notes" "Core Plugin:" - "Notes" "- Fixed Tank death messages not appearing when a survivor solos a Tank." + "Notes" "- Fixed the \"Health\" and \"Refill\" rewards not rewarding recipients with health properly. (Thanks to \"xcd222\" for reporting!) [Fixed in \"v8.97\".]" "Notes" "Config Files:" - "Notes" "- Fixed Mutant Tank type settings not being read properly under combined sections." + "Notes" "- Fixed custom config Mutant Tank types overlapping with main config Mutant Tank types. (Thanks to \"xcd222\" for reporting!)" + "Notes" "Settings:" + "Notes" "- Fixed the \"Reward Visual\" setting's limit. (Thanks to \"swofleswof\" for testing and reporting!)" "Notes" "Abilities:" - "Notes" "- Gunner" - "Notes" " - Fixed one of the messages not showing up when the ability activates. (Thanks to \"thewintersoldier97\" for reporting!)" - "Notes" " - Fixed the ability targeting the Tank itself." - "Notes" "- Quiet: Fixed the sound hook blocking other sound hooks." - "Notes" "- Rocket: Fixed an issue where survivor ragdolls will not disappear if the player goes afk and is replaced by a survivor bot. (Thanks to \"Slaven555\" for testing and reporting!)" + "Notes" "- Gunner: Fixed an error that caused the server to crash. (Thanks to \"Mi.Cura\" for testing and reporting!)" + "Notes" "- Item, Kamikaze, Rocket, Smash, Smite: Fixed survivor ragdolls being erased by all Mutant Tank types. (Thanks to \"George Rex\" for reporting!) [Fixed in \"v8.97\".]" + "Notes" "- Throw: Fixed Mutant Tank types not being able to throw cars and special infected. (Thanks to \"xcd222\" for reporting!) [Fixed in \"v8.97\".]" "Notes" "Changes:" - "Notes" "General:" - "Notes" "- Mutant Tanks and its sub-plugins now properly support the \"[L4D & L4D2] Lagged Movement - Plugin Conflict Resolver\" (https://forums.alliedmods.net/showthread.php?t=340345) plugin." - "Notes" "Commands:" - "Notes" "- Added a 4th parameter for the \"sm_tank\" command. (Usage: \"sm_tank <1-500> <0: spawn on crosshair|1: spawn automatically> <0: not blind|1: blind>\")" + "Notes" "Core Plugin:" + "Notes" "- The godmode reward now prevents recipients from being pinned by any special infected." + "Notes" "ConVars:" + "Notes" "- Added the \"mt_configfile\" convar. (Requested by \"zonbarbar\".)" + "Notes" "- Added a lock mechanism to enforce temporary values across maps for the core plugin's convars. (Thanks to \"NgBUCKWANGS\" for the code!)" + "Notes" " - Use \"-l-\" in front of the new value to enforce that value for the convar. (Example: \"mt_configfile \"-l-myconfig.cfg\"\")" + "Notes" " - Use \"-u-\" in front of the new value to allow the convar to accept new values. (Example: \"mt_configfile \"-u-myconfig.cfg\"\")" "Notes" "Game Data:" - "Notes" "- L4D2: Updated some signatures and offsets for the \"2.2.2.7\" update." - "Notes" "Abilities:" - "Notes" "- Gravity" - "Notes" " - Added the \"Gravity Radius\" setting." - "Notes" " - Added the \"Gravity Rock Break\" setting. (Thanks to \"JustMadMan\" for the idea!)" - "Notes" " - Added the \"Gravity Rock Chance\" setting. (Thanks to \"JustMadMan\" for the idea!)" + "Notes" "- Added signatures for the following functions:" + "Notes" " - \"CTerrorPlayer::GrabVictimWithTongue\"" + "Notes" " - \"CTerrorPlayer::OnLeptOnSurvivor\"" + "Notes" " - \"CTerrorPlayer::OnPouncedOnSurvivor\"" + "Notes" " - \"CTerrorPlayer::OnStartCarryingVictim\"" + "Notes" " - \"CTerrorPlayer::QueuePummelVictim\"" "Notes" "Settings:" - "Notes" "- Added the \"Footstep Shake\" setting under the \"Plugin Settings->Enhancements\", \"Tank #->Enhancements\", and \"STEAM_ID->Enhancements\" sections. (Thanks to \"Silvers\" for the code!)" - "Notes" "- Added the \"Refill Percent Reward\" setting under the \"Plugin Settings->Rewards\", \"Tank #->Rewards\", and \"STEAM_ID->Rewards\" sections. (Thanks to \"DARG367\" for suggesting!)" - "Notes" "- Updated the \"Stack Limits\" setting to accept an \"8th\" value." - "Notes" "Translations:" - "Notes" "- Updated English translations." - "Notes" "- Updated Simplified Chinese translations." - "Notes" "- Updated Hungarian translations." - "Notes" "- Updated Russian translations." + "Notes" "- Added the \"Prioritize Throws\" setting under the \"Plugin Settings->Competitive\" and \"Tank #->Competitive\" sections. (Requested by \"xcd222\".) [Thanks to \"Silvers\" for the help!]" "Notes" "Files:" "Notes" "General:" "Notes" "- The pre-compiled plugins included in the package are:" @@ -165,6 +157,7 @@ "Source" "Path_SM/scripting/mutant_tanks/abilities2/mt_witch.sp" "Source" "Path_SM/scripting/mutant_tanks/abilities2/mt_xiphos.sp" "Source" "Path_SM/scripting/mutant_tanks/abilities2/mt_yell.sp" + "Source" "Path_SM/scripting/mutant_tanks/abilities2/mt_zen.sp" "Source" "Path_SM/scripting/mutant_tanks/abilities2/mt_zombie.sp" // Includes diff --git a/addons/sourcemod/plugins/mutant_tanks/mt_abilities.smx b/addons/sourcemod/plugins/mutant_tanks/mt_abilities.smx index 588e73f8f2..9e01aeeb94 100644 Binary files a/addons/sourcemod/plugins/mutant_tanks/mt_abilities.smx and b/addons/sourcemod/plugins/mutant_tanks/mt_abilities.smx differ diff --git a/addons/sourcemod/plugins/mutant_tanks/mt_abilities2.smx b/addons/sourcemod/plugins/mutant_tanks/mt_abilities2.smx index ad89cd4b13..4ff2386729 100644 Binary files a/addons/sourcemod/plugins/mutant_tanks/mt_abilities2.smx and b/addons/sourcemod/plugins/mutant_tanks/mt_abilities2.smx differ diff --git a/addons/sourcemod/plugins/mutant_tanks/mutant_tanks.smx b/addons/sourcemod/plugins/mutant_tanks/mutant_tanks.smx index f7481eeb5b..afc23448d3 100644 Binary files a/addons/sourcemod/plugins/mutant_tanks/mutant_tanks.smx and b/addons/sourcemod/plugins/mutant_tanks/mutant_tanks.smx differ diff --git a/addons/sourcemod/scripting/include/mutant_tanks.inc b/addons/sourcemod/scripting/include/mutant_tanks.inc index 65ed9b6fd6..4e6d3f2914 100644 --- a/addons/sourcemod/scripting/include/mutant_tanks.inc +++ b/addons/sourcemod/scripting/include/mutant_tanks.inc @@ -22,7 +22,7 @@ #define MT_AUTHOR "Psyk0tik" #define MT_AUTHOR2 "Crasher_3637" #define MT_DESCRIPTION "Mutant Tanks enhances the fun and excitement players get from Tank fights by creating a unique experience with every Tank." -#define MT_VERSION "8.97" +#define MT_VERSION "8.98" #define MT_URL "https://forums.alliedmods.net/showthread.php?t=302140" #define MT_URL2 "https://github.com/Psykotikism/Mutant_Tanks" @@ -1417,7 +1417,6 @@ stock void vFixPlayerPosition(int client) while (flPosZ <= 200.0 && !bIsPlayerPositionFixed(client, 10.0, flPosZ)) { flPosZ = -flPosZ; - if (flPosZ > 0.0) { flPosZ += 20.0; @@ -2630,7 +2629,7 @@ stock bool bIsWitch(int witch) return false; } -// Filters +// Command target filters bool bBoomerFilter(const char[] pattern, ArrayList clients) { for (int iPlayer = 1; iPlayer <= MaxClients; iPlayer++) @@ -3503,18 +3502,21 @@ stock int iGetNearestCommonInfected(int tank, float pos[3], float range) { float flCommonPos[3]; int iCommonCount = 0, iCommon = -1; - int[] iCommons = new int[MaxClients + 1]; + int[] iCommons = new int[2048]; while ((iCommon = FindEntityByClassname(iCommon, "infected")) != INVALID_ENT_REFERENCE) { - GetEntPropVector(iCommon, Prop_Send, "m_vecOrigin", flCommonPos); - if (bIsVisibleToPosition(pos, flCommonPos, range)) - { - iCommons[iCommonCount] = iCommon; - iCommonCount++; - } + if (bIsValidEntity(iCommon)) + { + GetEntPropVector(iCommon, Prop_Send, "m_vecOrigin", flCommonPos); + if (bIsVisibleToPosition(pos, flCommonPos, range)) + { + iCommons[iCommonCount] = iCommon; + iCommonCount++; + } + } } - return (iCommonCount > 0) ? iCommons[MT_GetRandomInt(0, (iCommonCount - 1))] : 0; + return (iCommonCount > 0) ? iCommons[GetRandomInt(0, (iCommonCount - 1))] : 0; } stock int iGetNearestSpecialInfected(int tank, float pos[3], float range) @@ -3535,7 +3537,7 @@ stock int iGetNearestSpecialInfected(int tank, float pos[3], float range) } } - return (iInfectedCount > 0) ? iSpecials[MT_GetRandomInt(0, (iInfectedCount - 1))] : 0; + return (iInfectedCount > 0) ? iSpecials[GetRandomInt(0, (iInfectedCount - 1))] : 0; } stock int iGetNearestSurvivor(int tank, float pos[3], float range, bool noHumans = false, bool noBots = false, bool noIncaps = false) @@ -3563,7 +3565,7 @@ stock int iGetNearestSurvivor(int tank, float pos[3], float range, bool noHumans } } - return (iSurvivorCount > 0) ? iSurvivors[MT_GetRandomInt(0, (iSurvivorCount - 1))] : 0; + return (iSurvivorCount > 0) ? iSurvivors[GetRandomInt(0, (iSurvivorCount - 1))] : 0; } stock int iGetPlayerCount() diff --git a/addons/sourcemod/scripting/mutant_tanks/mt_abilities.sp b/addons/sourcemod/scripting/mutant_tanks/mt_abilities.sp index bc005c3310..99b01a8555 100644 --- a/addons/sourcemod/scripting/mutant_tanks/mt_abilities.sp +++ b/addons/sourcemod/scripting/mutant_tanks/mt_abilities.sp @@ -10,7 +10,7 @@ **/ #define MT_ABILITIES_MAIN -#define MT_ABILITIES_GROUP 3 // 0: NONE, 1: Only include first half (1-20), 2: Only include second half (21-38), 3: ALL +#define MT_ABILITIES_GROUP 3 // 0: NONE, 1: Only include first half (1-20), 2: Only include second half (21-39), 3: ALL #define MT_ABILITIES_COMPILER_MESSAGE 1 // 0: NONE, 1: Display warning messages about excluded abilities, 2: Display error messages about excluded abilities #include diff --git a/addons/sourcemod/scripting/mutant_tanks/mutant_tanks.sp b/addons/sourcemod/scripting/mutant_tanks/mutant_tanks.sp index 4b1da7dd56..5519e99eea 100644 --- a/addons/sourcemod/scripting/mutant_tanks/mutant_tanks.sp +++ b/addons/sourcemod/scripting/mutant_tanks/mutant_tanks.sp @@ -420,6 +420,7 @@ enum struct esGeneral char g_sBodyColorVisual3[64]; char g_sBodyColorVisual4[64]; char g_sChosenPath[PLATFORM_MAX_PATH]; + char g_sConfigPath[PLATFORM_MAX_PATH]; char g_sCurrentMissionDisplayTitle[64]; char g_sCurrentMissionName[64]; char g_sCurrentSection[128]; @@ -469,6 +470,7 @@ enum struct esGeneral ConVar g_cvMTAutoShotgunAmmo; ConVar g_cvMTAutoUpdate; ConVar g_cvMTColaBottlesUseDuration; + ConVar g_cvMTConfigFile; ConVar g_cvMTDefibrillatorUseDuration; ConVar g_cvMTDifficulty; ConVar g_cvMTDisabledGameModes; @@ -526,6 +528,7 @@ enum struct esGeneral DynamicDetour g_ddFireBulletDetour; DynamicDetour g_ddFlingDetour; DynamicDetour g_ddGetMaxClip1Detour; + DynamicDetour g_ddGrabVictimWithTongueDetour; DynamicDetour g_ddHitByVomitJarDetour; DynamicDetour g_ddIncapacitatedAsTankDetour; DynamicDetour g_ddInitialContainedActionDetour; @@ -534,9 +537,12 @@ enum struct esGeneral DynamicDetour g_ddLadderMountDetour; DynamicDetour g_ddLauncherDirectionDetour; DynamicDetour g_ddLeaveStasisDetour; + DynamicDetour g_ddLeptOnSurvivorDetour; DynamicDetour g_ddMaxCarryDetour; DynamicDetour g_ddPipeBombProjectileCreateDetour; + DynamicDetour g_ddPouncedOnSurvivorDetour; DynamicDetour g_ddPreThinkDetour; + DynamicDetour g_ddQueuePummelVictimDetour; DynamicDetour g_ddReplaceTankDetour; DynamicDetour g_ddRevivedDetour; DynamicDetour g_ddSecondaryAttackDetour; @@ -548,6 +554,7 @@ enum struct esGeneral DynamicDetour g_ddSpawnTankDetour; DynamicDetour g_ddStaggeredDetour; DynamicDetour g_ddStartActionDetour; + DynamicDetour g_ddStartCarryingVictimDetour; DynamicDetour g_ddStartHealingDetour; DynamicDetour g_ddStartRevivingDetour; DynamicDetour g_ddTankClawDoSwingDetour; @@ -559,6 +566,7 @@ enum struct esGeneral DynamicDetour g_ddTankRockReleaseDetour; DynamicDetour g_ddTestMeleeSwingCollisionDetour; DynamicDetour g_ddThrowActivateAbilityDetour; + DynamicDetour g_ddTryToThrowRockDetour; DynamicDetour g_ddUseDetour; DynamicDetour g_ddUseDetour2; DynamicDetour g_ddVomitedUponDetour; @@ -770,6 +778,7 @@ enum struct esGeneral int g_iPlayerCount[3]; int g_iPluginEnabled; int g_iPrefsNotify[4]; + int g_iPrioritizeThrows; int g_iRecoilDampenerReward[4]; int g_iRegularAmount; int g_iRegularCount; @@ -819,6 +828,8 @@ enum struct esGeneral int g_iVocalizeDeath; int g_iVoicePitchVisual[4]; int g_iVomitImmunity; + + StringMap g_smCvars; #if defined _adminmenu_included TopMenu g_tmMTMenu; #endif @@ -1381,6 +1392,7 @@ enum struct esTank int g_iOzTankColor[4]; int g_iParticleEffectVisual[4]; int g_iPrefsNotify[4]; + int g_iPrioritizeThrows; int g_iPropsAttached; int g_iPropTankColor[4]; int g_iRealType[2]; @@ -1580,6 +1592,7 @@ enum struct esCache int g_iOzTankColor[4]; int g_iParticleEffectVisual[4]; int g_iPrefsNotify[4]; + int g_iPrioritizeThrows; int g_iPropsAttached; int g_iPropTankColor[4]; int g_iRandomTank; @@ -1734,6 +1747,8 @@ public void OnAllPluginsLoaded() public void OnPluginStart() { + g_esGeneral.g_smCvars = new StringMap(); + char sDate[32]; FormatTime(sDate, sizeof sDate, "%Y-%m-%d", GetTime()); BuildPath(Path_SM, g_esGeneral.g_sLogFile, sizeof esGeneral::g_sLogFile, "logs/mutant_tanks_%s.log", sDate); @@ -1763,11 +1778,12 @@ public void OnPluginStart() g_esGeneral.g_ckMTPrefs = new Cookie("MTPrefs", "Mutant Tanks Preferences", CookieAccess_Private); #endif char sSMPath[PLATFORM_MAX_PATH]; + g_esGeneral.g_cvMTConfigFile.GetString(g_esGeneral.g_sConfigPath, sizeof esGeneral::g_sConfigPath); BuildPath(Path_SM, sSMPath, sizeof sSMPath, MT_CONFIG_FILEPATH); CreateDirectory(sSMPath, 511); - FormatEx(g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath, "%s%s", sSMPath, MT_CONFIG_FILE_MAIN); + FormatEx(g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath, "%s%s%s", sSMPath, g_esGeneral.g_sConfigPath, ((StrContains(g_esGeneral.g_sConfigPath, ".cfg") != -1) ? "" : ".cfg")); - switch (MT_FileExists(MT_CONFIG_FILEPATH, MT_CONFIG_FILE_MAIN, g_esGeneral.g_sSavePath, g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath)) + switch (MT_FileExists(MT_CONFIG_FILEPATH, g_esGeneral.g_sConfigPath, g_esGeneral.g_sSavePath, g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath)) { case true: g_esGeneral.g_iFileTimeOld[0] = GetFileTime(g_esGeneral.g_sSavePath, FileTime_LastChange); case false: SetFailState("Unable to load the \"%s\" config file.", g_esGeneral.g_sSavePath); @@ -3429,7 +3445,7 @@ Action cmdMTConfig(int client, int args) switch (args) { - case 1: BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, MT_CONFIG_FILE_MAIN); + case 1: BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, g_esGeneral.g_sConfigPath); case 2: { char sFilename[PLATFORM_MAX_PATH]; @@ -3437,13 +3453,13 @@ Action cmdMTConfig(int client, int args) switch (StrContains(sFilename, MT_CONFIG_FILE_DETOURS, false) != -1 || StrContains(sFilename, MT_CONFIG_FILE_PATCHES, false) != -1 || StrContains(sFilename, MT_CONFIG_FILE_SIGNATURES, false) != -1) { - case true: BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, MT_CONFIG_FILE_MAIN); + case true: BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, g_esGeneral.g_sConfigPath); case false: { BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s.cfg", MT_CONFIG_FILEPATH, sFilename); if (!FileExists(g_esGeneral.g_sChosenPath, true)) { - BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, MT_CONFIG_FILE_MAIN); + BuildPath(Path_SM, g_esGeneral.g_sChosenPath, sizeof esGeneral::g_sChosenPath, "%s%s", MT_CONFIG_FILEPATH, g_esGeneral.g_sConfigPath); } } } @@ -3805,22 +3821,24 @@ void vRegisterConVars() #if defined _autoexecconfig_included AutoExecConfig_SetFile("mutant_tanks"); AutoExecConfig_SetCreateFile(true); - g_esGeneral.g_cvMTAutoUpdate = AutoExecConfig_CreateConVar("mt_autoupdate", "0", "Automatically update Mutant Tanks.\nRequires \"Updater\": https://github.com/Teamkiller324/Updater\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); - g_esGeneral.g_cvMTDisabledGameModes = AutoExecConfig_CreateConVar("mt_disabledgamemodes", "", "Disable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: None\nNot empty: Disabled only in these game modes.", FCVAR_NOTIFY); - g_esGeneral.g_cvMTEnabledGameModes = AutoExecConfig_CreateConVar("mt_enabledgamemodes", "", "Enable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: All\nNot empty: Enabled only in these game modes.", FCVAR_NOTIFY); - g_esGeneral.g_cvMTGameModeTypes = AutoExecConfig_CreateConVar("mt_gamemodetypes", "0", "Enable Mutant Tanks in these game mode types.\n0 OR 15: All game mode types.\n1: Co-Op modes only.\n2: Versus modes only.\n4: Survival modes only.\n8: Scavenge modes only. (Only available in Left 4 Dead 2.)", FCVAR_NOTIFY, true, 0.0, true, 15.0); - g_esGeneral.g_cvMTListenSupport = AutoExecConfig_CreateConVar("mt_listensupport", (g_bDedicated ? "0" : "1"), "Enable Mutant Tanks on listen servers.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); - g_esGeneral.g_cvMTPluginEnabled = AutoExecConfig_CreateConVar("mt_pluginenabled", "1", "Enable Mutant Tanks.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTAutoUpdate, "mt_autoupdate", "0", "Automatically update Mutant Tanks.\nRequires \"Updater\": https://github.com/Teamkiller324/Updater\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTConfigFile, "mt_configfile", MT_CONFIG_FILE_MAIN, "The config filename used by Mutant Tanks to read settings from.\nEmpty: None\nNot empty: The custom config filename to use.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTDisabledGameModes, "mt_disabledgamemodes", "", "Disable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: None\nNot empty: Disabled only in these game modes.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTEnabledGameModes, "mt_enabledgamemodes", "", "Enable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: All\nNot empty: Enabled only in these game modes.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTGameModeTypes, "mt_gamemodetypes", "0", "Enable Mutant Tanks in these game mode types.\n0 OR 15: All game mode types.\n1: Co-Op modes only.\n2: Versus modes only.\n4: Survival modes only.\n8: Scavenge modes only. (Only available in Left 4 Dead 2.)", FCVAR_NOTIFY, true, 0.0, true, 15.0); + vSetupConVar(g_esGeneral.g_cvMTListenSupport, "mt_listensupport", (g_bDedicated ? "0" : "1"), "Enable Mutant Tanks on listen servers.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTPluginEnabled, "mt_pluginenabled", "1", "Enable Mutant Tanks.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); AutoExecConfig_CreateConVar("mt_pluginversion", MT_VERSION, "Mutant Tanks Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY); AutoExecConfig_ExecuteFile(); AutoExecConfig_CleanFile(); #else - g_esGeneral.g_cvMTAutoUpdate = CreateConVar("mt_autoupdate", "0", "Automatically update Mutant Tanks.\nRequires Updater: https://forums.alliedmods.net/showthread.php?t=169095\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); - g_esGeneral.g_cvMTDisabledGameModes = CreateConVar("mt_disabledgamemodes", "", "Disable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: None\nNot empty: Disabled only in these game modes.", FCVAR_NOTIFY); - g_esGeneral.g_cvMTEnabledGameModes = CreateConVar("mt_enabledgamemodes", "", "Enable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: All\nNot empty: Enabled only in these game modes.", FCVAR_NOTIFY); - g_esGeneral.g_cvMTGameModeTypes = CreateConVar("mt_gamemodetypes", "0", "Enable Mutant Tanks in these game mode types.\n0 OR 15: All game mode types.\n1: Co-Op modes only.\n2: Versus modes only.\n4: Survival modes only.\n8: Scavenge modes only. (Only available in Left 4 Dead 2.)", FCVAR_NOTIFY, true, 0.0, true, 15.0); - g_esGeneral.g_cvMTListenSupport = CreateConVar("mt_listensupport", (g_bDedicated ? "0" : "1"), "Enable Mutant Tanks on listen servers.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); - g_esGeneral.g_cvMTPluginEnabled = CreateConVar("mt_pluginenabled", "1", "Enable Mutant Tanks.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTAutoUpdate, "mt_autoupdate", "0", "Automatically update Mutant Tanks.\nRequires Updater: https://forums.alliedmods.net/showthread.php?t=169095\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTConfigFile, "mt_configfile", MT_CONFIG_FILE_MAIN, "The config filename used by Mutant Tanks to read settings from.\nEmpty: None\nNot empty: The custom config filename to use.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTDisabledGameModes, "mt_disabledgamemodes", "", "Disable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: None\nNot empty: Disabled only in these game modes.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTEnabledGameModes, "mt_enabledgamemodes", "", "Enable Mutant Tanks in these game modes.\nSeparate by commas.\nEmpty: All\nNot empty: Enabled only in these game modes.", FCVAR_NOTIFY); + vSetupConVar(g_esGeneral.g_cvMTGameModeTypes, "mt_gamemodetypes", "0", "Enable Mutant Tanks in these game mode types.\n0 OR 15: All game mode types.\n1: Co-Op modes only.\n2: Versus modes only.\n4: Survival modes only.\n8: Scavenge modes only. (Only available in Left 4 Dead 2.)", FCVAR_NOTIFY, true, 0.0, true, 15.0); + vSetupConVar(g_esGeneral.g_cvMTListenSupport, "mt_listensupport", (g_bDedicated ? "0" : "1"), "Enable Mutant Tanks on listen servers.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); + vSetupConVar(g_esGeneral.g_cvMTPluginEnabled, "mt_pluginenabled", "1", "Enable Mutant Tanks.\n0: OFF\n1: ON", FCVAR_NOTIFY, true, 0.0, true, 1.0); CreateConVar("mt_pluginversion", MT_VERSION, "Mutant Tanks Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_REPLICATED|FCVAR_SPONLY); AutoExecConfig(true, "mutant_tanks"); #endif @@ -3857,13 +3875,9 @@ void vRegisterConVars() g_esGeneral.g_cvMTUpgradePackUseDuration = FindConVar("upgrade_pack_use_duration"); } - g_esGeneral.g_cvMTDisabledGameModes.AddChangeHook(vPluginStatusCvar); - g_esGeneral.g_cvMTEnabledGameModes.AddChangeHook(vPluginStatusCvar); - g_esGeneral.g_cvMTGameMode.AddChangeHook(vPluginStatusCvar); - g_esGeneral.g_cvMTGameModeTypes.AddChangeHook(vPluginStatusCvar); - g_esGeneral.g_cvMTPluginEnabled.AddChangeHook(vPluginStatusCvar); - g_esGeneral.g_cvMTDifficulty.AddChangeHook(vGameDifficultyCvar); - g_esGeneral.g_cvMTGunVerticalPunch.AddChangeHook(vGunVerticalPunchCvar); + g_esGeneral.g_cvMTGameMode.AddChangeHook(vUpdateCvar); + g_esGeneral.g_cvMTDifficulty.AddChangeHook(vUpdateCvar); + g_esGeneral.g_cvMTGunVerticalPunch.AddChangeHook(vUpdateCvar); } void vSetDurationCvars(int item, bool reset, float duration = 1.0) @@ -4021,36 +4035,96 @@ void vSetReviveDurationCvar(int survivor) } } -void vGameDifficultyCvar(ConVar convar, const char[] oldValue, const char[] newValue) +void vSetupConVar(ConVar &convar, const char[] name, const char[] value, const char[] details, int flags = 0, bool hasMin = false, float min = 0.0, bool hasMax = false, float max = 0.0) { - if ((g_esGeneral.g_iConfigExecute & MT_CONFIG_DIFFICULTY) && g_esGeneral.g_iConfigEnable == 1) - { - char sDifficultyConfig[PLATFORM_MAX_PATH]; - if (bIsDifficultyConfigFound(sDifficultyConfig, sizeof sDifficultyConfig)) - { - vCustomConfig(sDifficultyConfig); - g_esGeneral.g_iFileTimeOld[1] = GetFileTime(sDifficultyConfig, FileTime_LastChange); - g_esGeneral.g_iFileTimeNew[1] = g_esGeneral.g_iFileTimeOld[1]; - } - } +#if defined _autoexecconfig_included + convar = AutoExecConfig_CreateConVar(name, value, details, flags, hasMin, min, hasMax, max); +#else + convar = CreateConVar(name, value, details, flags, hasMin, min, hasMax, max); +#endif + convar.AddChangeHook(vUpdateCvar); } -void vGunVerticalPunchCvar(ConVar convar, const char[] oldValue, const char[] newValue) +void vUpdateCvar(ConVar convar, const char[] oldValue, const char[] newValue) { - g_esGeneral.g_cvMTGunVerticalPunch.GetString(g_esGeneral.g_sDefaultGunVerticalPunch, sizeof esGeneral::g_sDefaultGunVerticalPunch); + char sName[64], sValue[64]; + convar.GetName(sName, sizeof sName); + FormatEx(sValue, sizeof sValue, "%s", newValue); + TrimString(sValue); - for (int iPlayer = 1; iPlayer <= MaxClients; iPlayer++) + if (StrContains(newValue, "-l-") == 0) + { + strcopy(sValue, sizeof sValue, sValue[3]); + TrimString(sValue); + g_esGeneral.g_smCvars.SetString(sName, sValue, true); + } + else if (StrContains(newValue, "-u-") == 0) { - if (bIsHumanSurvivor(iPlayer) && (bIsDeveloper(iPlayer, 4) || ((g_esPlayer[iPlayer].g_iRewardTypes & MT_REWARD_DAMAGEBOOST) && g_esPlayer[iPlayer].g_iRecoilDampener == 1))) + strcopy(sValue, sizeof sValue, sValue[3]); + TrimString(sValue); + g_esGeneral.g_smCvars.Remove(sName); + } + + g_esGeneral.g_smCvars.GetString(sName, sValue, sizeof sValue); + + if (!StrEqual(newValue, sValue)) + { + convar.SetString(sValue); + + return; + } + + if (StrEqual(sName, "mt_configfile")) + { + char sSMPath[PLATFORM_MAX_PATH]; + strcopy(g_esGeneral.g_sConfigPath, sizeof esGeneral::g_sConfigPath, newValue); + BuildPath(Path_SM, sSMPath, sizeof sSMPath, MT_CONFIG_FILEPATH); + FormatEx(g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath, "%s%s%s", sSMPath, g_esGeneral.g_sConfigPath, ((StrContains(g_esGeneral.g_sConfigPath, ".cfg") != -1) ? "" : ".cfg")); + + switch (MT_FileExists(MT_CONFIG_FILEPATH, g_esGeneral.g_sConfigPath, g_esGeneral.g_sSavePath, g_esGeneral.g_sSavePath, sizeof esGeneral::g_sSavePath)) { - vToggleWeaponVerticalPunch(iPlayer, true); + case true: + { + g_esGeneral.g_iFileTimeOld[0] = GetFileTime(g_esGeneral.g_sSavePath, FileTime_LastChange); + + vLogMessage(MT_LOG_SERVER, _, "%s %T", MT_TAG, "ReloadingConfig", LANG_SERVER, g_esGeneral.g_sSavePath); + vLoadConfigs(g_esGeneral.g_sSavePath, 1); + vPluginStatus(); + vResetTimers(); + vToggleLogging(); + } + case false: LogError("%s Unable to load the \"%s\" config file.", MT_TAG, g_esGeneral.g_sSavePath); } } -} + else if (StrEqual(sName, "mt_disabledgamemodes") || StrEqual(sName, "mt_enabledgamemodes") || StrEqual(sName, "mt_gamemodetypes") || StrEqual(sName, "mt_pluginenabled") || StrEqual(sName, "mp_gamemode")) + { + vPluginStatus(); + } + else if (StrEqual(sName, "z_difficulty")) + { + if ((g_esGeneral.g_iConfigExecute & MT_CONFIG_DIFFICULTY) && g_esGeneral.g_iConfigEnable == 1) + { + char sDifficultyConfig[PLATFORM_MAX_PATH]; + if (bIsDifficultyConfigFound(sDifficultyConfig, sizeof sDifficultyConfig)) + { + vCustomConfig(sDifficultyConfig); + g_esGeneral.g_iFileTimeOld[1] = GetFileTime(sDifficultyConfig, FileTime_LastChange); + g_esGeneral.g_iFileTimeNew[1] = g_esGeneral.g_iFileTimeOld[1]; + } + } + } + else if (StrEqual(sName, "z_gun_vertical_punch")) + { + g_esGeneral.g_cvMTGunVerticalPunch.GetString(g_esGeneral.g_sDefaultGunVerticalPunch, sizeof esGeneral::g_sDefaultGunVerticalPunch); -void vPluginStatusCvar(ConVar convar, const char[] oldValue, const char[] newValue) -{ - vPluginStatus(); + for (int iPlayer = 1; iPlayer <= MaxClients; iPlayer++) + { + if (bIsHumanSurvivor(iPlayer) && (bIsDeveloper(iPlayer, 4) || ((g_esPlayer[iPlayer].g_iRewardTypes & MT_REWARD_DAMAGEBOOST) && g_esPlayer[iPlayer].g_iRecoilDampener == 1))) + { + vToggleWeaponVerticalPunch(iPlayer, true); + } + } + } } void vViewDistanceQuery(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue) @@ -10110,7 +10184,6 @@ void vRemoveTankProps(int tank, int mode = 1) } g_esPlayer[tank].g_iFlashlight = INVALID_ENT_REFERENCE; - vRemovePlayerGlow(tank); if (mode == 1) @@ -11187,6 +11260,7 @@ void vCacheSettings(int tank) g_esCache[tank].g_iMinimumHumans = iGetSettingValue(bAccess, bHuman, g_esPlayer[tank].g_iMinimumHumans, g_esCache[tank].g_iMinimumHumans); g_esCache[tank].g_iMultiplyHealth = iGetSettingValue(bAccess, true, g_esTank[iType].g_iMultiplyHealth, g_esGeneral.g_iMultiplyHealth); g_esCache[tank].g_iMultiplyHealth = iGetSettingValue(bAccess, bHuman, g_esPlayer[tank].g_iMultiplyHealth, g_esCache[tank].g_iMultiplyHealth); + g_esCache[tank].g_iPrioritizeThrows = iGetSettingValue(bAccess, true, g_esTank[iType].g_iPrioritizeThrows, g_esGeneral.g_iPrioritizeThrows); g_esCache[tank].g_iPropsAttached = iGetSettingValue(bAccess, bHuman, g_esPlayer[tank].g_iPropsAttached, g_esTank[iType].g_iPropsAttached); g_esCache[tank].g_iRandomTank = iGetSettingValue(bAccess, bHuman, g_esPlayer[tank].g_iRandomTank, g_esTank[iType].g_iRandomTank); g_esCache[tank].g_iRockEffects = iGetSettingValue(bAccess, bHuman, g_esPlayer[tank].g_iRockEffects, g_esTank[iType].g_iRockEffects); @@ -11707,6 +11781,7 @@ void vReadTankSettings(int type, const char[] sub, const char[] key, const char[ g_esTank[iIndex].g_iVocalizeDeath = iGetKeyValue(sub, MT_CONFIG_SECTION_ANNOUNCE, MT_CONFIG_SECTION_ANNOUNCE, MT_CONFIG_SECTION_ANNOUNCE, MT_CONFIG_SECTION_ANNOUNCE2, key, "VocalizeDeath", "Vocalize Death", "Vocalize_Death", "deathvoc", g_esTank[iIndex].g_iVocalizeDeath, value, 0, 1); g_esTank[iIndex].g_iTeammateLimit = iGetKeyValue(sub, MT_CONFIG_SECTION_REWARDS, MT_CONFIG_SECTION_REWARDS, MT_CONFIG_SECTION_REWARDS, MT_CONFIG_SECTION_REWARDS, key, "TeammateLimit", "Teammate Limit", "Teammate_Limit", "teamlimit", g_esTank[iIndex].g_iTeammateLimit, value, 0, 32); g_esTank[iIndex].g_iAutoAggravate = iGetKeyValue(sub, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "AutoAggravate", "Auto Aggravate", "Auto_Aggravate", "autoaggro", g_esTank[iIndex].g_iAutoAggravate, value, 0, 1); + g_esTank[iIndex].g_iPrioritizeThrows = iGetKeyValue(sub, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "PrioritizeThrows", "Prioritize Throws", "Prioritize_Throws", "priothrow", g_esTank[iIndex].g_iPrioritizeThrows, value, 0, 1); g_esTank[iIndex].g_iGlowEnabled = iGetKeyValue(sub, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, key, "GlowEnabled", "Glow Enabled", "Glow_Enabled", "genabled", g_esTank[iIndex].g_iGlowEnabled, value, 0, 1); g_esTank[iIndex].g_iGlowFlashing = iGetKeyValue(sub, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, key, "GlowFlashing", "Glow Flashing", "Glow_Flashing", "flashing", g_esTank[iIndex].g_iGlowFlashing, value, 0, 1); g_esTank[iIndex].g_iGlowType = iGetKeyValue(sub, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, MT_CONFIG_SECTION_GLOW, key, "GlowType", "Glow Type", "Glow_Type", "type", g_esTank[iIndex].g_iGlowType, value, 0, 1); @@ -11812,7 +11887,7 @@ void vReadTankSettings(int type, const char[] sub, const char[] key, const char[ g_esTank[iIndex].g_iRewardBots[iPos] = iGetClampedValue(key, "RewardBots", "Reward Bots", "Reward_Bots", "bots", g_esTank[iIndex].g_iRewardBots[iPos], sSet[iPos], -1, 2147483647); g_esTank[iIndex].g_iRewardEffect[iPos] = iGetClampedValue(key, "RewardEffect", "Reward Effect", "Reward_Effect", "effect", g_esTank[iIndex].g_iRewardEffect[iPos], sSet[iPos], 0, 15); g_esTank[iIndex].g_iRewardNotify[iPos] = iGetClampedValue(key, "RewardNotify", "Reward Notify", "Reward_Notify", "rnotify", g_esTank[iIndex].g_iRewardNotify[iPos], sSet[iPos], 0, 3); - g_esTank[iIndex].g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esTank[iIndex].g_iRewardVisual[iPos], sSet[iPos], 0, 63); + g_esTank[iIndex].g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esTank[iIndex].g_iRewardVisual[iPos], sSet[iPos], 0, 127); g_esTank[iIndex].g_iAmmoBoostReward[iPos] = iGetClampedValue(key, "AmmoBoostReward", "Ammo Boost Reward", "Ammo_Boost_Reward", "ammoboost", g_esTank[iIndex].g_iAmmoBoostReward[iPos], sSet[iPos], 0, 1); g_esTank[iIndex].g_iAmmoRegenReward[iPos] = iGetClampedValue(key, "AmmoRegenReward", "Ammo Regen Reward", "Ammo_Regen_Reward", "ammoregen", g_esTank[iIndex].g_iAmmoRegenReward[iPos], sSet[iPos], 0, 99999); g_esTank[iIndex].g_iBunnyHopReward[iPos] = iGetClampedValue(key, "BunnyHopReward", "Bunny Hop Reward", "Bunny_Hop_Reward", "bhop", g_esTank[iIndex].g_iBunnyHopReward[iPos], sSet[iPos], 0, 1); @@ -13179,13 +13254,13 @@ void SMCParseStart_Main(SMCParser smc) g_esGeneral.g_csState = ConfigState_None; g_esGeneral.g_iCurrentLine = 0; g_esGeneral.g_iIgnoreLevel = 0; - g_esGeneral.g_iTypeCounter[0] = 0; - g_esGeneral.g_iTypeCounter[1] = 0; g_esGeneral.g_sCurrentSection[0] = '\0'; g_esGeneral.g_sCurrentSubSection[0] = '\0'; if (g_esGeneral.g_iConfigMode == 1) { + g_esGeneral.g_iTypeCounter[0] = 0; + g_esGeneral.g_iTypeCounter[1] = 0; g_esGeneral.g_iPluginEnabled = 0; g_esGeneral.g_iAutoUpdate = 0; g_esGeneral.g_iListenSupport = g_bDedicated ? 0 : 1; @@ -13248,6 +13323,7 @@ void SMCParseStart_Main(SMCParser smc) g_esGeneral.g_iAutoAggravate = 1; g_esGeneral.g_iCreditIgniters = 1; g_esGeneral.g_flForceSpawn = 0.0; + g_esGeneral.g_iPrioritizeThrows = 0; g_esGeneral.g_iStasisMode = 0; g_esGeneral.g_flSurvivalDelay = 0.1; g_esGeneral.g_iScaleDamage = 0; @@ -13320,7 +13396,7 @@ void SMCParseStart_Main(SMCParser smc) g_esGeneral.g_iRewardEffect[iPos] = 15; g_esGeneral.g_iRewardNotify[iPos] = 3; g_esGeneral.g_flRewardPercentage[iPos] = 10.0; - g_esGeneral.g_iRewardVisual[iPos] = 63; + g_esGeneral.g_iRewardVisual[iPos] = g_bSecondGame ? 127 : 63; g_esGeneral.g_flActionDurationReward[iPos] = 2.0; g_esGeneral.g_iAmmoBoostReward[iPos] = 1; g_esGeneral.g_iAmmoRegenReward[iPos] = 1; @@ -13439,6 +13515,7 @@ void SMCParseStart_Main(SMCParser smc) g_esTank[iIndex].g_sScreenColorVisual4[0] = '\0'; g_esTank[iIndex].g_iTeammateLimit = 0; g_esTank[iIndex].g_iAutoAggravate = 0; + g_esTank[iIndex].g_iPrioritizeThrows = 0; g_esTank[iIndex].g_iBaseHealth = 0; g_esTank[iIndex].g_iDisplayHealth = 0; g_esTank[iIndex].g_iDisplayHealthType = 0; @@ -13882,7 +13959,7 @@ SMCResult SMCNewSection_Main(SMCParser smc, const char[] name, bool opt_quotes) strcopy(g_esGeneral.g_sCurrentSection, sizeof esGeneral::g_sCurrentSection, name); - if (!strncmp(name, "Tank", 4, false) || name[0] == '#') + if (g_esGeneral.g_iConfigMode == 1 && (!strncmp(name, "Tank", 4, false) || name[0] == '#')) { int iStartPos = iGetConfigSectionNumber(g_esGeneral.g_sCurrentSection, sizeof esGeneral::g_sCurrentSection), iIndex = StringToInt(g_esGeneral.g_sCurrentSection[iStartPos]); for (int iType = 1; iType <= g_esGeneral.g_iTypeCounter[0]; iType++) @@ -13928,7 +14005,7 @@ SMCResult SMCNewSection_Main(SMCParser smc, const char[] name, bool opt_quotes) strcopy(g_esGeneral.g_sCurrentSubSection, sizeof esGeneral::g_sCurrentSubSection, name); - if (!strncmp(name, "Tank", 4, false) || name[0] == '#') + if (g_esGeneral.g_iConfigMode == 1 && (!strncmp(name, "Tank", 4, false) || name[0] == '#')) { int iStartPos = iGetConfigSectionNumber(g_esGeneral.g_sCurrentSubSection, sizeof esGeneral::g_sCurrentSubSection), iIndex = StringToInt(g_esGeneral.g_sCurrentSubSection[iStartPos]); for (int iType = 1; iType <= g_esGeneral.g_iTypeCounter[1]; iType++) @@ -14010,6 +14087,7 @@ SMCResult SMCKeyValues_Main(SMCParser smc, const char[] key, const char[] value, g_esGeneral.g_iAutoAggravate = iGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "AutoAggravate", "Auto Aggravate", "Auto_Aggravate", "autoaggro", g_esGeneral.g_iAutoAggravate, value, 0, 1); g_esGeneral.g_iCreditIgniters = iGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "CreditIgniters", "Credit Igniters", "Credit_Igniters", "credit", g_esGeneral.g_iCreditIgniters, value, 0, 1); g_esGeneral.g_flForceSpawn = flGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "ForceSpawn", "Force Spawn", "Force_Spawn", "force", g_esGeneral.g_flForceSpawn, value, 0.0, 99999.0); + g_esGeneral.g_iPrioritizeThrows = iGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "PrioritizeThrows", "Prioritize Throws", "Prioritize_Throws", "priothrow", g_esGeneral.g_iPrioritizeThrows, value, 0, 1); g_esGeneral.g_iStasisMode = iGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "StasisMode", "Stasis Mode", "Stasis_Mode", "stasis", g_esGeneral.g_iStasisMode, value, 0, 1); g_esGeneral.g_flSurvivalDelay = flGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP, MT_CONFIG_SECTION_COMP2, key, "SurvivalDelay", "Survival Delay", "Survival_Delay", "survdelay", g_esGeneral.g_flSurvivalDelay, value, 0.1, 99999.0); g_esGeneral.g_iScaleDamage = iGetKeyValue(g_esGeneral.g_sCurrentSubSection, MT_CONFIG_SECTION_DIFF, MT_CONFIG_SECTION_DIFF, MT_CONFIG_SECTION_DIFF, MT_CONFIG_SECTION_DIFF2, key, "ScaleDamage", "Scale Damage", "Scale_Damage", "scaledmg", g_esGeneral.g_iScaleDamage, value, 0, 1); @@ -14114,7 +14192,7 @@ SMCResult SMCKeyValues_Main(SMCParser smc, const char[] key, const char[] value, g_esGeneral.g_iRewardBots[iPos] = iGetClampedValue(key, "RewardBots", "Reward Bots", "Reward_Bots", "bots", g_esGeneral.g_iRewardBots[iPos], sSet[iPos], -1, 2147483647); g_esGeneral.g_iRewardEffect[iPos] = iGetClampedValue(key, "RewardEffect", "Reward Effect", "Reward_Effect", "effect", g_esGeneral.g_iRewardEffect[iPos], sSet[iPos], 0, 15); g_esGeneral.g_iRewardNotify[iPos] = iGetClampedValue(key, "RewardNotify", "Reward Notify", "Reward_Notify", "rnotify", g_esGeneral.g_iRewardNotify[iPos], sSet[iPos], 0, 3); - g_esGeneral.g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esGeneral.g_iRewardVisual[iPos], sSet[iPos], 0, 63); + g_esGeneral.g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esGeneral.g_iRewardVisual[iPos], sSet[iPos], 0, 127); g_esGeneral.g_iAmmoBoostReward[iPos] = iGetClampedValue(key, "AmmoBoostReward", "Ammo Boost Reward", "Ammo_Boost_Reward", "ammoboost", g_esGeneral.g_iAmmoBoostReward[iPos], sSet[iPos], 0, 1); g_esGeneral.g_iAmmoRegenReward[iPos] = iGetClampedValue(key, "AmmoRegenReward", "Ammo Regen Reward", "Ammo_Regen_Reward", "ammoregen", g_esGeneral.g_iAmmoRegenReward[iPos], sSet[iPos], 0, 99999); g_esGeneral.g_iBunnyHopReward[iPos] = iGetClampedValue(key, "BunnyHopReward", "Bunny Hop Reward", "Bunny_Hop_Reward", "bhop", g_esGeneral.g_iBunnyHopReward[iPos], sSet[iPos], 0, 1); @@ -14419,7 +14497,7 @@ SMCResult SMCKeyValues_Main(SMCParser smc, const char[] key, const char[] value, g_esPlayer[iPlayer].g_iRewardBots[iPos] = iGetClampedValue(key, "RewardBots", "Reward Bots", "Reward_Bots", "bots", g_esPlayer[iPlayer].g_iRewardBots[iPos], sSet[iPos], -1, 2147483647); g_esPlayer[iPlayer].g_iRewardEffect[iPos] = iGetClampedValue(key, "RewardEffect", "Reward Effect", "Reward_Effect", "effect", g_esPlayer[iPlayer].g_iRewardEffect[iPos], sSet[iPos], 0, 15); g_esPlayer[iPlayer].g_iRewardNotify[iPos] = iGetClampedValue(key, "RewardNotify", "Reward Notify", "Reward_Notify", "rnotify", g_esPlayer[iPlayer].g_iRewardNotify[iPos], sSet[iPos], 0, 3); - g_esPlayer[iPlayer].g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esPlayer[iPlayer].g_iRewardVisual[iPos], sSet[iPos], 0, 63); + g_esPlayer[iPlayer].g_iRewardVisual[iPos] = iGetClampedValue(key, "RewardVisual", "Reward Visual", "Reward_Visual", "visual", g_esPlayer[iPlayer].g_iRewardVisual[iPos], sSet[iPos], 0, 127); g_esPlayer[iPlayer].g_iAmmoBoostReward[iPos] = iGetClampedValue(key, "AmmoBoostReward", "Ammo Boost Reward", "Ammo_Boost_Reward", "ammoboost", g_esPlayer[iPlayer].g_iAmmoBoostReward[iPos], sSet[iPos], 0, 1); g_esPlayer[iPlayer].g_iAmmoRegenReward[iPos] = iGetClampedValue(key, "AmmoRegenReward", "Ammo Regen Reward", "Ammo_Regen_Reward", "ammoregen", g_esPlayer[iPlayer].g_iAmmoRegenReward[iPos], sSet[iPos], 0, 99999); g_esPlayer[iPlayer].g_iBunnyHopReward[iPos] = iGetClampedValue(key, "BunnyHopReward", "Bunny Hop Reward", "Bunny_Hop_Reward", "bhop", g_esPlayer[iPlayer].g_iBunnyHopReward[iPos], sSet[iPos], 0, 1); @@ -14696,8 +14774,6 @@ void SMCParseEnd_Main(SMCParser smc, bool halted, bool failed) { g_esGeneral.g_csState = ConfigState_None; g_esGeneral.g_iIgnoreLevel = 0; - g_esGeneral.g_iTypeCounter[0] = 0; - g_esGeneral.g_iTypeCounter[1] = 0; g_esGeneral.g_sCurrentSection[0] = '\0'; g_esGeneral.g_sCurrentSubSection[0] = '\0'; @@ -14962,6 +15038,21 @@ void vPlayerSpawnFrame(DataPack pack) } } +void vPummelTeleportFrame(DataPack pack) +{ + pack.Reset(); + int iSurvivor = GetClientOfUserId(pack.ReadCell()), iSpecial = GetClientOfUserId(pack.ReadCell()); + delete pack; + + if (bIsValidClient(iSurvivor) && bIsValidClient(iSpecial)) + { + SetVariantString("!activator"); + AcceptEntityInput(iSurvivor, "SetParent", iSpecial); + TeleportEntity(iSurvivor, view_as({50.0, 0.0, 0.0}), NULL_VECTOR, NULL_VECTOR); + AcceptEntityInput(iSurvivor, "ClearParent"); + } +} + void vRespawnFrame(int userid) { int iSurvivor = GetClientOfUserId(userid); @@ -15155,7 +15246,7 @@ Action OnFriendlyTakeDamage(int victim, int &attacker, int &inflictor, float &da if (damagetype == 134217792) { char sClassname[5]; - GetEntityClassname(inflictor, sClassname, sizeof(sClassname)); + GetEntityClassname(inflictor, sClassname, sizeof sClassname); if (StrEqual(sClassname, "pipe") && (bIsDeveloper(victim, 4) || ((g_esPlayer[victim].g_iRewardTypes & MT_REWARD_DAMAGEBOOST) && g_esPlayer[victim].g_iFriendlyFire == 1))) { return Plugin_Handled; @@ -16355,6 +16446,7 @@ void vSetupDetours() vSetupDetour(g_esGeneral.g_ddFirstSurvivorLeftSafeAreaDetour, "MTDetour_CDirector::OnFirstSurvivorLeftSafeArea"); vSetupDetour(g_esGeneral.g_ddFlingDetour, "MTDetour_CTerrorPlayer::Fling"); vSetupDetour(g_esGeneral.g_ddGetMaxClip1Detour, "MTDetour_CBaseCombatWeapon::GetMaxClip1"); + vSetupDetour(g_esGeneral.g_ddGrabVictimWithTongueDetour, "MTDetour_CTerrorPlayer::GrabVictimWithTongue"); vSetupDetour(g_esGeneral.g_ddHitByVomitJarDetour, "MTDetour_CTerrorPlayer::OnHitByVomitJar"); vSetupDetour(g_esGeneral.g_ddIncapacitatedAsTankDetour, "MTDetour_CTerrorPlayer::OnIncapacitatedAsTank"); vSetupDetour(g_esGeneral.g_ddInitialContainedActionDetour, "MTDetour_TankBehavior::InitialContainedAction"); @@ -16363,9 +16455,12 @@ void vSetupDetours() vSetupDetour(g_esGeneral.g_ddLadderMountDetour, "MTDetour_CTerrorPlayer::OnLadderMount"); vSetupDetour(g_esGeneral.g_ddLauncherDirectionDetour, "MTDetour_CEnvRockLauncher::LaunchCurrentDir"); vSetupDetour(g_esGeneral.g_ddLeaveStasisDetour, "MTDetour_Tank::LeaveStasis"); + vSetupDetour(g_esGeneral.g_ddLeptOnSurvivorDetour, "MTDetour_CTerrorPlayer::OnLeptOnSurvivor"); vSetupDetour(g_esGeneral.g_ddMaxCarryDetour, "MTDetour_CAmmoDef::MaxCarry"); vSetupDetour(g_esGeneral.g_ddPipeBombProjectileCreateDetour, "MTDetour_CPipeBombProjectile::Create"); + vSetupDetour(g_esGeneral.g_ddPouncedOnSurvivorDetour, "MTDetour_CTerrorPlayer::OnPouncedOnSurvivor"); vSetupDetour(g_esGeneral.g_ddPreThinkDetour, "MTDetour_CTerrorPlayer::PreThink"); + vSetupDetour(g_esGeneral.g_ddQueuePummelVictimDetour, "MTDetour_CTerrorPlayer::QueuePummelVictim"); vSetupDetour(g_esGeneral.g_ddReplaceTankDetour, "MTDetour_ZombieManager::ReplaceTank"); vSetupDetour(g_esGeneral.g_ddRevivedDetour, "MTDetour_CTerrorPlayer::OnRevived"); vSetupDetour(g_esGeneral.g_ddSecondaryAttackDetour, "MTDetour_CTerrorWeapon::SecondaryAttack"); @@ -16377,6 +16472,7 @@ void vSetupDetours() vSetupDetour(g_esGeneral.g_ddSpawnTankDetour, "MTDetour_ZombieManager::SpawnTank"); vSetupDetour(g_esGeneral.g_ddStaggeredDetour, "MTDetour_CTerrorPlayer::OnStaggered"); vSetupDetour(g_esGeneral.g_ddStartActionDetour, "MTDetour_CBaseBackpackItem::StartAction"); + vSetupDetour(g_esGeneral.g_ddStartCarryingVictimDetour, "MTDetour_CTerrorPlayer::OnStartCarryingVictim"); vSetupDetour(g_esGeneral.g_ddStartHealingDetour, "MTDetour_CFirstAidKit::StartHealing"); vSetupDetour(g_esGeneral.g_ddStartRevivingDetour, "MTDetour_CTerrorPlayer::StartReviving"); vSetupDetour(g_esGeneral.g_ddTankClawDoSwingDetour, "MTDetour_CTankClaw::DoSwing"); @@ -16388,6 +16484,7 @@ void vSetupDetours() vSetupDetour(g_esGeneral.g_ddTankRockReleaseDetour, "MTDetour_CTankRock::OnRelease"); vSetupDetour(g_esGeneral.g_ddTestMeleeSwingCollisionDetour, "MTDetour_CTerrorMeleeWeapon::TestMeleeSwingCollision"); vSetupDetour(g_esGeneral.g_ddThrowActivateAbilityDetour, "MTDetour_CThrow::ActivateAbility"); + vSetupDetour(g_esGeneral.g_ddTryToThrowRockDetour, "MTDetour_TankAttack::TryToThrowRock"); vSetupDetour(g_esGeneral.g_ddUseDetour, "MTDetour_CTerrorGun::Use"); vSetupDetour(g_esGeneral.g_ddUseDetour2, "MTDetour_CWeaponSpawn::Use"); vSetupDetour(g_esGeneral.g_ddVomitedUponDetour, "MTDetour_CTerrorPlayer::OnVomitedUpon"); @@ -16449,11 +16546,14 @@ void vToggleDetours(bool toggle) vToggleDetour(g_esGeneral.g_ddDoAnimationEventDetour, "MTDetour_CTerrorPlayer::DoAnimationEvent", Hook_Pre, mreDoAnimationEventPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddFlingDetour, "MTDetour_CTerrorPlayer::Fling", Hook_Pre, mreFlingPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddHitByVomitJarDetour, "MTDetour_CTerrorPlayer::OnHitByVomitJar", Hook_Pre, mreHitByVomitJarPre, toggle, 2); + vToggleDetour(g_esGeneral.g_ddLeptOnSurvivorDetour, "MTDetour_CTerrorPlayer::OnLeptOnSurvivor", Hook_Pre, mreLeptOnSurvivorPre, toggle, 2); + vToggleDetour(g_esGeneral.g_ddQueuePummelVictimDetour, "MTDetour_CTerrorPlayer::QueuePummelVictim", Hook_Pre, mreQueuePummelVictimPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddSecondaryAttackDetour2, "MTDetour_CTerrorMeleeWeapon::SecondaryAttack", Hook_Pre, mreSecondaryAttackPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddSecondaryAttackDetour2, "MTDetour_CTerrorMeleeWeapon::SecondaryAttack", Hook_Post, mreSecondaryAttackPost, toggle, 2); vToggleDetour(g_esGeneral.g_ddSelectWeightedSequenceDetour, "MTDetour_CTerrorPlayer::SelectWeightedSequence", Hook_Pre, mreSelectWeightedSequencePre, toggle, 2); vToggleDetour(g_esGeneral.g_ddStartActionDetour, "MTDetour_CBaseBackpackItem::StartAction", Hook_Pre, mreStartActionPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddStartActionDetour, "MTDetour_CBaseBackpackItem::StartAction", Hook_Post, mreStartActionPost, toggle, 2); + vToggleDetour(g_esGeneral.g_ddStartCarryingVictimDetour, "MTDetour_CTerrorPlayer::OnStartCarryingVictim", Hook_Pre, mreStartCarryingVictimPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddTankRockCreateDetour, "MTDetour_CTankRock::Create", Hook_Post, mreTankRockCreatePost, toggle, 2); vToggleDetour(g_esGeneral.g_ddTestMeleeSwingCollisionDetour, "MTDetour_CTerrorMeleeWeapon::TestMeleeSwingCollision", Hook_Pre, mreTestMeleeSwingCollisionPre, toggle, 2); vToggleDetour(g_esGeneral.g_ddTestMeleeSwingCollisionDetour, "MTDetour_CTerrorMeleeWeapon::TestMeleeSwingCollision", Hook_Post, mreTestMeleeSwingCollisionPost, toggle, 2); @@ -16479,6 +16579,7 @@ void vToggleDetours(bool toggle) vToggleDetour(g_esGeneral.g_ddFireBulletDetour, "MTDetour_CTerrorGun::FireBullet", Hook_Post, mreFireBulletPost, toggle); vToggleDetour(g_esGeneral.g_ddFirstSurvivorLeftSafeAreaDetour, "MTDetour_CDirector::OnFirstSurvivorLeftSafeArea", Hook_Post, mreFirstSurvivorLeftSafeAreaPost, toggle); vToggleDetour(g_esGeneral.g_ddGetMaxClip1Detour, "MTDetour_CBaseCombatWeapon::GetMaxClip1", Hook_Pre, mreGetMaxClip1Pre, toggle); + vToggleDetour(g_esGeneral.g_ddGrabVictimWithTongueDetour, "MTDetour_CTerrorPlayer::GrabVictimWithTongue", Hook_Pre, mreGrabVictimWithTonguePre, toggle); vToggleDetour(g_esGeneral.g_ddIncapacitatedAsTankDetour, "MTDetour_CTerrorPlayer::OnIncapacitatedAsTank", Hook_Pre, mreIncapacitatedAsTankPre, toggle); vToggleDetour(g_esGeneral.g_ddIncapacitatedAsTankDetour, "MTDetour_CTerrorPlayer::OnIncapacitatedAsTank", Hook_Post, mreIncapacitatedAsTankPost, toggle); vToggleDetour(g_esGeneral.g_ddInitialContainedActionDetour, "MTDetour_TankBehavior::InitialContainedAction", Hook_Pre, mreInitialContainedActionPre, toggle); @@ -16493,6 +16594,7 @@ void vToggleDetours(bool toggle) vToggleDetour(g_esGeneral.g_ddMaxCarryDetour, "MTDetour_CAmmoDef::MaxCarry", Hook_Pre, mreMaxCarryPre, toggle); vToggleDetour(g_esGeneral.g_ddPipeBombProjectileCreateDetour, "MTDetour_CPipeBombProjectile::Create", Hook_Pre, mrePipeBombProjectileCreatePre, toggle); vToggleDetour(g_esGeneral.g_ddPipeBombProjectileCreateDetour, "MTDetour_CPipeBombProjectile::Create", Hook_Post, mrePipeBombProjectileCreatePost, toggle); + vToggleDetour(g_esGeneral.g_ddPouncedOnSurvivorDetour, "MTDetour_CTerrorPlayer::OnPouncedOnSurvivor", Hook_Pre, mrePouncedOnSurvivorPre, toggle); vToggleDetour(g_esGeneral.g_ddPreThinkDetour, "MTDetour_CTerrorPlayer::PreThink", Hook_Pre, mrePreThinkPre, toggle); vToggleDetour(g_esGeneral.g_ddPreThinkDetour, "MTDetour_CTerrorPlayer::PreThink", Hook_Post, mrePreThinkPost, toggle); vToggleDetour(g_esGeneral.g_ddReplaceTankDetour, "MTDetour_ZombieManager::ReplaceTank", Hook_Post, mreReplaceTankPost, toggle); @@ -16515,6 +16617,8 @@ void vToggleDetours(bool toggle) vToggleDetour(g_esGeneral.g_ddTankClawPrimaryAttackDetour, "MTDetour_CTankClaw::PrimaryAttack", Hook_Pre, mreTankClawPrimaryAttackPre, toggle); vToggleDetour(g_esGeneral.g_ddTankRockDetonateDetour, "MTDetour_CTankRock::Detonate", Hook_Pre, mreTankRockDetonatePre, toggle); vToggleDetour(g_esGeneral.g_ddThrowActivateAbilityDetour, "MTDetour_CThrow::ActivateAbility", Hook_Pre, mreThrowActivateAbilityPre, toggle); + vToggleDetour(g_esGeneral.g_ddTryToThrowRockDetour, "MTDetour_TankAttack::TryToThrowRock", Hook_Pre, mreTryToThrowRockPre, toggle); + vToggleDetour(g_esGeneral.g_ddTryToThrowRockDetour, "MTDetour_TankAttack::TryToThrowRock", Hook_Post, mreTryToThrowRockPost, toggle); vToggleDetour(g_esGeneral.g_ddUseDetour, "MTDetour_CTerrorGun::Use", Hook_Pre, mreUsePre, toggle); vToggleDetour(g_esGeneral.g_ddUseDetour, "MTDetour_CTerrorGun::Use", Hook_Post, mreUsePost, toggle); vToggleDetour(g_esGeneral.g_ddUseDetour2, "MTDetour_CWeaponSpawn::Use", Hook_Pre, mreUsePre, toggle); @@ -17200,6 +17304,17 @@ MRESReturn mreGetMaxClip1Pre(int pThis, DHookReturn hReturn) return MRES_Ignored; } +MRESReturn mreGrabVictimWithTonguePre(int pThis, DHookParam hParams) +{ + int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); + if (bIsSurvivor(iSurvivor) && (bIsDeveloper(iSurvivor, 11) || (g_esPlayer[iSurvivor].g_iRewardTypes & MT_REWARD_GODMODE))) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + MRESReturn mreHitByVomitJarPre(int pThis, DHookParam hParams) { int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); @@ -17377,6 +17492,17 @@ MRESReturn mreLeaveStasisPost(int pThis) return MRES_Ignored; } +MRESReturn mreLeptOnSurvivorPre(int pThis, DHookParam hParams) +{ + int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); + if (bIsSurvivor(iSurvivor) && (bIsDeveloper(iSurvivor, 11) || (g_esPlayer[iSurvivor].g_iRewardTypes & MT_REWARD_GODMODE))) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + MRESReturn mreMaxCarryPre(Address pThis, DHookReturn hReturn, DHookParam hParams) { int iSurvivor = hParams.IsNull(2) ? 0 : hParams.Get(2), iAmmo = iGetMaxAmmo(iSurvivor, hParams.Get(1), 0, true); @@ -17425,6 +17551,17 @@ MRESReturn mrePipeBombProjectileCreatePost(DHookReturn hReturn, DHookParam hPara return MRES_Ignored; } +MRESReturn mrePouncedOnSurvivorPre(int pThis, DHookParam hParams) +{ + int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); + if (bIsSurvivor(iSurvivor) && (bIsDeveloper(iSurvivor, 11) || (g_esPlayer[iSurvivor].g_iRewardTypes & MT_REWARD_GODMODE))) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + MRESReturn mrePreThinkPre(int pThis) { if (bIsSurvivor(pThis) && (bIsDeveloper(pThis, 6) || ((g_esPlayer[pThis].g_iRewardTypes & MT_REWARD_ATTACKBOOST) && g_esPlayer[pThis].g_iLadderActions == 1))) @@ -17460,6 +17597,24 @@ MRESReturn mrePreThinkPost(int pThis) return MRES_Ignored; } +MRESReturn mreQueuePummelVictimPre(int pThis, DHookParam hParams) +{ + int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); + if (bIsSurvivor(iSurvivor) && (bIsDeveloper(iSurvivor, 11) || (g_esPlayer[iSurvivor].g_iRewardTypes & MT_REWARD_GODMODE))) + { + DataPack dpPummel = new DataPack(); + dpPummel.WriteCell(GetClientUserId(iSurvivor)); + dpPummel.WriteCell(GetClientUserId(pThis)); + RequestFrame(vPummelTeleportFrame, dpPummel); + + SetEntityMoveType(iSurvivor, MOVETYPE_WALK); + + return MRES_Supercede; + } + + return MRES_Ignored; +} + MRESReturn mreReplaceTankPost(DHookParam hParams) { int iOldTank = hParams.IsNull(1) ? 0 : hParams.Get(1), iNewTank = hParams.IsNull(2) ? 0 : hParams.Get(2), @@ -17666,6 +17821,17 @@ MRESReturn mreStartActionPost(int pThis, DHookReturn hReturn, DHookParam hParams return MRES_Ignored; } +MRESReturn mreStartCarryingVictimPre(int pThis, DHookParam hParams) +{ + int iSurvivor = hParams.IsNull(1) ? 0 : hParams.Get(1); + if (bIsSurvivor(iSurvivor) && (bIsDeveloper(iSurvivor, 11) || (g_esPlayer[iSurvivor].g_iRewardTypes & MT_REWARD_GODMODE))) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + MRESReturn mreStartHealingLinuxPre(DHookParam hParams) { int pThis = hParams.Get(1), iSurvivor = !bIsValidEntity(pThis) ? 0 : GetEntPropEnt(pThis, Prop_Send, "m_hOwner"); @@ -18039,6 +18205,52 @@ MRESReturn mreThrowActivateAbilityPre(int pThis) return MRES_Ignored; } +MRESReturn mreTryToThrowRockPre(Address pThis, DHookParam hParams) +{ + int iTank = hParams.Get(1); + if (bIsTank(iTank) && bIsCoopMode() && g_esCache[iTank].g_iPrioritizeThrows == 1) + { + char sName[32]; + static int iIndex[2] = {-1, -1}; + for (int iPos = 0; iPos < (sizeof iIndex); iPos++) + { + if (iIndex[iPos] == -1) + { + FormatEx(sName, sizeof sName, "MTPatch_TankAttackDifficulty%i", (iPos + 1)); + iIndex[iPos] = iGetPatchIndex(sName); + } + + if (iIndex[iPos] != -1) + { + vInstallPatch(iIndex[iPos]); + } + } + } + + return MRES_Ignored; +} + +MRESReturn mreTryToThrowRockPost(Address pThis, DHookParam hParams) +{ + char sName[32]; + static int iIndex[2] = {-1, -1}; + for (int iPos = 0; iPos < (sizeof iIndex); iPos++) + { + if (iIndex[iPos] == -1) + { + FormatEx(sName, sizeof sName, "MTPatch_TankAttackDifficulty%i", (iPos + 1)); + iIndex[iPos] = iGetPatchIndex(sName); + } + + if (iIndex[iPos] != -1) + { + vRemovePatch(iIndex[iPos]); + } + } + + return MRES_Ignored; +} + MRESReturn mreUsePre(int pThis, DHookParam hParams) { int iSurvivor = hParams.Get(1); diff --git a/cfg/sourcemod/mutant_tanks.cfg b/cfg/sourcemod/mutant_tanks.cfg index 5177b51545..c06faf7fb9 100644 --- a/cfg/sourcemod/mutant_tanks.cfg +++ b/cfg/sourcemod/mutant_tanks.cfg @@ -12,6 +12,13 @@ // Maximum: "1.000000" mt_autoupdate "0" +// The config filename used by Mutant Tanks to read settings from. +// Empty: None +// Not empty: The custom config filename to use. +// - +// Default: "mutant_tanks.cfg" +mt_configfile "mutant_tanks.cfg" + // Disable Mutant Tanks in these game modes. // Separate by commas. // Empty: None