Compare commits

...

34 commits

Author SHA1 Message Date
1ab9848ee7 archive project 2022-06-29 23:53:27 +09:00
3c7d101d72 improved building instruction 2022-05-06 23:15:50 +09:00
c210ae8e81 v1.14 update: made it work in v466 2022-05-06 23:15:38 +09:00
a6359cca7b v1.13.0.0 update: made it work in v465 2022-04-30 12:24:12 +09:00
ffebff3229 v1.12.0.0 update
- made it work in v464
2022-04-12 13:20:16 +09:00
106dc517f5 made WBM work in v463 2022-04-01 14:52:55 +09:00
f9fb8d7a4e v1.10.0.0 update
- made WBM work in WB v462
2022-03-26 13:40:13 +09:00
bbd8d882e6 filename capitalization 2022-03-21 13:20:54 +09:00
aeba107b31 bumped version from v1.9.1.0 to v1.9.2.0 2022-03-20 17:54:33 +09:00
33571dc3ef fixed old gun sound 2022-03-20 17:54:08 +09:00
1a7f50476b fixed gun sound replacement logic 2022-03-19 17:35:47 +09:00
d823e55e92 v1.9.0.0 update
- made it work in v461
- improved project structure
2022-03-19 11:11:19 +09:00
5df7dca06f improved code readability
- added mangled name dictionary
- added class alias
2022-03-18 20:52:43 +09:00
854cf56bce added video tutorial link 2022-03-18 13:32:57 +09:00
f8418e36e3 v1.8.0.0 update
- fixed mod to work in v460
2022-03-18 13:05:36 +09:00
1fb7e162df README tags update
- removed license tag
- added "what's this?" tag
2022-03-16 11:23:11 +09:00
fa37d4390b improved project structure 2022-03-12 20:28:48 +09:00
b37cca33c4 improved function naming 2022-03-12 11:37:36 +09:00
1e5ce5fda2 readability improvement 2022-03-12 10:42:37 +09:00
beabe6b56a separated logic to dedicated files/directories 2022-03-12 10:25:37 +09:00
0317053e4c updated feature description 2022-03-11 13:08:03 +09:00
25184a27d2 improved section separation 2022-03-11 11:50:54 +09:00
22de1eee4b moved UI related code to separate file 2022-03-10 16:30:59 +09:00
3fd5113d20 simplified Update function 2022-03-10 15:57:01 +09:00
4dc04d25da code splitting for key presses 2022-03-10 15:54:45 +09:00
4c10c59b3b code formatting update
- applied new code formatting
- code splitting on `WBM.cs`
2022-03-10 15:14:48 +09:00
f59718a144 added more words to vscode workspace dictionary 2022-03-10 14:59:21 +09:00
b517914b45 updated README
- made badges bigger
- improved readability in general
- moved OBS related information to the WBM-Overlays repository
2022-03-08 13:22:53 +09:00
d509a618b4 updated install instruction 2022-02-09 11:51:31 +09:00
f78c0ccd8b improved readability and added link to installer 2022-01-23 14:41:57 +09:00
7d15cf225f added link to sound effects 2022-01-01 15:57:53 +09:00
c39649d1ff fixed incorrectly formatted markdown 2022-01-01 15:53:24 +09:00
195e44c005 made folder tree more consistent 2021-10-27 00:08:20 +09:00
b2b7074213 improved readability 2021-10-27 00:07:07 +09:00
30 changed files with 1363 additions and 969 deletions

10
.vscode/settings.json vendored
View file

