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