diff --git a/PublicationContent/description.txt b/PublicationContent/description.txt index 3568c0d..2fd59f2 100644 --- a/PublicationContent/description.txt +++ b/PublicationContent/description.txt @@ -1,8 +1,41 @@ -[h1]KF2-SafeMutLoader[/h1] +[h1][b]Use non-whitelisted mutators and stay ranked[/b][/h1] -[h1]Description[/h1] -[b]Mutator(s):[/b] SML.Mut +[h1]Limitations[/h1] +⚠️ SML only has an effect when compatible mutators are used. If you use incompatible mutators you will lose ranked status. +⚠️ SML incompatible with [b][url=https://github.com/th3-z/kf2-acpp]AccessPlus[/url][/b]. If you need something from there, implement it as an SML compatible mutator using [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2863210737]developer guide[/url]. -[h1]Author[/h1] -[url=https://github.com/GenZmeY]GenZmeY[/url] +[h1]Compatible mutators[/h1] +🟒 Any whitelisted mutators +🟒 [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2848836389]Admin Auto Login[/url] +🟒 [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2847465899]Controlled Vote Collector[/url] +🟑 [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2830826239]Custom Trader Inventory[/url] +[list] +[*]Purchasing a DLC weapon will unrank the server if currently there is no player with the purchased DLC. This can be bypassed by replacing all DLC weapons with their clones. +[*]Since [url=https://wiki.killingfloor2.com/index.php?title=Update_1133_(Killing_Floor_2)]KF2 v1133[/url] the content preload causes the server to unrank for some reason. Disable it in CTI settings ([b]bPreloadContent=False[/b]) to stay ranked. +[/list] +🟑 [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2811290931]Zed Spawner[/url] +[list] +[*]Since [url=https://wiki.killingfloor2.com/index.php?title=Update_1133_(Killing_Floor_2)]KF2 v1133[/url] zed preload causes the server to unrank for some reason (current version of ZedSpawner does not allow you to disable preload, but I will add it later). +[/list] +🟒 [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2521826524]Yet Another Scoreboard[/url] +[h1]Developer guide[/h1] +If you want to make your mutator compatible with SML use this: +[url=https://steamcommunity.com/sharedfiles/filedetails/?id=2863210737]Developer Guide[/url] + +If you make a public mutator with SML support, I'd be happy if you tell me about it so I can add it to the list above. + +[h1]Usage[/h1] +[code] +?Mutator=SML.Mut,AAL.AALMut,YAS.YASMut,CTI.CTIMut,CVC.CVCMut,ZedSpawner.ZedSpawnerMut +[/code] +(replace the map and add/remove [b]compatible[/b] mutators you need) + +❗️ SML must be first in the mutators list or it won't work. +❗️ SML is a server-side mutator, clients never download it. Therefore, no one will know about SML if you don’t tell yourself. You can also accidentally give it to the whole world if you use a redirect and share the folder where it's located. Be careful about this. +❗️ I also really hope you don't report this to TWI. If I find this blocked, I will probably be upset in the world and in the people with whom I shared this :( + +[h1]Sources[/h1] +Right now, I don't want to post SML sources because I'm planning to submit several whitelist requests for my mutators. TWI will probably look at my github (At least I hope so) and I don't want them to see SML. + +But later I will post it under the GNU GPLv3. diff --git a/PublicationContent/dev_guide.txt b/PublicationContent/dev_guide.txt new file mode 100644 index 0000000..0acc9d5 --- /dev/null +++ b/PublicationContent/dev_guide.txt @@ -0,0 +1,176 @@ +[SML] Developer Guide + +[b]SML compatible mutator development guide[/b] + +Mutator template + +You can use this template to make the mutator compatible with [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847]SML[/url]. +Here I will use "[b]Example[/b]" as mutator name. Replace it with yours. + +[b]ExampleMut.uc[/b] +[code] +class ExampleMut extends KFMutator; + +var private Example Example; + +public simulated function bool SafeDestroy() +{ + return (bPendingDelete || bDeleteMe || Destroy()); +} + +public event PreBeginPlay() +{ + Super.PreBeginPlay(); + + if (WorldInfo.NetMode == NM_Client) return; + + foreach WorldInfo.DynamicActors(class'Example', Example) + { + break; + } + + if (Example == None) + { + Example = WorldInfo.Spawn(class'Example'); + } + + if (Example == None) + { + `Log("Example: FATAL: Can't Spawn 'Example'"); + SafeDestroy(); + } +} + +public function AddMutator(Mutator Mut) +{ + if (Mut == Self) return; + + if (Mut.Class == Class) + Mut.Destroy(); + else + Super.AddMutator(Mut); +} + +public function NotifyLogin(Controller C) +{ + Example.NotifyLogin(C); + + Super.NotifyLogin(C); +} + +public function NotifyLogout(Controller C) +{ + Example.NotifyLogout(C); + + Super.NotifyLogout(C); +} + +static function String GetLocalString(optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2) +{ + return String(class'Example'); +} + +defaultproperties +{ + +} +[/code] + +[b]Example.uc[/b] +[code] +class Example extends Info; + +public event PreBeginPlay() +{ + Super.PreBeginPlay(); + + // do some initialization here +} + +public event PostBeginPlay() +{ + Super.PostBeginPlay(); + + // do some initialization here +} + +public function NotifyLogin(Controller C) +{ + // Do what you need here when the player log in +} + +public function NotifyLogout(Controller C) +{ + // Do what you need here when the player log out +} + +public simulated function vector GetTargetLocation(optional actor RequestedBy, optional bool bRequestAlternateLoc) +{ + local Controller C; + C = Controller(RequestedBy); + if (C != None) { bRequestAlternateLoc ? NotifyLogout(C) : NotifyLogin(C); } + return Super.GetTargetLocation(RequestedBy, bRequestAlternateLoc); +} + +defaultproperties +{ + +} +[/code] + +That's all. You can create new classes and add any code to [b]Example.uc[/b], but refrain from implementing anything else in [b]ExampleMut.uc[/b] + +Limitations + +❌ Can't make ranked game mode this way; +❌ [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847]SML[/url] can only emulate [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/Mutator.uc#L147]NotifyLogin(...)[/url] and [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/Mutator.uc#L141]NotifyLogout(...)[/url], other functions of the [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/Mutator.uc]Mutator[/url] and [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/KFMutator.uc]KFMutator[/url] classes are not supported - look for workarounds in this case. + +[Tips] Alternative to the InitMutator(...) function + +Even though the [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/KFGame/Classes/KFMutator.uc#L22]InitMutator(...)[/url] function is not supported, you can still parse the startup string if you need to: +Refer to [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/GameInfo.uc#L209]WorldInfo.Game.ServerOptions[/url] or [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/9553ac0b31c729c27e9cd0a460ab5a7bae2fd799/Engine/Classes/WorldInfo.uc#L1315]WorldInfo.GetLocalURL()[/url] and get the option from there. It's best to do this in [b]PreBeginPlay()[/b] or [b]PostBeginPlay()[/b] of your [b]Example.uc[/b] (as well as other initializations). + +[Tips] XP for custom Zeds / Weapons + +While custom weapons and zeds won't make your server unranked, the [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/513c60070e2b700b5c311843754ed0e39b55a14e/KFGame/Classes/KFGameInfo.uc#L2594]ValidateForXP(...)[/url] function will not allow you to gain experience if it detects a custom zed or custom damage type. + +To work around this, don't use custom damage types on custom weapons, or replace information in [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/513c60070e2b700b5c311843754ed0e39b55a14e/KFGame/Classes/KFPawn.uc#L182]DamageHistory[/url] before it gets into the [url=https://github.com/GenZmeY/KF2-Dev-Scripts/blob/513c60070e2b700b5c311843754ed0e39b55a14e/KFGame/Classes/KFGameInfo.uc#L2489]DistributeMoneyAndXP(...)[/url] function. + +[Tips] Replacing base classes to bypass restrictions + +In some cases, changing the base classes of the game can help. For example, we cannot make [b][url=https://steamcommunity.com/sharedfiles/filedetails/?id=2379769040]TAWOD[/url][/b] and [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847]SML[/url] compatible because the [url=https://github.com/GenZmeY/KF2-TAWOD/blob/master/TAWOD/Classes/TAWODMut.uc#L19]PreventDeath(...)[/url] function is not supported. But this can be bypassed by replacing the player's Pawn base class with custom Pawn class: +[code] +WorldInfo.Game.DefaultPawnClass = class'ExamplePawn_Human'; +[/code] +(This can be done in [b]PostBeginPlay()[/b]) + +And now we can implement all weapons drop in [b]ExamplePawn_Human.uc[/b]: +[code] +class TAWODPawn_Human extends KFPawn_Human; + +public function ThrowActiveWeapon(optional bool bDestroyWeap) +{ + local KFWeapon KFW; + + if (Role < ROLE_Authority) + { + return; + } + + if (Health <= 0) + { + if (InvManager != None) + foreach KFP.InvManager.InventoryActors(class'KFWeapon', KFW) + if (KFW != None && KFW.bDropOnDeath && KFW.CanThrow()) + KFP.TossInventory(KFW); + } + else + { + super.ThrowActiveWeapon(bDestroyWeap); + } +} +[/code] + +[Tips] Cloning DLC weapons + +πŸ› [b] [/b]πŸ›  diff --git a/PublicationContent/dev_guide_preview.png b/PublicationContent/dev_guide_preview.png new file mode 100644 index 0000000..a060a71 Binary files /dev/null and b/PublicationContent/dev_guide_preview.png differ diff --git a/PublicationContent/preview.png b/PublicationContent/preview.png index 7fb463e..4d7b065 100644 Binary files a/PublicationContent/preview.png and b/PublicationContent/preview.png differ diff --git a/PublicationContent/title.txt b/PublicationContent/title.txt index e2230aa..4b3951b 100644 --- a/PublicationContent/title.txt +++ b/PublicationContent/title.txt @@ -1 +1 @@ -KF2-SafeMutLoader +Safe Mut Loader diff --git a/README.md b/README.md index 9b11259..4d99886 100644 --- a/README.md +++ b/README.md @@ -1 +1,37 @@ -# KF2-SafeMutLoader \ No newline at end of file +# KF2-SafeMutLoader + +[![Steam Workshop](https://img.shields.io/static/v1?message=workshop&logo=steam&labelColor=gray&color=blue&logoColor=white&label=steam%20)](https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847) +[![Steam Downloads](https://img.shields.io/steam/downloads/2863226847)](https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847) +[![Steam Favorites](https://img.shields.io/steam/favorites/2863226847)](https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847) +[![Steam Update Date](https://img.shields.io/steam/update-date/2863226847)](https://steamcommunity.com/sharedfiles/filedetails/?id=2863226847) +[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/GenZmeY/KF2-SafeMutLoader)](https://github.com/GenZmeY/KF2-SafeMutLoader/tags) +[![GitHub](https://img.shields.io/github/license/GenZmeY/KF2-SafeMutLoader)](LICENSE) + +# Description +Use non-whitelisted mutators and stay ranked + +# Usage +``` +?Mutator=SML.Mut,AAL.AALMut,YAS.YASMut,CTI.CTIMut,CVC.CVCMut,ZedSpawner.ZedSpawnerMut +``` +(replace the map and add/remove compatible mutators you need) + +❗️ SML must be first in the mutators list or it won't work. +❗️ SML is a server-side mutator, clients never download it. Therefore, no one will know about SML if you don’t tell yourself. You can also accidentally give it to the whole world if you use a redirect and share the folder where it's located. Be careful about this. + +# Build +**Note:** If you want to build/test/brew/publish a mutator without git-bash and/or scripts, follow [these instructions](https://tripwireinteractive.atlassian.net/wiki/spaces/KF2SW/pages/26247172/KF2+Code+Modding+How-to) instead of what is described here. +1. Install [Killing Floor 2](https://store.steampowered.com/app/232090/Killing_Floor_2/), Killing Floor 2 - SDK and [git for windows](https://git-scm.com/download/win); +2. open git-bash and go to any folder where you want to store sources: +`cd ` +3. Clone this repository and go to the source folder: +`git clone https://github.com/GenZmeY/KF2-SafeMutLoader && cd KF2-SafeMutLoader` +4. Download dependencies: +`git submodule init && git submodule update` +5. Compile: +`./tools/builder -c` +5. The compiled files will be here: +`C:\Users\\Documents\My Games\KillingFloor2\KFGame\Unpublished\BrewedPC\Script\` + +# License +[GNU GPLv3](LICENSE) diff --git a/builder.cfg b/builder.cfg index 2a62a4f..d62af68 100644 --- a/builder.cfg +++ b/builder.cfg @@ -55,7 +55,7 @@ Difficulty="0" GameLength="0" # Mutators -Mutators="SML.Mut" +Mutators="SML.Mut,AAL.AALMut,YAS.YASMut,CTI.CTIMut,CVC.CVCMut,ZedSpawner.ZedSpawnerMut" # Additional parameters Args=""