@ -1,5 +1,13 @@
{
"cSpell.words": ["Behaviour", "Prefs", "headshot", "leaderboard", "wbm"],
"cSpell.words": [
"Behaviour",
"developomp",
"headshot",
"leaderboard",
"Prefs",
"wbm"
],
"editor.formatOnSave": true,
"editor.formatOnPaste": true,

18
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,18 @@
# Contribution guide
## feature structure
- All features should be contained in the `WBM/features` folder.
### Feature functions
- All features can have at most one function to be called in each event functions.
- feature function should have the following format: `<prefix><feature name>`
| Event function | feature function prefix |
| -------------: | :---------------------- |
| `Awake` | `init` |
| `Start` | `setup` |
| `Update` | `do` |
| `OnGUI` | `draw` |
| `onDestroy` | `destroy` |

224
README.md
View file

@ -1,15 +1,23 @@
# [War Brokers Mods (WBM)](https://github.com/War-Brokers-Mods/WBM)
![License: MIT](https://img.shields.io/github/license/War-Brokers-Mods/WBM?style=flat-square&color=blue)
[![discord invite](https://img.shields.io/badge/Discord-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/aQqamSCUcS)
WBM has been officially included into the game
> **IF YOU USE THIS TO DEVELOP HACKS YOUR MOM IS GAY.**
<details>
<summary>Potentially outdated information (click to unfold)</summary>
[![what's this?](https://img.shields.io/badge/what's_this%3F-grey?style=for-the-badge)](https://developomp.com/portfolio/wbm)
[![discord invite](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/aQqamSCUcS)
[![video tutorial](https://img.shields.io/badge/video_tutorial-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/watch?v=ZBE3nVvHwF8&t=64s)
<p align="center">
<strong>IF YOU USE THIS TO DEVELOP HACKS YOUR MOM IS GAY.</strong>
</p>
<p align="center">
<img src="images/WBM.png" alt="WBM logo"/>
</p>
**W**ar **B**rokers **M**ods, AKA **WBM** is a unofficial mod for [War Brokers](https://store.steampowered.com/app/750470).<br />
**W**ar **B**rokers **M**ods, AKA **WBM** is a mod for [War Brokers](https://store.steampowered.com/app/750470).<br />
<details>
<summary>Example Images (click to unfold)</summary>
@ -22,36 +30,38 @@
## Installation
Only Windows, MacOS, and Linux are officially supported. It is Not compatible with browsers.
Only Windows, MacOS, and Linux are officially supported. It does **NOT** work on browsers.
> **WARNING**<br />
> I do not upload WBM anywhere other than github. If you find it elsewhere, IT IS NOT UPLOADED BY ME.
Usage of the [WBM Installer](https://github.com/War-Brokers-Mods/WBM-installer/releases) is recommended.
<details>
<summary>Manual Installation Instruction (not recommended) (click to unfold)</summary>
### 1. Install BepInEx
1. Download the latest version of BepInEx **version 5** from [here](https://github.com/BepInEx/BepInEx/releases). It is important that you download the right version.
1. Download the latest version of [BepInEx](https://github.com/BepInEx/BepInEx/releases) **version 5**.
| Platform | Filename |
| ------------: | :---------------------------- |
| Linux & MacOS | BepInEx\_**unix_5**.Y.Z.W.zip |
| Windows | BepInEx\_**x86_5**.Y.Z.W.zip |
2. Extract (Unzip) the content**S** to where the game is installed.
2. Extract all the contents to where the game is installed.
How to find game location:<br />
![how to find game location](./images/local_files.png)
The folder structure should look like this after unzipping file:
Now the folder structure should look like this:
```
WarBrokers/
├── BepInEx/
  ├── core/
└ other files...
other files...
├── core/
└── ...
── ...
```
3. If you are using Linux or MacOS, you must also perform the following setup:
3. **If you are using Linux or MacOS:**
1. make `run_bepinex.sh` executable: `chmod u+x run_bepinex.sh`
2. Add launch option
@ -59,102 +69,102 @@ Only Windows, MacOS, and Linux are officially supported. It is Not compatible wi
where to find game properties:<br />
![where to find game properties](images/properties.png)
If you're on linux, set the launch option to:
**If you're using linux**, set the launch option to:
```bash
./run_bepinex.sh %command%
```
If you're on Mac, open a terminal in the game folder and run
**If you're using Mac**, open a terminal in the game folder and run
```bash
pwd
```
This will print the full path to the game folder. Copy it. Next, set launch option to
This will print the full path to the game folder. Copy it, then set the launch option to:
```bash
"PUT_RESULT_FROM_PWD_HERE/run_bepinex.sh" %command%
"PWD_RESULT_HERE/run_bepinex.sh" %command%
```
4. Run the game at least once to generate the plugins folder as well as other necessary files.
### 2. Install WBM
1. [Download](https://github.com/War-Brokers-Mods/WBM/releases/latest) the latest version of WBM. (`WBM.zip` file)
2. Unzip it in the `<Game folder>/BepInEx/plugins` folder.
2. Unzip it in the `<game folder>/BepInEx/plugins` folder. Create one if it doesn't exist.
It should look like this:
The folder structure should look like this after unzipping the file:
```
plugins (in the BepInEx folder)
└── WBM
├── assets
│   └── audio
│   └── ...
└── WBM.dll
WarBrokers/
├── BepInEx/
│ ├── plugins/
│ │ └── WBM
│ │ ├── assets/
│ │ ├── WBM.dll
│ │ └── ...
│ ├── core/
│ └── ...
└── ...
```
### 3. Set up OBS (optional)
1. [Download](https://github.com/War-Brokers-Mods/WBM-Overlays/archive/refs/heads/master.zip) the overlays and Unzip it anywhere. (Source code can be found [here](https://github.com/War-Brokers-Mods/WBM-Overlays))
2. Create a new browser source in OBS studio.
![OBS source](./images/obs_source.png)
3. Check the `Local file` checkbox and use a `.html` file of the overlay you want to use. Width and height of the overlays can be found [here](#obs-overlays).
![OBS source property](./images/obs_source_props.png)
That's it! You can open War Brokers now.
### Updating
Simply go through the installation process again and replace existing files. You don't have to reinstall BepInEx to reinstall WBM.
</details>
## Usage
### Warning
The order of keystroke matters.<br />
For example, pressing <kbd>RShift</kbd>+<kbd>A</kbd> is different from pressing <kbd>A</kbd>+<kbd>RShift</kbd>.<br/>
This is to prevent situation where <kbd>RShift</kbd>+<kbd>A</kbd> fires when the user intended to press <kbd>LCtrl</kbd>+<kbd>RShift</kbd>+<kbd>A</kbd>.
### Default shortcuts
- Hold down <kbd>LCtrl</kbd> or <kbd>RShift</kbd> to show shortcuts in-game.
- Press F1 to show menu. Press outside the menu to close.
- Press F1 to show menu. Click outside the menu to close it.
| Function | Default Shortcut |
| ------------------------------------ | --------------------------------------------------- |
| Show Menu | <kbd>F1</kbd> |
| <br /> | |
| Move GUI | <kbd>LCtrl</kbd>+<kbd>LShift</kbd>+<kbd>Arrow</kbd> |
| Move GUI by one pixel | <kbd>LCtrl</kbd>+<kbd>Arrow</kbd> |
| Reset GUI position | <kbd>LCtrl</kbd>+<kbd>R</kbd> |
| <br /> | |
| Toggle All GUI visibility | <kbd>RShift</kbd>+<kbd>A</kbd> |
| Toggle Player statistics visibility | <kbd>RShift</kbd>+<kbd>P</kbd> |
| Toggle Weapon statistics visibility | <kbd>RShift</kbd>+<kbd>W</kbd> |
| Toggle Team statistics visibility | <kbd>RShift</kbd>+<kbd>L</kbd> |
| Toggle Elo visibility on leaderboard | <kbd>RShift</kbd>+<kbd>E</kbd> |
| Squad server visibility | <kbd>RShift</kbd>+<kbd>S</kbd> |
| Testing servers visibility | <kbd>RShift</kbd>+<kbd>T</kbd> |
| Kill streak sound effect | <kbd>RShift</kbd>+<kbd>F</kbd> |
| Clear chat | <kbd>RShift</kbd>+<kbd>Z</kbd> |
| Clear Messages (kills and death log) | <kbd>RShift</kbd>+<kbd>X</kbd> |
| <br /> | |
| Toggle shift to crouch | <kbd>RShift</kbd>+<kbd>C</kbd> |
#### Warning
The order of keystroke matter. For example, pressing <kbd>RShift</kbd>+<kbd>A</kbd> is different from pressing <kbd>A</kbd>+<kbd>RShift</kbd>. This is to prevent situation where <kbd>RShift</kbd>+<kbd>A</kbd> fires when the user intended to press <kbd>LCtrl</kbd>+<kbd>RShift</kbd>+<kbd>A</kbd>.
| Function | Default Shortcut |
| ------------------------------------------ | --------------------------------------------------- |
| Show Menu | <kbd>F1</kbd> |
| <br /> | |
| Move GUI (long press) | <kbd>LCtrl</kbd>+<kbd>LShift</kbd>+<kbd>Arrow</kbd> |
| Move GUI by one pixel | <kbd>LCtrl</kbd>+<kbd>Arrow</kbd> |
| Reset GUI position | <kbd>LCtrl</kbd>+<kbd>R</kbd> |
| <br /> | |
| Toggle All GUI visibility | <kbd>RShift</kbd>+<kbd>A</kbd> |
| Toggle player statistics visibility | <kbd>RShift</kbd>+<kbd>P</kbd> |
| Toggle weapon statistics visibility | <kbd>RShift</kbd>+<kbd>W</kbd> |
| Toggle team statistics visibility | <kbd>RShift</kbd>+<kbd>L</kbd> |
| Toggle kills Elo visibility on leaderboard | <kbd>RShift</kbd>+<kbd>E</kbd> |
| Toggle squad server visibility | <kbd>RShift</kbd>+<kbd>S</kbd> |
| Toggle Testing servers visibility | <kbd>RShift</kbd>+<kbd>T</kbd> |
| Toggle kill streak sound effect | <kbd>RShift</kbd>+<kbd>F</kbd> |
| Clear chat | <kbd>RShift</kbd>+<kbd>Z</kbd> |
| Clear kills and death log | <kbd>RShift</kbd>+<kbd>X</kbd> |
| <br /> | |
| Toggle shift to crouch | <kbd>RShift</kbd>+<kbd>C</kbd> |
## Features
<details>
<summary>A list of all the features in WBM (click to unfold)</summary>
- in-game menu
- reconfigure shortcut keys
- custom shortcut keys
- clear chat
- clear game messages (kills, deaths, missile launch, bomb diffuse, etc.)
- Extended fps limit (5~240 => disabled~1000)
- Extended fps limit (5\~240 => disabled\~1000) (may be buggy)
### in-game overlays
- Tab Leaderboard
- Leaderboard
- show kills Elo
- kills Elo for each player
- Player statistics
@ -189,76 +199,92 @@ The order of keystroke matter. For example, pressing <kbd>RShift</kbd>+<kbd>A</k
### Controls
- Shift to crouch
- Shift to crouch (does not interfere with breath holding)
### Sound effects
- 10 kill streak: "rampage"
- 20 kill streak: "killing spree"
- 30 kill streak: "unstoppable"
- 50 kill streak: "godlike"
- 69 kill streak: "nice"
- 10 kill streak: ["rampage"](./assets/audio/rampage.wav)
- 20 kill streak: ["killing spree"](<./assets/audio/killing spree.wav>)
- 30 kill streak: ["unstoppable"](./assets/audio/unstoppable.wav)
- 50 kill streak: ["godlike"](./assets/audio/godlike.wav)
- 69 kill streak: ["nice"](./assets/audio/nice.wav)
### OBS overlays
- kills and games Elo (size: 355x140)
![Elo overlay](./images/elo.png)
### [OBS overlays](https://github.com/War-Brokers-Mods/WBM-Overlays)
### Etc
- persistent configuration
- kill streak sound effect
- Quickly change settings with keyboard shortcut
- Quickly change settings with keyboard shortcuts
</details>
## Limitations
WBM is not a hack. WBM will not include any features that will give unfair advantage. These features include but not limited to: extended minimap zoom, quick weapon swap, instant zoom, extended field of view, audio filter, etc.
WBM is not a hack.
WBM will not include any features that will give unfair advantages.
These features include but are not limited to:
extended minimap zoom, quick weapon swap, instant zoom, extended field of view, audio filter, etc.
WBM will not include any custom skins. Micro-transaction accounts for a significant portion of the developers' income and WBM will not include any feature that will damage it.
WBM will not include any custom skins.
Micro-transaction accounts for a significant portion of the developers' income,
and WBM will not include any feature that will affect it.
## Building
If you are a casual user, this is completely unnecessary. **This is only recommended for developers.**
If you are a casual user, this is completely unnecessary.
**This is only intended for developers.**
<details>
<summary>Building instructions (click to unfold)</summary>
<br />
The guide is intentionally left incomplete.
To prevent any regular developers from using this mod to develop hacks,
I won't provide any help when it comes to building the mod from scratch.
This guide is only useful to people who's already familiar with reverse engineering,
and can create hacks on their own anyway.
> Assumes that working directory is project root.
1. Install .NET sdk.
2. Clone this repository.
3. Copy all DLL files from `<WB install path>/war_brokers_Data/Managed/` and `<WB install path>/BepInEx/core` to `WBM/dll/`. Create directory if it does not exist.
4. Download [BepInEx configuration manager v16](https://github.com/BepInEx/BepInEx.ConfigurationManager/releases) and put the dll file in `WBM/dll` directory. Other file(s) in the zip file can be deleted.
5. Create `scripts/config.sh`.
2. Copy all DLL files from `<WB install path>/war_brokers_Data/Managed/` and `<WB install path>/BepInEx/core` to `WBM/dll/`. Create directory if it does not exist.
3. Download and unzip [BepInEx configuration manager v16](https://github.com/BepInEx/BepInEx.ConfigurationManager/releases) then copy the dll file to the `WBM/dll` directory.
4. Create `scripts/config.sh`. This will be used to quickly test the mod without having to manually install it.
```bash
#!/bin/bash
WB_PLUGINS_DIR="<PATH_TO_PLUGINS_DIRECTORY_HERE>"
WB_PLUGINS_DIR="<PATH_TO_PLUGIN_INSTALL_DIRECTORY>"
```
5. Install the `zip` cli. Most likely you already have it.
6. Now you can run the scripts.
- `scripts/debug.sh`: Build WBM in debug mode and copy the files to the plugins directory.
- `scripts/release.sh`: Create a zip file that can be uploaded in the gh release section.
- `scripts/debug.sh`: Builds WBM in debug mode and copy the files to the plugins directory.
- `scripts/release.sh`: Creates a zip file that can be uploaded to the gh release section.
</details>
## Bug reports / Suggestions
If you have a cool idea that will make WBM better, or if WBM misbehaves in any way (no matter how minor the problem is), feel free go to the [Issues page](https://github.com/War-Brokers-Mods/WBM/issues) and open a new issue!
## Contributing
- use GH pull request
- use vscode and install [recommended extensions](.vscode/extensions.json). This is required for code formatting.
If you have a cool idea that will make WBM better, or if WBM misbehaves in any way (no matter how minor the problem is), feel free go to the [Issues page](https://github.com/War-Brokers-Mods/WBM/issues) and open a new issue! Alternatively, you can report the bug in my [discord server](https://discord.gg/aQqamSCUcS).
## Special thanks
- [inorganik](https://github.com/inorganik) for [countUp.js](https://github.com/inorganik/countUp.js)
- [l3lackShark](https://github.com/l3lackShark) for [inspiration](https://github.com/l3lackShark/gosumemory)
- [jassper0](https://github.com/jassper0) for [Elo overlay design](https://github.com/l3lackShark/static/tree/master/Simplistic)
- REKT (discord: `REKT#7777`, 710249221609226320) for:
- fps improvement by modifying `boot.config`
- shader rework
- video tutorial
## License
This project is licenced under the [MIT License](https://opensource.org/licenses/MIT).
The source code for this project is available under the [MIT License](https://opensource.org/licenses/MIT).
Fonts:
- https://fonts.google.com/specimen/Architects+Daughter : OFL (used in WBM logo)
</details>

View file

@ -2,84 +2,51 @@ using System.Runtime.Serialization;
namespace WBM
{
public class Data
{
public enum TeamEnum
{
None,
Red,
Blue
}
public class Data
{
public enum TeamEnum
{
None,
Red,
Blue
}
private enum QuestTypeEnum
{
Kill,
Damage,
Package,
Missile,
Capture,
Play,
Travel,
Assist,
Finish
}
public struct PlayerStatsStruct
{
public int kills;
public int deaths;
public int damage;
public int longestKill;
public int points;
public int headShots;
public int vote;
public int mapVote;
public int gamesElo;
public int gamesEloDelta;
public int killsElo;
public int killsEloDelta;
}
public struct PlayerStatsStruct
{
public int kills;
public int deaths;
public int damage;
public int longestKill;
public int points;
public int headShots;
public int vote;
public int mapVote;
public int gamesElo;
public int gamesEloDelta;
public int killsElo;
public int killsEloDelta;
}
public enum GameStateEnum
{
WaitingOnPlayers,
Countdown,
GameInProgress,
Results
}
public enum GameModeEnum
{
DeathMatch,
DemolitionDerby,
ProtectLeader,
ResourceCapture,
Race,
TankBattle,
TankKing,
CapturePoint,
VehicleEscort,
PackageDrop,
ScudLaunch,
BattleRoyale,
Competitive,
LobbyCompetitive,
LobbyBR,
Count
}
[DataContract]
public class SerializableData
{
// game version
// gamemode
// teammate list
// team rank (array of player index)
public enum GameStateEnum
{
WaitingOnPlayers,
Countdown,
GameInProgress,
Results
}
[DataContract]
public class SerializableData
{
// game version
// gamemode
// teammate list
// team rank (array of player index)
[DataMember] public int localPlayerIndex = -1;
[DataMember] public string[] nickList = new string[] { };
[DataMember] public PlayerStatsStruct[] playerStatsArray = new PlayerStatsStruct[] { };
[DataMember] public Data.GameStateEnum gameState;
}
}
[DataMember] public int localPlayerIndex = -1;
[DataMember] public string[] nickList = new string[] { };
[DataMember] public PlayerStatsStruct[] playerStatsArray = new PlayerStatsStruct[] { };
[DataMember] public Data.GameStateEnum gameState;
}
}
}

38
WBM/MangledNames.cs Normal file
View file

@ -0,0 +1,38 @@
/// This file contains all information related to matching
/// mangles names to something more readable
namespace WBM
{
public static class MangledNames
{
//
// Variables
//
public const string AKRifleShotClip = "AJLCLOJGKLF";
public const string SMGShotClip = "GDKKJENDFOF";
// fps limit value
public const string fpsValue = "PFOMGOFNIOE";
public const string showElo = "JEFPGBDBGFF";
// show squad servers
public const string isClan = "GHAAFBAPMMH";
// show testing servers
public const string isTesting = "CIAFOJDAKFA";
public const string chatList = "CBKINJHGBOM";
public const string gameState = "HHBJFNILCBJ";
public const string nickList = "MBFCFOPONAI";
public const string personGun = "FDHBIGANHOH";
public const string localPlayerIndex = "INGKMFAPBJC";
public const string teamList = "GKDEFMOHMGH";
public const string statsList = "GNKKKHEDFAN";
//
// functions
//
public const string drawChatMessage = "IACLHANNPED";
public const string clearMessages = "NFNFPNGMKFD";
public const string onFPSChanged = "EFDAECNGBEP";
public const string addMessage = "GPIKJGHDPEA";
}
}

View file

@ -1,40 +0,0 @@
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
namespace WBM
{
[HarmonyPatch(typeof(webguy))]
[HarmonyPatch("FHBMKCDMGII")]
class FPSSliderPatch
{
private static int defaultTargetFrameRate = -1;
private static int maxTargetFrameRate = 1000;
private static GameObject fpsSliderTextObj = GameObject.Find("fpsSlideFuckText");
private static Slider slider = GameObject.Find("fpsSlider").GetComponent<Slider>();
private static AccessTools.FieldRef<webguy, float> fpsValueRef = AccessTools.FieldRefAccess<webguy, float>("CLLNACDIPHE");
static bool Prefix(webguy __instance, float JKNNNLEEIAO)
{
fpsValueRef(__instance) = JKNNNLEEIAO;
int targetFrameRate = (int)(JKNNNLEEIAO * maxTargetFrameRate);
if (targetFrameRate == 0)
{
((InfernalBehaviour)__instance).KKFJBNFGKEP(fpsSliderTextObj, __instance.HNDAMJPNGAE("Disabled"));
targetFrameRate = defaultTargetFrameRate;
}
else
{
((InfernalBehaviour)__instance).KKFJBNFGKEP(fpsSliderTextObj, targetFrameRate.ToString());
}
if (targetFrameRate > 0 && targetFrameRate < 5) targetFrameRate = 5;
Application.targetFrameRate = targetFrameRate;
return false;
}
}
}

View file

@ -1,16 +0,0 @@
namespace WBM
{
class PrefNames
{
public const string showSquadServer = "showSquadServer";
public const string showTestingServer = "showTestingServer";
public const string GUIOffsetX = "GUIOffsetX";
public const string GUIOffsetY = "GUIOffsetY";
public const string showGUI = "showGUI";
public const string showPlayerStats = "showPlayerStats";
public const string showWeaponStats = "showWeaponStats";
public const string showTeammateStats = "showTeammateStats";
public const string showElo = "showElo";
public const string shiftToCrouch = "shiftToCrouch";
}
}

View file

@ -6,73 +6,74 @@ using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Runtime.Serialization.Json;
using CPersonGun = JABKDMKNMKE;
namespace WBM
{
public class Util
{
public async static Task<AudioClip> fetchAudioClip(string where)
{
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + where, AudioType.WAV))
{
uwr.SendWebRequest();
public class Util
{
public async static Task<AudioClip> fetchAudioClip(string where)
{
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + where, AudioType.WAV))
{
uwr.SendWebRequest();
while (!uwr.isDone) await Task.Delay(10);
while (!uwr.isDone) await Task.Delay(10);
return DownloadHandlerAudioClip.GetContent(uwr);
}
}
return DownloadHandlerAudioClip.GetContent(uwr);
}
}
public static string data2JSON(Data.SerializableData data)
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Data.SerializableData));
public static string data2JSON(Data.SerializableData data)
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Data.SerializableData));
serializer.WriteObject(stream, data);
byte[] json = stream.ToArray();
stream.Close();
serializer.WriteObject(stream, data);
byte[] json = stream.ToArray();
stream.Close();
return Encoding.UTF8.GetString(json, 0, json.Length);
}
return Encoding.UTF8.GetString(json, 0, json.Length);
}
public static string formatKDR(int kills, int deaths)
{
return deaths == 0 ? "inf" : formatDecimal((float)kills / deaths);
}
public static string formatKDR(int kills, int deaths)
{
return deaths == 0 ? "inf" : formatDecimal((float)kills / deaths);
}
public static string formatDecimal(float number)
{
return String.Format("{0:0.0}", number);
}
public static string formatDecimal(float number)
{
return String.Format("{0:0.0}", number);
}
public static float getGunZoom(NGNJNHEFLHB gun)
{
return gun.ADLGCCMDNED;
}
public static float getGunZoom(CPersonGun gun)
{
// CPersonGun.cameraZoom
return gun.IDOOGDDHKOG;
}
public static float getGunFireTimer(NGNJNHEFLHB gun)
{
return gun.MAKBOBOAAHG;
}
public static float getGunFireTimer(CPersonGun gun)
{
// CPersonGun.fireTimer
return gun.ABENIMBBCFL;
}
public static float getGunFireVelocity(NGNJNHEFLHB gun)
{
return gun.HOIKHOJJBOG;
}
public static float getGunFireVelocity(CPersonGun gun)
{
// CPersonGun.fireVel
return gun.EMDMIEBFHDL;
}
public static float getGunFireRate(NGNJNHEFLHB gun)
{
return gun.IHEEIAIOABG;
}
public static float getGunFireRate(CPersonGun gun)
{
// CPersonGun.fireRate
return gun.EDHPPDGFLEB;
}
public static float getGunReloadTimer(NGNJNHEFLHB gun)
{
return gun.NBLDKJAKFIB;
}
public static float getGunCooldownTimer(NGNJNHEFLHB gun)
{
return gun.LBOBALHJBDM;
}
}
public static float getGunReloadTimer(CPersonGun gun)
{
// CPersonGun.reloadTimer
return gun.ALNGHNHLNGP;
}
}
}

View file

@ -1,334 +1,87 @@
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using System;
using System.IO;
namespace WBM
{
[BepInPlugin("com.developomp.wbm", "War Brokers Mods", "1.7.1.0")]
public partial class WBM : BaseUnityPlugin
{
private void Awake()
{
this.harmony = new Harmony("com.developomp.wbm");
this.harmony.PatchAll();
}
/// <summary>
/// Class <c>WBM</c> is a regular unity script component (<c>GameObject</c>).
/// The functions <c>Awake</c>, <c>Start</c>, <c>Update</c>, <c>OnGUI</c>, and <c>onDestroy</c>
/// are event functions that gets called on specific stages of the component's lifecycle.
/// More information can be found in the <see href="https://docs.unity3d.com/Manual/ExecutionOrder.html">unity's documentation page</see>.
/// </summary>
[BepInPlugin(WBM.programID, WBM.programName, WBM.programVersion)]
public partial class WBM : BaseUnityPlugin
{
public const string programID = "com.developomp.wbm";
public const string programName = "War Brokers Mods";
public const string programVersion = "1.14.0.0";
private async void Start()
{
Logger.LogDebug("Initializing");
/// This function is called as soon as the component becomes active.
/// It is the first event function that's called during the component's lifecycle.
private void Awake()
{
Logger.LogDebug("Initializing");
this.webguy = FindObjectOfType<webguy>();
this.initCore();
}
System.Type webguyType = typeof(webguy);
/// This function is called only once before the first frame update.
/// The component is more or less initialized at this point,
/// and it is this function that completes the initialization process.
private async void Start()
{
await this.setupCore();
this.showEloOnLeaderboardRef = webguyType.GetField("KDOBENAOLLF", bindFlags);
this.showSquadServerRef = webguyType.GetField("PHPIBBCFKFI", bindFlags);
this.showTestingServerRef = webguyType.GetField("LHHEGFHLNJE", bindFlags);
this.playerStatsArrayRef = webguyType.GetField("NAFCGDLLFJC", bindFlags);
this.currentAreaRef = webguyType.GetField("FLJLJNLDFAM", bindFlags);
this.teamListRef = webguyType.GetField("MNEJLPDLMBH", bindFlags);
this.localPlayerIndexRef = webguyType.GetField("ALEJJPEPFOG", bindFlags);
this.personGunRef = webguyType.GetField("IEGLIMLBDPH", bindFlags);
this.nickListRef = webguyType.GetField("CLLDJOMEKIP", bindFlags);
this.gameStateRef = webguyType.GetField("MCGMEPGBCKK", bindFlags);
this.chatListRef = webguyType.GetField("MOOBJBOCANE", bindFlags);
this.setupOldGunSound();
this.setupWSSever();
this.setupClearChat();
this.setupShiftToCrouch();
this.setupShowEloOnLeaderBoard();
this.setupShowSquadServer();
this.setupShowTestingServer();
this.setupKillStreakSFX();
this.addMessageFuncRef = webguyType.GetMethod("NBPKLIOLLEI", bindFlags);
this.clearMessagesFuncRef = webguyType.GetMethod("IOCHBBACKFA", bindFlags);
this.drawChatMessageFuncRef = webguyType.GetMethod("EBDKFEJMEMB", bindFlags);
StartCoroutine(UpdateValuesFunction());
this.oldGunSoundRef = webguyType.GetField("PINGEJAHHDI", bindFlags);
this.AKSoundRef = webguyType.GetField("BJFBGCMEELH", bindFlags);
this.SMGSoundRef = webguyType.GetField("HKDDIMFIHCE", bindFlags);
Logger.LogDebug("Ready!");
}
// Configurations
this.showGUI = Config.Bind("Config", "show GUI", true);
this.showGUIShortcut = Config.Bind("Hotkeys", "show GUI Shortcut", new KeyboardShortcut(KeyCode.A, KeyCode.RightShift));
/// This function is called on each frame.
private void Update()
{
this.doCore();
this.GUIOffsetX = Config.Bind("Config", "GUI Horizontal position", 38, new ConfigDescription("WBM GUI Horizontal position", new AcceptableValueRange<int>(0, Screen.width)));
this.GUIOffsetY = Config.Bind("Config", "GUI Vertical position", 325, new ConfigDescription("WBM GUI Vertical position", new AcceptableValueRange<int>(0, Screen.height)));
this.resetGUIShortcut = Config.Bind("Hotkeys", "reset GUI position", new KeyboardShortcut(KeyCode.R, KeyCode.LeftControl));
this.doKillStreakSFX();
this.doPlayerStats();
this.doWeaponStats();
this.doTeamStats();
this.doLeaderboardElo();
this.doShowSquadServer();
this.doTestingServer();
this.doClearChat();
this.doclearMessage();
this.doShiftToCrouch();
}
this.shiftToCrouch = Config.Bind("Config", "shift to crouch", true);
this.shiftToCrouchShortcut = Config.Bind("Hotkeys", "shift to crouch", new KeyboardShortcut(KeyCode.C, KeyCode.RightShift));
/// Called multiple times per frame in response to GUI events.
/// The Layout and Repaint events are processed first,
/// followed by a Layout and keyboard/mouse event for each input event.
private void OnGUI()
{
this.drawCoreUI();
this.killStreakSFX = Config.Bind("Config", "kill streak sound effect", true);
this.killStreakSFXShortcut = Config.Bind("Hotkeys", "kill streak sound effect", new KeyboardShortcut(KeyCode.F, KeyCode.RightShift));
// don't draw if player is not in a games
if (this.data.localPlayerIndex < 0) return;
this.showPlayerStats = Config.Bind("Config", "show player statistics", true);
this.showPlayerStatsShortcut = Config.Bind("Hotkeys", "show player statistics", new KeyboardShortcut(KeyCode.P, KeyCode.RightShift));
this.drawPlayerStats();
this.drawWeaponStats();
this.drawTeamStats();
}
this.showWeaponStats = Config.Bind("Config", "show weapon statistics", true);
this.showWeaponStatsShortcut = Config.Bind("Hotkeys", "show weapon statistics", new KeyboardShortcut(KeyCode.W, KeyCode.RightShift));
this.showTeamStats = Config.Bind("Config", "show team statistics", true);
this.showTeamStatsShortcut = Config.Bind("Hotkeys", "show team statistics", new KeyboardShortcut(KeyCode.L, KeyCode.RightShift));
this.showEloOnLeaderboard = Config.Bind("Config", "show Elo on leaderboard", true);
this.showEloOnLeaderboard.SettingChanged += this.showEloOnLeaderboardChanged;
this.showEloOnLeaderboardShortcut = Config.Bind("Hotkeys", "show Elo on leaderboard", new KeyboardShortcut(KeyCode.E, KeyCode.RightShift));
this.showEloOnLeaderboardRaw = this.showEloOnLeaderboard.Value;
this.showSquadServer = Config.Bind("Config", "show squad server", true);
this.showSquadServer.SettingChanged += this.showSquadServerChanged;
this.showSquadServerShortcut = Config.Bind("Hotkeys", "show squad server", new KeyboardShortcut(KeyCode.S, KeyCode.RightShift));
this.showSquadServerRaw = this.showSquadServer.Value;
this.showTestingServer = Config.Bind("Config", "show testing server", true);
this.showTestingServer.SettingChanged += this.showTestingServerChanged;
this.showTestingServerShortcut = Config.Bind("Hotkeys", "show testing server", new KeyboardShortcut(KeyCode.T, KeyCode.RightShift));
this.showTestingServerRaw = this.showTestingServer.Value;
this.clearChatShortcut = Config.Bind("Hotkeys", "clear chat", new KeyboardShortcut(KeyCode.Z, KeyCode.RightShift));
this.clearDeathLogShortcut = Config.Bind("Hotkeys", "clear messages", new KeyboardShortcut(KeyCode.X, KeyCode.RightShift));
this.useOldGunSoundConf = Config.Bind("Config", "use old gun sound", true);
this.useOldGunSoundConf.SettingChanged += this.useOldGunSoundChanged;
// Audio
this.killStreakAudioSource = this.gameObject.AddComponent<AudioSource>();
if (!Directory.Exists(this.audioPath))
{
Logger.LogError($"Directory {this.audioPath} does not exist. Aborting!");
GameObject.Destroy(this);
}
foreach (string fileName in Directory.GetFiles(this.audioPath))
{
Logger.LogDebug("Loading AudioClip " + Path.GetFileNameWithoutExtension(fileName));
this.AudioDict.Add(
Path.GetFileNameWithoutExtension(fileName),
await Util.fetchAudioClip(Path.Combine(this.audioPath, fileName))
);
}
this.oldGunSound = this.oldGunSoundRaw;
this.newAKSound = this.AKSoundRaw.ADCOCHNNCHM;
this.newSMGSound = this.SMGSoundRaw.ADCOCHNNCHM;
// Websocket
server = new WebSocketSharp.Server.WebSocketServer($"ws://127.0.0.1:{this.serverPort}");
server.AddWebSocketService<WSJSONService>("/json");
server.Start();
StartCoroutine(UpdateValuesFunction());
// Final tasks
this.useOldGunSoundChanged(new object(), new EventArgs());
Logger.LogDebug("Ready!");
}
private void Update()
{
// Move UI
if (Input.GetKey(KeyCode.LeftControl))
{
// move GUI
if (Input.GetKey(KeyCode.LeftShift))
{
if (Input.GetKey(KeyCode.UpArrow)) this.GUIOffsetY.Value -= 1;
if (Input.GetKey(KeyCode.DownArrow)) this.GUIOffsetY.Value += 1;
if (Input.GetKey(KeyCode.LeftArrow)) this.GUIOffsetX.Value -= 1;
if (Input.GetKey(KeyCode.RightArrow)) this.GUIOffsetX.Value += 1;
}
else
{
if (Input.GetKeyDown(KeyCode.UpArrow)) this.GUIOffsetY.Value -= 1;
if (Input.GetKeyDown(KeyCode.DownArrow)) this.GUIOffsetY.Value += 1;
if (Input.GetKeyDown(KeyCode.LeftArrow)) this.GUIOffsetX.Value -= 1;
if (Input.GetKeyDown(KeyCode.RightArrow)) this.GUIOffsetX.Value += 1;
}
}
// reset GUI position
if (this.resetGUIShortcut.Value.IsDown())
{
this.GUIOffsetX.Value = (int)this.GUIOffsetX.DefaultValue;
this.GUIOffsetY.Value = (int)this.GUIOffsetY.DefaultValue;
}
if (this.showGUIShortcut.Value.IsDown()) this.showGUI.Value = !this.showGUI.Value;
if (this.shiftToCrouchShortcut.Value.IsDown()) this.shiftToCrouch.Value = !this.shiftToCrouch.Value;
if (this.killStreakSFXShortcut.Value.IsDown()) this.killStreakSFX.Value = !this.killStreakSFX.Value;
if (this.showPlayerStatsShortcut.Value.IsDown()) this.showPlayerStats.Value = !this.showPlayerStats.Value;
if (this.showWeaponStatsShortcut.Value.IsDown()) this.showWeaponStats.Value = !this.showWeaponStats.Value;
if (this.showTeamStatsShortcut.Value.IsDown()) this.showTeamStats.Value = !this.showTeamStats.Value;
if (this.showEloOnLeaderboardShortcut.Value.IsDown()) this.showEloOnLeaderboard.Value = !this.showEloOnLeaderboard.Value;
if (this.showSquadServerShortcut.Value.IsDown()) this.showSquadServer.Value = !this.showSquadServer.Value;
if (this.showTestingServerShortcut.Value.IsDown()) this.showTestingServer.Value = !this.showTestingServer.Value;
if (this.clearChatShortcut.Value.IsDown()) this.clearChat();
if (this.clearDeathLogShortcut.Value.IsDown()) this.clearMessagesFuncRef.Invoke(this.webguy, new object[] { });
// config visibility
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightShift)) this._showConfig = true;
if (!Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightShift)) this._showConfig = false;
// only if right buttton is not held
if (this.shiftToCrouch.Value && !Input.GetMouseButton(1))
{
if (Input.GetKeyDown(KeyCode.LeftShift)) OMOJPGNNKFN.NEELEHFDKBP.EGACOOOGDDC = true;
if (Input.GetKeyUp(KeyCode.LeftShift)) OMOJPGNNKFN.NEELEHFDKBP.EGACOOOGDDC = false;
}
}
private void OnGUI()
{
GUI.skin.box.fontSize = 15;
GUI.skin.label.fontSize = 15;
GUI.skin.label.wordWrap = false;
if (this._showConfig)
{
GUI.Box(
new Rect(Screen.width - 370, 60, 360, 370), $@"Configuration
move GUI: LCtrl+LShift+Arrow
move GUI by pixel: LCtrl+Arrow
reset GUI position: {this.resetGUIShortcut.Value}
clear chat: {this.clearChatShortcut.Value}
clear death log: {this.clearDeathLogShortcut.Value}
GUI X offset: {this.GUIOffsetX.Value}
GUI Y offset: {this.GUIOffsetY.Value}
Show WBM GUI: {this.showGUI.Value} ({this.showGUIShortcut.Value})
Show Elo on leaderboard: {this.showEloOnLeaderboard.Value} ({this.showEloOnLeaderboardShortcut.Value})
Show player stats: {this.showPlayerStats.Value} ({this.showPlayerStatsShortcut.Value})
Show weapon stats: {this.showWeaponStats.Value} ({this.showWeaponStatsShortcut.Value})
Show teammate stats: {this.showTeamStats.Value} ({this.showTeamStatsShortcut.Value})
show squad server: {this.showSquadServer.Value} ({this.showSquadServerShortcut.Value})
show testing server: {this.showTestingServer.Value} ({this.showTestingServerShortcut.Value})
shift to crouch: {this.shiftToCrouch.Value} ({this.shiftToCrouchShortcut.Value})
kill streak SFX: {this.killStreakSFX.Value} ({this.killStreakSFXShortcut.Value})"
);
}
if (!this.showGUI.Value) return;
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value, 220, 60),
@"War Brokers Mods
Made by [LP] POMP
v1.7.1.0"
);
if (this.data.localPlayerIndex >= 0)
{
if (this.showPlayerStats.Value)
{
try
{
string killsEloDeltaSign = this.myPlayerStats.killsEloDelta >= 0 ? "+" : "";
string gamesEloDeltaSign = this.myPlayerStats.gamesEloDelta >= 0 ? "+" : "";
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value + 65, 220, 180),
$@"Player stats
KDR: {Util.formatKDR(this.myPlayerStats.kills, this.myPlayerStats.deaths)}
kills Elo: {this.myPlayerStats.killsElo} {killsEloDeltaSign}{Util.formatDecimal((float)this.myPlayerStats.killsEloDelta / 10)}
games Elo: {this.myPlayerStats.gamesElo} {gamesEloDeltaSign}{Util.formatDecimal((float)this.myPlayerStats.gamesEloDelta / 10)}
Damage dealt: {this.myPlayerStats.damage}
Longest Kill: {this.myPlayerStats.longestKill}m
Points: {this.myPlayerStats.points}
Headshots: {this.myPlayerStats.headShots}
Kill streak: {this.killStreak}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
if (this.showWeaponStats.Value)
{
try
{
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value + 250, 230, 130),
$@"Weapon stats
fire Timer: {String.Format("{0:0.00}", Util.getGunFireTimer(this.personGun))}s (max: {String.Format("{0:0.00}", Util.getGunFireRate(this.personGun))}s)
reload Timer: {Util.getGunReloadTimer(this.personGun)}
cooldown Timer: {Util.getGunCooldownTimer(this.personGun)}
speed: {Util.getGunFireVelocity(this.personGun)}
zoom: {Util.getGunZoom(this.personGun)}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
if (this.showTeamStats.Value)
{
try
{
string teamNames = "Nickname\n\n";
string teamKDR = "KDR\n\n";
string teamPoints = "pts\n\n";
string teamDamage = "Damage\n\n";
int teamTotalKills = 0;
int teamTotalDeaths = 0;
int teamTotalDamage = 0;
for (int i = 0; i < this.data.playerStatsArray.Length; i++)
{
Data.PlayerStatsStruct stat = this.data.playerStatsArray[i];
// if player is not a bot and if player is in my team
if ((stat.killsElo != 0) && (this.teamList[i] == this.myTeam))
{
teamNames += $"{this.data.nickList[i]}\n";
teamKDR += $"{Util.formatKDR(stat.kills, stat.deaths)}\n";
teamPoints += $"{stat.points}\n";
teamDamage += $"{stat.damage}\n";
teamTotalKills += stat.kills;
teamTotalDeaths += stat.deaths;
teamTotalDamage += stat.damage;
}
}
int teamStatOffset = (this.data.gameState == Data.GameStateEnum.Results) ? 280 : 0;
GUI.Box(new Rect(Screen.width - 320, 445 + teamStatOffset, 300, 270), "Team Stats");
GUI.Label(new Rect(Screen.width - 315, 470 + teamStatOffset, 105, 190), teamNames);
GUI.Label(new Rect(Screen.width - 200, 470 + teamStatOffset, 40, 190), teamKDR);
GUI.Label(new Rect(Screen.width - 150, 470 + teamStatOffset, 40, 190), teamPoints);
GUI.Label(new Rect(Screen.width - 100, 470 + teamStatOffset, 70, 190), teamDamage);
GUI.Label(
new Rect(Screen.width - 315, 655 + teamStatOffset, 300, 55),
$@"total damage: {teamTotalDamage}
total deaths: {teamTotalDeaths}
total kills: {teamTotalKills}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
}
}
private void onDestroy()
{
this.server.Stop();
}
}
/// This function is called after the component has been disabled and is ready to be destroyed.
/// It is the last event function that's called during the component's lifecycle.
private void onDestroy()
{
this.destroyWSSever();
}
}
}

View file

@ -1,360 +0,0 @@
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
namespace WBM
{
public partial class WBM
{
// important boy
private webguy webguy;
private Harmony harmony;
private IEnumerator UpdateValues;
// websocket data stuff
private WebSocketSharp.Server.WebSocketServer server;
private ushort serverPort = 24601;
private Data.SerializableData data = new Data.SerializableData();
// internal or temporary
private bool _showConfig;
// Configurations
private ConfigEntry<bool> showGUI;
private ConfigEntry<KeyboardShortcut> showGUIShortcut;
private ConfigEntry<int> GUIOffsetX;
private ConfigEntry<int> GUIOffsetY;
private ConfigEntry<KeyboardShortcut> resetGUIShortcut;
private ConfigEntry<bool> shiftToCrouch;
private ConfigEntry<KeyboardShortcut> shiftToCrouchShortcut;
private ConfigEntry<bool> killStreakSFX;
private ConfigEntry<KeyboardShortcut> killStreakSFXShortcut;
private ConfigEntry<bool> showPlayerStats;
private ConfigEntry<KeyboardShortcut> showPlayerStatsShortcut;
private ConfigEntry<bool> showWeaponStats;
private ConfigEntry<KeyboardShortcut> showWeaponStatsShortcut;
private ConfigEntry<bool> showTeamStats;
private ConfigEntry<KeyboardShortcut> showTeamStatsShortcut;
private ConfigEntry<bool> showEloOnLeaderboard;
private void showEloOnLeaderboardChanged(object sender, EventArgs e)
{
this.showEloOnLeaderboardRaw = this.showEloOnLeaderboard.Value;
}
private ConfigEntry<KeyboardShortcut> showEloOnLeaderboardShortcut;
private ConfigEntry<bool> showSquadServer;
private void showSquadServerChanged(object sender, EventArgs e)
{
this.showSquadServerRaw = this.showSquadServer.Value;
}
private ConfigEntry<KeyboardShortcut> showSquadServerShortcut;
private ConfigEntry<bool> showTestingServer;
private void showTestingServerChanged(object sender, EventArgs e)
{
this.showTestingServerRaw = this.showTestingServer.Value;
}
private ConfigEntry<KeyboardShortcut> showTestingServerShortcut;
private ConfigEntry<KeyboardShortcut> clearChatShortcut;
private ConfigEntry<KeyboardShortcut> clearDeathLogShortcut;
private ConfigEntry<bool> useOldGunSoundConf;
private void useOldGunSoundChanged(object sender, EventArgs e)
{
if (this.useOldGunSoundConf.Value)
{
this.AKSoundRaw.ADCOCHNNCHM = this.oldGunSound;
this.SMGSoundRaw.ADCOCHNNCHM = this.oldGunSound;
}
else
{
this.AKSoundRaw.ADCOCHNNCHM = this.newAKSound;
this.SMGSoundRaw.ADCOCHNNCHM = this.newSMGSound;
}
}
// Audio
private AudioClip oldGunSound;
private AudioClip newAKSound;
private AudioClip newSMGSound;
private Dictionary<string, AudioClip> AudioDict = new Dictionary<string, AudioClip>();
private string audioPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "assets/audio");
private AudioSource killStreakAudioSource;
private Dictionary<int, string> killStreakSFXDictionary = new Dictionary<int, string>()
{
{10, "rampage"},
{20, "killing spree"},
{30, "unstoppable"},
{50, "godlike"},
{69, "nice"},
};
// memory stuff
private static BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
private FieldInfo showEloOnLeaderboardRef;
private bool showEloOnLeaderboardRaw
{
get
{
return (bool)this.showEloOnLeaderboardRef.GetValue(this.webguy);
}
set
{
this.showEloOnLeaderboardRef.SetValue(this.webguy, value);
}
}
private FieldInfo showSquadServerRef;
private bool showSquadServerRaw
{
get
{
return (bool)this.showSquadServerRef.GetValue(this.webguy);
}
set
{
this.showSquadServerRef.SetValue(this.webguy, value);
}
}
private FieldInfo showTestingServerRef;
private bool showTestingServerRaw
{
get
{
return (bool)this.showTestingServerRef.GetValue(this.webguy);
}
set
{
this.showTestingServerRef.SetValue(this.webguy, value);
}
}
private FieldInfo playerStatsArrayRef;
private Data.PlayerStatsStruct[] playerStatsArrayRaw
{
get
{
PDEMAFHPNBD[] rawPlayerStatsArray = (PDEMAFHPNBD[])this.playerStatsArrayRef.GetValue(this.webguy);
Data.PlayerStatsStruct[] result = new Data.PlayerStatsStruct[rawPlayerStatsArray.Length];
for (int i = 0; i < rawPlayerStatsArray.Length; i++)
{
PDEMAFHPNBD currentlyParsing = rawPlayerStatsArray[i];
result[i] = new Data.PlayerStatsStruct
{
kills = currentlyParsing.CFMGCOGACPA,
deaths = currentlyParsing.GABHLIIJHBJ,
damage = currentlyParsing.CECNBFABADA,
longestKill = currentlyParsing.GDFIBEEKMJA,
points = currentlyParsing.HNHFAABONHO,
headShots = currentlyParsing.GJLLOFLEHHD,
vote = currentlyParsing.JCBAKMONPGC,
mapVote = currentlyParsing.BOFANBBCNOH,
gamesElo = currentlyParsing.IBHFIBAOKCB,
gamesEloDelta = currentlyParsing.JMGOHGIGLPI,
killsElo = currentlyParsing.GBIABKEEFOC,
killsEloDelta = currentlyParsing.JAAKOCPIGJL,
};
}
return result;
}
}
private Data.PlayerStatsStruct myPlayerStats;
private int prevDeaths = 0;
private int prevKills = 0;
private int killCountBeforeDeath = 0;
private int killStreak = 0;
private FieldInfo currentAreaRef;
private int currentAreaRaw
{
get
{
return (int)this.currentAreaRef.GetValue(this.webguy);
}
}
private FieldInfo teamListRef;
private Data.TeamEnum[] teamListRaw
{
get
{
return (Data.TeamEnum[])this.teamListRef.GetValue(this.webguy);
}
}
private Data.TeamEnum[] teamList;
private Data.TeamEnum myTeam;
private FieldInfo localPlayerIndexRef;
private int localPlayerIndexRaw
{
get
{
return (int)this.localPlayerIndexRef.GetValue(this.webguy);
}
}
private FieldInfo personGunRef;
private NGNJNHEFLHB personGunRaw
{
get
{
return (NGNJNHEFLHB)this.personGunRef.GetValue(this.webguy);
}
}
private NGNJNHEFLHB personGun;
private FieldInfo nickListRef;
private string[] nickListRaw
{
get
{
return (string[])this.nickListRef.GetValue(this.webguy);
}
}
private FieldInfo gameStateRef;
private Data.GameStateEnum gameStateRaw
{
get
{
return (Data.GameStateEnum)this.gameStateRef.GetValue(this.webguy);
}
}
private FieldInfo chatListRef;
private string[] chatListRaw
{
get
{
return (string[])this.chatListRef.GetValue(this.webguy);
}
set
{
this.chatListRef.SetValue(this.webguy, value);
}
}
private FieldInfo oldGunSoundRef;
private AudioClip oldGunSoundRaw
{
get
{
return ((LPJKBALIFCC)this.oldGunSoundRef.GetValue(this.webguy)).ADCOCHNNCHM;
}
}
private FieldInfo AKSoundRef;
private LPJKBALIFCC AKSoundRaw
{
get
{
return (LPJKBALIFCC)this.AKSoundRef.GetValue(this.webguy);
}
set
{
this.AKSoundRef.SetValue(this.webguy, value);
}
}
private FieldInfo SMGSoundRef;
private LPJKBALIFCC SMGSoundRaw
{
get
{
return (LPJKBALIFCC)this.SMGSoundRef.GetValue(this.webguy);
}
set
{
this.SMGSoundRef.SetValue(this.webguy, value);
}
}
// Methods
private MethodInfo addMessageFuncRef;
private MethodInfo clearMessagesFuncRef;
private MethodInfo drawChatMessageFuncRef;
private IEnumerator UpdateValuesFunction()
{
try
{
this.data.localPlayerIndex = this.localPlayerIndexRaw;
if (this.data.localPlayerIndex >= 0)
{
this.data.playerStatsArray = this.playerStatsArrayRaw;
this.myPlayerStats = this.data.playerStatsArray[this.data.localPlayerIndex];
this.teamList = this.teamListRaw;
this.myTeam = this.teamList[this.data.localPlayerIndex];
this.personGun = this.personGunRaw;
this.data.nickList = this.nickListRaw;
this.data.gameState = this.gameStateRaw;
// check if deaths has changed since the last value update
if (this.prevDeaths == this.myPlayerStats.deaths)
{
this.killStreak = this.myPlayerStats.kills - this.killCountBeforeDeath;
if (this.prevKills != this.myPlayerStats.kills)
{
if (this.killStreakSFX.Value && this.killStreakSFXDictionary.ContainsKey(this.killStreak))
{
this.killStreakAudioSource.clip = this.AudioDict[this.killStreakSFXDictionary[this.killStreak]];
this.killStreakAudioSource.Play();
this.addMessageFuncRef.Invoke(this.webguy, new object[] { $"You are on a {this.killStreak} kill streak", -1 });
}
}
}
else
{
// reset kill streak when death count changes
this.killCountBeforeDeath = this.myPlayerStats.kills;
this.prevDeaths = this.myPlayerStats.deaths;
this.killStreak = 0;
}
this.prevKills = this.myPlayerStats.kills;
}
this.server.WebSocketServices["/json"].Sessions.Broadcast(Util.data2JSON(data));
}
catch (Exception e)
{
Logger.LogError(e);
}
yield return new WaitForSeconds(0.1f);
this.UpdateValues = UpdateValuesFunction();
StartCoroutine(this.UpdateValues);
}
private void clearChat()
{
Logger.LogDebug($"clear1 {chatListRaw.Length}");
for (int i = 0; i < this.chatListRaw.Length; i++) this.chatListRaw[i] = string.Empty;
this.drawChatMessageFuncRef.Invoke(this.webguy, new object[] { "" });
}
}
}

View file

@ -1,6 +0,0 @@
namespace WBM
{
public class WSJSONService : WebSocketSharp.Server.WebSocketBehavior
{
}
}

0
WBM/features/BRStats.cs Normal file
View file

26
WBM/features/WSServer.cs Normal file
View file

@ -0,0 +1,26 @@
namespace WBM
{
public partial class WBM
{
private WebSocketSharp.Server.WebSocketServer server;
private ushort serverPort = 24601;
private Data.SerializableData data = new Data.SerializableData();
private void setupWSSever()
{
this.server = new WebSocketSharp.Server.WebSocketServer($"ws://127.0.0.1:{this.serverPort}");
this.server.AddWebSocketService<WSService>("/json");
this.server.Start();
}
private void destroyWSSever()
{
// properly stop websocket server
this.server.Stop();
}
}
public class WSService : WebSocketSharp.Server.WebSocketBehavior
{
}
}

32
WBM/features/clearChat.cs Normal file
View file

@ -0,0 +1,32 @@
using BepInEx.Configuration;
using UnityEngine;
using System.Reflection;
namespace WBM
{
partial class WBM
{
private MethodInfo drawChatMessageFuncRef;
private ConfigEntry<KeyboardShortcut> clearChatShortcut;
private void setupClearChat()
{
this.drawChatMessageFuncRef = webguyType.GetMethod(MangledNames.drawChatMessage, bindFlags);
this.clearChatShortcut = Config.Bind("Hotkeys", "clear chat", new KeyboardShortcut(KeyCode.Z, KeyCode.RightShift));
}
private void doClearChat()
{
if (this.clearChatShortcut.Value.IsDown()) this.clearChat();
}
private void clearChat()
{
for (int i = 0; i < this.chatListRaw.Length; i++) this.chatListRaw[i] = string.Empty;
this.drawChatMessageFuncRef.Invoke(this.webguy, new object[] { "" });
}
}
}

View file

@ -0,0 +1,23 @@
using BepInEx.Configuration;
using System.Reflection;
namespace WBM
{
partial class WBM
{
private ConfigEntry<KeyboardShortcut> clearDeathLogShortcut;
private MethodInfo clearMessagesFuncRef;
private void setupClearMessage()
{
this.clearMessagesFuncRef = webguyType.GetMethod(MangledNames.clearMessages, bindFlags);
}
private void doclearMessage()
{
if (this.clearDeathLogShortcut.Value.IsDown()) this.clearMessagesFuncRef.Invoke(this.webguy, new object[] { });
}
}
}

281
WBM/features/core/core.cs Normal file
View file

@ -0,0 +1,281 @@
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using CPersonGun = JABKDMKNMKE;
using SPlayerStats = INPDBACNIGK;
namespace WBM
{
partial class WBM
{
private webguy webguy;
private System.Type webguyType;
private Harmony harmony;
private IEnumerator UpdateValues;
//
// internal or temporary
//
private bool _showConfig;
//
// memory stuff
//
private static BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
//
// Methods
//
private MethodInfo addMessageFuncRef;
private IEnumerator UpdateValuesFunction()
{
try
{
this.data.localPlayerIndex = this.localPlayerIndexRaw;
if (this.data.localPlayerIndex >= 0)
{
this.data.playerStatsArray = this.playerStatsArrayRaw;
this.myPlayerStats = this.data.playerStatsArray[this.data.localPlayerIndex];
this.teamList = this.teamListRaw;
this.myTeam = this.teamList[this.data.localPlayerIndex];
this.personGun = this.personGunRaw;
this.data.nickList = this.nickListRaw;
this.data.gameState = this.gameStateRaw;
// check if deaths has changed since the last value update
if (this.prevDeaths == this.myPlayerStats.deaths)
{
this.killStreak = this.myPlayerStats.kills - this.killCountBeforeDeath;
if (this.prevKills != this.myPlayerStats.kills)
{
if (this.killStreakSFX.Value && this.killStreakSFXDictionary.ContainsKey(this.killStreak))
{
this.killStreakAudioSource.clip = this.AudioDict[this.killStreakSFXDictionary[this.killStreak]];
this.killStreakAudioSource.Play();
this.addMessageFuncRef.Invoke(this.webguy, new object[] { $"You are on a {this.killStreak} kill streak", -1 });
}
}
}
else
{
// reset kill streak when death count changes
this.killCountBeforeDeath = this.myPlayerStats.kills;
this.prevDeaths = this.myPlayerStats.deaths;
this.killStreak = 0;
}
this.prevKills = this.myPlayerStats.kills;
}
this.server.WebSocketServices["/json"].Sessions.Broadcast(Util.data2JSON(data));
}
catch (Exception e)
{
Logger.LogError(e);
}
yield return new WaitForSeconds(0.1f);
this.UpdateValues = UpdateValuesFunction();
StartCoroutine(this.UpdateValues);
}
private FieldInfo playerStatsArrayRef;
private Data.PlayerStatsStruct[] playerStatsArrayRaw
{
get
{
SPlayerStats[] rawPlayerStatsArray = (SPlayerStats[])this.playerStatsArrayRef.GetValue(this.webguy);
Data.PlayerStatsStruct[] result = new Data.PlayerStatsStruct[rawPlayerStatsArray.Length];
for (int i = 0; i < rawPlayerStatsArray.Length; i++)
{
SPlayerStats currentlyParsing = rawPlayerStatsArray[i];
result[i] = new Data.PlayerStatsStruct
{
kills = currentlyParsing.JJEIOHLJMHO,
deaths = currentlyParsing.CADBJPEGEAL,
damage = currentlyParsing.MBNBFDFDBAN,
longestKill = currentlyParsing.FNOCIFHHINH,
points = currentlyParsing.AIDBBHHNCAK,
headShots = currentlyParsing.FJPBIMILEPN,
vote = currentlyParsing.ILNFHPIOPCI,
mapVote = currentlyParsing.DPMNDAMAHML,
gamesElo = currentlyParsing.OPMKKKJPDON,
gamesEloDelta = currentlyParsing.BIFCAPOBMIO,
killsElo = currentlyParsing.ICIBGMLJNHJ,
killsEloDelta = currentlyParsing.ONICDMLDBFL,
};
}
return result;
}
}
private Data.PlayerStatsStruct myPlayerStats;
private int prevDeaths = 0;
private int prevKills = 0;
private int killCountBeforeDeath = 0;
private FieldInfo teamListRef;
private Data.TeamEnum[] teamListRaw
{
get
{
return (Data.TeamEnum[])this.teamListRef.GetValue(this.webguy);
}
}
private Data.TeamEnum[] teamList;
private Data.TeamEnum myTeam;
private FieldInfo localPlayerIndexRef;
private int localPlayerIndexRaw
{
get
{
return (int)this.localPlayerIndexRef.GetValue(this.webguy);
}
}
private FieldInfo personGunRef;
private CPersonGun personGunRaw
{
get
{
return (CPersonGun)this.personGunRef.GetValue(this.webguy);
}
}
private CPersonGun personGun;
private FieldInfo nickListRef;
private string[] nickListRaw
{
get
{
return (string[])this.nickListRef.GetValue(this.webguy);
}
}
private FieldInfo gameStateRef;
private Data.GameStateEnum gameStateRaw
{
get
{
return (Data.GameStateEnum)this.gameStateRef.GetValue(this.webguy);
}
}
private FieldInfo chatListRef;
private string[] chatListRaw
{
get
{
return (string[])this.chatListRef.GetValue(this.webguy);
}
set
{
this.chatListRef.SetValue(this.webguy, value);
}
}
//
// Audio
//
private Dictionary<string, AudioClip> AudioDict = new Dictionary<string, AudioClip>();
private string audioPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "assets/audio");
private void initCore()
{
this.harmony = new Harmony(WBM.programID);
this.harmony.PatchAll();
}
private async System.Threading.Tasks.Task setupCore()
{
this.webguy = FindObjectOfType<webguy>();
this.webguyType = typeof(webguy);
//
// References
//
this.playerStatsArrayRef = webguyType.GetField(MangledNames.statsList, bindFlags);
this.teamListRef = webguyType.GetField(MangledNames.teamList, bindFlags);
this.localPlayerIndexRef = webguyType.GetField(MangledNames.localPlayerIndex, bindFlags);
this.personGunRef = webguyType.GetField(MangledNames.personGun, bindFlags);
this.nickListRef = webguyType.GetField(MangledNames.nickList, bindFlags);
this.gameStateRef = webguyType.GetField(MangledNames.gameState, bindFlags);
this.chatListRef = webguyType.GetField(MangledNames.chatList, bindFlags);
this.addMessageFuncRef = webguyType.GetMethod(MangledNames.addMessage, bindFlags);
//
// Configurations
//
this.showGUI = Config.Bind("Config", "show GUI", true);
this.showGUIShortcut = Config.Bind("Hotkeys", "show GUI Shortcut", new KeyboardShortcut(KeyCode.A, KeyCode.RightShift));
this.GUIOffsetX = Config.Bind("Config", "GUI Horizontal position", 38, new ConfigDescription("WBM GUI Horizontal position", new AcceptableValueRange<int>(0, Screen.width)));
this.GUIOffsetY = Config.Bind("Config", "GUI Vertical position", 325, new ConfigDescription("WBM GUI Vertical position", new AcceptableValueRange<int>(0, Screen.height)));
this.resetGUIShortcut = Config.Bind("Hotkeys", "reset GUI position", new KeyboardShortcut(KeyCode.R, KeyCode.LeftControl));
this.showPlayerStats = Config.Bind("Config", "show player statistics", true);
this.showPlayerStatsShortcut = Config.Bind("Hotkeys", "show player statistics", new KeyboardShortcut(KeyCode.P, KeyCode.RightShift));
this.showWeaponStats = Config.Bind("Config", "show weapon statistics", true);
this.showWeaponStatsShortcut = Config.Bind("Hotkeys", "show weapon statistics", new KeyboardShortcut(KeyCode.W, KeyCode.RightShift));
this.showTeamStats = Config.Bind("Config", "show team statistics", true);
this.showTeamStatsShortcut = Config.Bind("Hotkeys", "show team statistics", new KeyboardShortcut(KeyCode.L, KeyCode.RightShift));
this.clearDeathLogShortcut = Config.Bind("Hotkeys", "clear messages", new KeyboardShortcut(KeyCode.X, KeyCode.RightShift));
//
// Audio
//
this.killStreakAudioSource = this.gameObject.AddComponent<AudioSource>();
if (!Directory.Exists(this.audioPath))
{
Logger.LogError($"Directory {this.audioPath} does not exist. Aborting!");
GameObject.Destroy(this);
}
foreach (string fileName in Directory.GetFiles(this.audioPath))
{
Logger.LogDebug("Loading AudioClip " + Path.GetFileNameWithoutExtension(fileName));
this.AudioDict.Add(
Path.GetFileNameWithoutExtension(fileName),
await Util.fetchAudioClip(Path.Combine(this.audioPath, fileName))
);
}
}
private void doCore()
{
this.moveUIOnKeyPress();
this.resetUIOnKeyPress();
this.toggleUIOnKeyPress();
this.showConfigOnKeyPress();
}
}
}

106
WBM/features/core/ui.cs Normal file
View file

@ -0,0 +1,106 @@
using BepInEx.Configuration;
using UnityEngine;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showGUI;
private ConfigEntry<KeyboardShortcut> showGUIShortcut;
private ConfigEntry<int> GUIOffsetX;
private ConfigEntry<int> GUIOffsetY;
private ConfigEntry<KeyboardShortcut> resetGUIShortcut;
private void drawCoreUI()
{
GUI.skin.box.fontSize = 15;
GUI.skin.label.fontSize = 15;
GUI.skin.label.wordWrap = false;
if (this._showConfig) this.showConfig();
if (!this.showGUI.Value) return;
this.showWBMVersion();
}
private void showConfig()
{
GUI.Box(
new Rect(Screen.width - 370, 60, 360, 370), $@"Configuration
move GUI: LCtrl+LShift+Arrow
move GUI by pixel: LCtrl+Arrow
reset GUI position: {this.resetGUIShortcut.Value}
clear chat: {this.clearChatShortcut.Value}
clear death log: {this.clearDeathLogShortcut.Value}
GUI X offset: {this.GUIOffsetX.Value}
GUI Y offset: {this.GUIOffsetY.Value}
Show WBM GUI: {this.showGUI.Value} ({this.showGUIShortcut.Value})
Show Elo on leaderboard: {this.showEloOnLeaderboard.Value} ({this.showEloOnLeaderboardShortcut.Value})
Show player stats: {this.showPlayerStats.Value} ({this.showPlayerStatsShortcut.Value})
Show weapon stats: {this.showWeaponStats.Value} ({this.showWeaponStatsShortcut.Value})
Show teammate stats: {this.showTeamStats.Value} ({this.showTeamStatsShortcut.Value})
show squad server: {this.showSquadServer.Value} ({this.showSquadServerShortcut.Value})
show testing server: {this.showTestingServer.Value} ({this.showTestingServerShortcut.Value})
shift to crouch: {this.shiftToCrouch.Value} ({this.shiftToCrouchShortcut.Value})
kill streak SFX: {this.killStreakSFX.Value} ({this.killStreakSFXShortcut.Value})"
);
}
private void showWBMVersion()
{
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value, 220, 60),
$@"{WBM.programName}
Made by [LP] POMP
v{WBM.programVersion}"
);
}
private void moveUIOnKeyPress()
{
if (Input.GetKey(KeyCode.LeftControl))
{
// move GUI
if (Input.GetKey(KeyCode.LeftShift))
{
if (Input.GetKey(KeyCode.UpArrow)) this.GUIOffsetY.Value -= 1;
if (Input.GetKey(KeyCode.DownArrow)) this.GUIOffsetY.Value += 1;
if (Input.GetKey(KeyCode.LeftArrow)) this.GUIOffsetX.Value -= 1;
if (Input.GetKey(KeyCode.RightArrow)) this.GUIOffsetX.Value += 1;
}
else
{
if (Input.GetKeyDown(KeyCode.UpArrow)) this.GUIOffsetY.Value -= 1;
if (Input.GetKeyDown(KeyCode.DownArrow)) this.GUIOffsetY.Value += 1;
if (Input.GetKeyDown(KeyCode.LeftArrow)) this.GUIOffsetX.Value -= 1;
if (Input.GetKeyDown(KeyCode.RightArrow)) this.GUIOffsetX.Value += 1;
}
}
}
private void resetUIOnKeyPress()
{
if (this.resetGUIShortcut.Value.IsDown())
{
this.GUIOffsetX.Value = (int)this.GUIOffsetX.DefaultValue;
this.GUIOffsetY.Value = (int)this.GUIOffsetY.DefaultValue;
}
}
private void toggleUIOnKeyPress()
{
if (this.showGUIShortcut.Value.IsDown()) this.showGUI.Value = !this.showGUI.Value;
}
private void showConfigOnKeyPress()
{
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightShift)) this._showConfig = true;
if (!Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightShift)) this._showConfig = false;
}
}
}

41
WBM/features/fpsUnlock.cs Normal file
View file

@ -0,0 +1,41 @@
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
namespace WBM
{
/// patch for onFPSChanged function
[HarmonyPatch(typeof(webguy))]
[HarmonyPatch(MangledNames.onFPSChanged)]
class FPSSliderPatch
{
private static int defaultTargetFrameRate = -1;
private static int maxTargetFrameRate = 1000;
private static GameObject fpsSliderTextObj = GameObject.Find("fpsSlideFuckText");
private static Slider slider = GameObject.Find("fpsSlider").GetComponent<Slider>();
private static AccessTools.FieldRef<webguy, float> fpsValueRef = AccessTools.FieldRefAccess<webguy, float>(MangledNames.fpsValue);
static bool Prefix(webguy __instance, float CNFIJGNCMNE)
{
fpsValueRef(__instance) = CNFIJGNCMNE;
int targetFrameRate = (int)(CNFIJGNCMNE * maxTargetFrameRate);
if (targetFrameRate == 0)
{
((InfernalBehaviour)__instance).CEHBKMNGHPG(fpsSliderTextObj, __instance.ILCOAONDEKP("Disabled"));
targetFrameRate = defaultTargetFrameRate;
}
else
{
((InfernalBehaviour)__instance).CEHBKMNGHPG(fpsSliderTextObj, targetFrameRate.ToString());
}
if (targetFrameRate > 0 && targetFrameRate < 5) targetFrameRate = 5;
Application.targetFrameRate = targetFrameRate;
return false;
}
}
}

View file

@ -0,0 +1,42 @@
using BepInEx.Configuration;
using UnityEngine;
using System.Collections.Generic;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> killStreakSFX;
private ConfigEntry<KeyboardShortcut> killStreakSFXShortcut;
private int killStreak = 0;
private AudioSource killStreakAudioSource;
private Dictionary<int, string> killStreakSFXDictionary = new Dictionary<int, string>()
{
{10, "rampage"},
{20, "killing spree"},
{30, "unstoppable"},
{50, "godlike"},
{69, "nice"},
};
private void setupKillStreakSFX()
{
this.killStreakSFX = Config.Bind("Config", "kill streak sound effect", true);
this.killStreakSFXShortcut = Config.Bind("Hotkeys", "kill streak sound effect", new KeyboardShortcut(KeyCode.F, KeyCode.RightShift));
}
private void doKillStreakSFX()
{
this.toggleKillStreakSFXOnKeyPress();
}
private void toggleKillStreakSFXOnKeyPress()
{
if (this.killStreakSFXShortcut.Value.IsDown()) this.killStreakSFX.Value = !this.killStreakSFX.Value;
}
}
}

View file

@ -0,0 +1,71 @@
using BepInEx.Configuration;
using System;
using System.Reflection;
using CAudioClip = KGEACBNNOIM;
namespace WBM
{
public partial class WBM
{
private ConfigEntry<bool> useOldGunSoundConf;
private CAudioClip oldGunSound;
private FieldInfo AKSoundRef;
private CAudioClip AKSoundRaw
{
set
{
this.AKSoundRef.SetValue(this.webguy, value);
}
}
private CAudioClip newAKSound;
private FieldInfo SMGSoundRef;
private CAudioClip SMGSoundRaw
{
set
{
this.SMGSoundRef.SetValue(this.webguy, value);
}
}
private CAudioClip newSMGSound;
private void setupOldGunSound()
{
this.useOldGunSoundConf = Config.Bind("Config", "use old gun sound", true);
this.useOldGunSoundConf.SettingChanged += this.onOldGunSoundChange;
this.AKSoundRef = webguyType.GetField(MangledNames.AKRifleShotClip, bindFlags);
this.SMGSoundRef = webguyType.GetField(MangledNames.SMGShotClip, bindFlags);
this.oldGunSound = new CAudioClip("Sound/gun_shot", 1f, 0f);
this.oldGunSound.DMMKODLJJGP(50f, 1_000f);
this.newAKSound = new CAudioClip("Sound/AK47_Krinkov_Close_Single", 1f, 0f);
this.newAKSound.DMMKODLJJGP(50f, 1_000f);
this.newSMGSound = new CAudioClip("Sound/smg_gun_shot", 1f, 0f);
this.newSMGSound.DMMKODLJJGP(50f, 1_000f);
this.onOldGunSoundChange(new object(), new EventArgs());
}
private void onOldGunSoundChange(object sender, EventArgs e)
{
if (this.useOldGunSoundConf.Value)
{
this.AKSoundRaw = this.oldGunSound;
this.SMGSoundRaw = this.oldGunSound;
}
else
{
this.AKSoundRaw = this.newAKSound;
this.SMGSoundRaw = this.newSMGSound;
}
}
}
}

View file

@ -0,0 +1,53 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showPlayerStats;
private ConfigEntry<KeyboardShortcut> showPlayerStatsShortcut;
private void togglePlayerStatsOnKeyPress()
{
if (this.showPlayerStatsShortcut.Value.IsDown()) this.showPlayerStats.Value = !this.showPlayerStats.Value;
}
private void doPlayerStats()
{
this.togglePlayerStatsOnKeyPress();
}
private void drawPlayerStats()
{
if (!this.showPlayerStats.Value) return;
try
{
string killsEloDeltaSign = this.myPlayerStats.killsEloDelta >= 0 ? "+" : "";
string gamesEloDeltaSign = this.myPlayerStats.gamesEloDelta >= 0 ? "+" : "";
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value + 65, 220, 180),
$@"Player stats
KDR: {Util.formatKDR(this.myPlayerStats.kills, this.myPlayerStats.deaths)}
kills Elo: {this.myPlayerStats.killsElo} {killsEloDeltaSign}{Util.formatDecimal((float)this.myPlayerStats.killsEloDelta / 10)}
games Elo: {this.myPlayerStats.gamesElo} {gamesEloDeltaSign}{Util.formatDecimal((float)this.myPlayerStats.gamesEloDelta / 10)}
Damage dealt: {this.myPlayerStats.damage}
Longest Kill: {this.myPlayerStats.longestKill}m
Points: {this.myPlayerStats.points}
Headshots: {this.myPlayerStats.headShots}
Kill streak: {this.killStreak}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
}
}

View file

@ -0,0 +1,47 @@
using BepInEx.Configuration;
using UnityEngine;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> shiftToCrouch;
private ConfigEntry<KeyboardShortcut> shiftToCrouchShortcut;
private void setupShiftToCrouch()
{
this.shiftToCrouch = Config.Bind("Config", "shift to crouch", true);
this.shiftToCrouchShortcut = Config.Bind("Hotkeys", "shift to crouch", new KeyboardShortcut(KeyCode.C, KeyCode.RightShift));
}
private void doShiftToCrouch()
{
this.crouchOnKeyPress();
this.toggleShiftToCrouchOnKeyPress();
}
private void crouchOnKeyPress()
{
// Skip if this setting is not activated
if (!this.shiftToCrouch.Value) return;
// Skip if right buttton is being pressed (if weapon is zoomed)
if (Input.GetMouseButton(1)) return;
if (Input.GetKeyDown(KeyCode.LeftShift)) setCrouchState(true);
if (Input.GetKeyUp(KeyCode.LeftShift)) setCrouchState(false);
}
private void toggleShiftToCrouchOnKeyPress()
{
if (this.shiftToCrouchShortcut.Value.IsDown()) this.shiftToCrouch.Value = !this.shiftToCrouch.Value;
}
private void setCrouchState(bool crouchState)
{
// CFPSGuy.inSt.isCrouching
HGIJNAOOGIC.AIPINJPLLIN.GDKHEALABDI = crouchState;
}
}
}

View file

@ -0,0 +1,53 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
using System.Reflection;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showEloOnLeaderboard;
private ConfigEntry<KeyboardShortcut> showEloOnLeaderboardShortcut;
private FieldInfo showEloOnLeaderboardRef;
private bool showEloOnLeaderboardRaw
{
get
{
return (bool)this.showEloOnLeaderboardRef.GetValue(this.webguy);
}
set
{
this.showEloOnLeaderboardRef.SetValue(this.webguy, value);
}
}
private void setupShowEloOnLeaderBoard()
{
this.showEloOnLeaderboardRef = webguyType.GetField(MangledNames.showElo, bindFlags);
this.showEloOnLeaderboard = Config.Bind("Config", "show Elo on leaderboard", true);
this.showEloOnLeaderboard.SettingChanged += this.onShowEloOnLeaderboardChange;
this.showEloOnLeaderboardShortcut = Config.Bind("Hotkeys", "show Elo on leaderboard", new KeyboardShortcut(KeyCode.E, KeyCode.RightShift));
this.showEloOnLeaderboardRaw = this.showEloOnLeaderboard.Value;
}
private void doLeaderboardElo()
{
this.toggleLeaderboardEloOnKeyPress();
}
private void toggleLeaderboardEloOnKeyPress()
{
if (this.showEloOnLeaderboardShortcut.Value.IsDown()) this.showEloOnLeaderboard.Value = !this.showEloOnLeaderboard.Value;
}
private void onShowEloOnLeaderboardChange(object sender, EventArgs e)
{
this.showEloOnLeaderboardRaw = this.showEloOnLeaderboard.Value;
}
}
}

View file

@ -0,0 +1,53 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
using System.Reflection;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showSquadServer;
private ConfigEntry<KeyboardShortcut> showSquadServerShortcut;
private FieldInfo showSquadServerRef;
private bool showSquadServerRaw
{
get
{
return (bool)this.showSquadServerRef.GetValue(this.webguy);
}
set
{
this.showSquadServerRef.SetValue(this.webguy, value);
}
}
private void setupShowSquadServer()
{
this.showSquadServerRef = webguyType.GetField(MangledNames.isClan, bindFlags);
this.showSquadServer = Config.Bind("Config", "show squad server", true);
this.showSquadServer.SettingChanged += this.onShowSquadServerChange;
this.showSquadServerShortcut = Config.Bind("Hotkeys", "show squad server", new KeyboardShortcut(KeyCode.S, KeyCode.RightShift));
this.showSquadServerRaw = this.showSquadServer.Value;
}
private void doShowSquadServer()
{
this.toggleShowSquadServerOnKeyPress();
}
private void toggleShowSquadServerOnKeyPress()
{
if (this.showSquadServerShortcut.Value.IsDown()) this.showSquadServer.Value = !this.showSquadServer.Value;
}
private void onShowSquadServerChange(object sender, EventArgs e)
{
this.showSquadServerRaw = this.showSquadServer.Value;
}
}
}

View file

@ -0,0 +1,53 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
using System.Reflection;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showTestingServer;
private ConfigEntry<KeyboardShortcut> showTestingServerShortcut;
private FieldInfo showTestingServerRef;
private bool showTestingServerRaw
{
get
{
return (bool)this.showTestingServerRef.GetValue(this.webguy);
}
set
{
this.showTestingServerRef.SetValue(this.webguy, value);
}
}
private void setupShowTestingServer()
{
this.showTestingServerRef = webguyType.GetField(MangledNames.isTesting, bindFlags);
this.showTestingServer = Config.Bind("Config", "show testing server", true);
this.showTestingServer.SettingChanged += this.onShowTestingServerChange;
this.showTestingServerShortcut = Config.Bind("Hotkeys", "show testing server", new KeyboardShortcut(KeyCode.T, KeyCode.RightShift));
this.showTestingServerRaw = this.showTestingServer.Value;
}
private void doTestingServer()
{
this.toggleTestingServerOnKeyPress();
}
private void toggleTestingServerOnKeyPress()
{
if (this.showTestingServerShortcut.Value.IsDown()) this.showTestingServer.Value = !this.showTestingServer.Value;
}
private void onShowTestingServerChange(object sender, EventArgs e)
{
this.showTestingServerRaw = this.showTestingServer.Value;
}
}
}

77
WBM/features/teamStats.cs Normal file
View file

@ -0,0 +1,77 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showTeamStats;
private ConfigEntry<KeyboardShortcut> showTeamStatsShortcut;
private void doTeamStats()
{
this.toggleTeamStatsOnKeyPress();
}
private void drawTeamStats()
{
if (!this.showTeamStats.Value) return;
try
{
string teamNames = "Nickname\n\n";
string teamKDR = "KDR\n\n";
string teamPoints = "pts\n\n";
string teamDamage = "Damage\n\n";
int teamTotalKills = 0;
int teamTotalDeaths = 0;
int teamTotalDamage = 0;
for (int i = 0; i < this.data.playerStatsArray.Length; i++)
{
Data.PlayerStatsStruct stat = this.data.playerStatsArray[i];
// if player is not a bot and if player is in my team
if ((stat.killsElo != 0) && (this.teamList[i] == this.myTeam))
{
teamNames += $"{this.data.nickList[i]}\n";
teamKDR += $"{Util.formatKDR(stat.kills, stat.deaths)}\n";
teamPoints += $"{stat.points}\n";
teamDamage += $"{stat.damage}\n";
teamTotalKills += stat.kills;
teamTotalDeaths += stat.deaths;
teamTotalDamage += stat.damage;
}
}
int teamStatOffset = (this.data.gameState == Data.GameStateEnum.Results) ? 280 : 0;
GUI.Box(new Rect(Screen.width - 320, 445 + teamStatOffset, 300, 270), "Team Stats");
GUI.Label(new Rect(Screen.width - 315, 470 + teamStatOffset, 105, 190), teamNames);
GUI.Label(new Rect(Screen.width - 200, 470 + teamStatOffset, 40, 190), teamKDR);
GUI.Label(new Rect(Screen.width - 150, 470 + teamStatOffset, 40, 190), teamPoints);
GUI.Label(new Rect(Screen.width - 100, 470 + teamStatOffset, 70, 190), teamDamage);
GUI.Label(
new Rect(Screen.width - 315, 655 + teamStatOffset, 300, 55),
$@"total damage: {teamTotalDamage}
total deaths: {teamTotalDeaths}
total kills: {teamTotalKills}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
private void toggleTeamStatsOnKeyPress()
{
if (this.showTeamStatsShortcut.Value.IsDown()) this.showTeamStats.Value = !this.showTeamStats.Value;
}
}
}

View file

@ -0,0 +1,47 @@
using BepInEx.Configuration;
using UnityEngine;
using System;
namespace WBM
{
partial class WBM
{
private ConfigEntry<bool> showWeaponStats;
private ConfigEntry<KeyboardShortcut> showWeaponStatsShortcut;
private void doWeaponStats()
{
this.toggleWeaponStatsOnKeyPress();
}
private void drawWeaponStats()
{
if (!this.showWeaponStats.Value) return;
try
{
GUI.Box(
new Rect(this.GUIOffsetX.Value, this.GUIOffsetY.Value + 250, 230, 130),
$@"Weapon stats
fire Timer: {String.Format("{0:0.00}", Util.getGunFireTimer(this.personGun))}s (max: {String.Format("{0:0.00}", Util.getGunFireRate(this.personGun))}s)
reload Timer: {Util.getGunReloadTimer(this.personGun)}
speed: {Util.getGunFireVelocity(this.personGun)}
zoom: {Util.getGunZoom(this.personGun)}"
);
}
catch (Exception e)
{
Logger.LogError(e);
}
}
private void toggleWeaponStatsOnKeyPress()
{
if (this.showWeaponStatsShortcut.Value.IsDown()) this.showWeaponStats.Value = !this.showWeaponStats.Value;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB