Compare commits
No commits in common. "master" and "v1.1.0" have entirely different histories.
@ -1,33 +0,0 @@
|
||||
root = true
|
||||
|
||||
# Global
|
||||
[*]
|
||||
indent_style = unset
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = unset
|
||||
|
||||
# Unreal Engine 3 / Source
|
||||
[*.uc]
|
||||
indent_style = tab
|
||||
|
||||
[*.{uci,upkg}]
|
||||
|
||||
# Unreal Engine 3 / i18n
|
||||
[*.{chn,cht,cze,dan,deu,dut,esl,esn,fra,frc,hun,int,ita,jpn,kor,pol,por,ptb,rus,tur,ukr}]
|
||||
charset = utf-16le
|
||||
|
||||
# Other
|
||||
[*.md]
|
||||
indent_style = space
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{txt,cfg,conf}]
|
||||
indent_style = tab
|
114
.github/workflows/mega-linter.yml
vendored
114
.github/workflows/mega-linter.yml
vendored
@ -1,114 +0,0 @@
|
||||
---
|
||||
name: MegaLinter
|
||||
|
||||
permissions: read-all
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
APPLY_FIXES: none
|
||||
APPLY_FIXES_EVENT: pull_request
|
||||
APPLY_FIXES_MODE: commit
|
||||
FILTER_REGEX_EXCLUDE: (mega-linter.yml)
|
||||
DISABLE: SPELL
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.ref }}-${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
megalinter:
|
||||
name: MegaLinter
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
||||
with:
|
||||
token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: MegaLinter
|
||||
uses: oxsecurity/megalinter@7e042c726c68415475b05a65a686c612120a1232
|
||||
id: ml
|
||||
env:
|
||||
VALIDATE_ALL_CODEBASE: true
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392
|
||||
if: success() || failure()
|
||||
with:
|
||||
name: MegaLinter reports
|
||||
path: |
|
||||
megalinter-reports
|
||||
mega-linter.log
|
||||
|
||||
- name: Set APPLY_FIXES_IF var
|
||||
run: |
|
||||
printf 'APPLY_FIXES_IF=%s\n' "${{
|
||||
steps.ml.outputs.has_updated_sources == 1 &&
|
||||
(
|
||||
env.APPLY_FIXES_EVENT == 'all' ||
|
||||
env.APPLY_FIXES_EVENT == github.event_name
|
||||
) &&
|
||||
(
|
||||
github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
)
|
||||
}}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Set APPLY_FIXES_IF_* vars
|
||||
run: |
|
||||
printf 'APPLY_FIXES_IF_PR=%s\n' "${{
|
||||
env.APPLY_FIXES_IF == 'true' &&
|
||||
env.APPLY_FIXES_MODE == 'pull_request'
|
||||
}}" >> "${GITHUB_ENV}"
|
||||
printf 'APPLY_FIXES_IF_COMMIT=%s\n' "${{
|
||||
env.APPLY_FIXES_IF == 'true' &&
|
||||
env.APPLY_FIXES_MODE == 'commit' &&
|
||||
(!contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref))
|
||||
}}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Create Pull Request with applied fixes
|
||||
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38
|
||||
id: cpr
|
||||
if: env.APPLY_FIXES_IF_PR == 'true'
|
||||
with:
|
||||
token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
|
||||
commit-message: "[MegaLinter] Apply linters automatic fixes"
|
||||
title: "[MegaLinter] Apply linters automatic fixes"
|
||||
labels: bot
|
||||
|
||||
- name: Create PR output
|
||||
if: env.APPLY_FIXES_IF_PR == 'true'
|
||||
run: |
|
||||
echo "PR Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
||||
echo "PR URL - ${{ steps.cpr.outputs.pull-request-url }}"
|
||||
|
||||
- name: Prepare commit
|
||||
if: env.APPLY_FIXES_IF_COMMIT == 'true'
|
||||
run: sudo chown -Rc $UID .git/
|
||||
|
||||
- name: Commit and push applied linter fixes
|
||||
uses: stefanzweifel/git-auto-commit-action@8756aa072ef5b4a080af5dc8fef36c5d586e521d
|
||||
if: env.APPLY_FIXES_IF_COMMIT == 'true'
|
||||
with:
|
||||
branch: >-
|
||||
${{
|
||||
github.event.pull_request.head.ref ||
|
||||
github.head_ref ||
|
||||
github.ref
|
||||
}}
|
||||
commit_message: "[MegaLinter] Apply linters fixes"
|
||||
commit_user_name: "github-actions"
|
||||
commit_user_email: "github-actions[bot]@users.noreply.github.com"
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*.psd
|
||||
/ignore
|
@ -1,56 +1,46 @@
|
||||
[img]https://img.shields.io/static/v1?logo=GitHub&labelColor=gray&color=blue&logoColor=white&label=&message=Open Source[/img] [img]https://img.shields.io/github/license/GenZmeY/KF2-StartWave[/img] [img]https://img.shields.io/steam/subscriptions/2521731447[/img] [img]https://img.shields.io/steam/favorites/2521731447[/img] [img]https://img.shields.io/steam/update-date/2521731447[/img] [url=https://steamcommunity.com/sharedfiles/filedetails/changelog/2521731447][img]https://img.shields.io/github/v/tag/GenZmeY/KF2-StartWave[/img][/url]
|
||||
[h1]Warning[/h1]
|
||||
This mod is not whitelisted and will unrank your server. Any XP gained will not be saved.
|
||||
|
||||
[h1]Description:[/h1]
|
||||
This is the same as [url=https://steamcommunity.com/sharedfiles/filedetails/?id=1417081496]Pharrahnox's SetWave[/url], but with some fixes:
|
||||
[olist]
|
||||
[*] fixed starting Dosh for Endless mode;
|
||||
[*] fixed difficulty setting when changing wave;
|
||||
[*] optimized boss replacement: now it always works successfully and quickly;
|
||||
[*] players no longer need to download StartWave when connecting to a server.
|
||||
[/olist]
|
||||
- fixed starting Dosh for Endless mode.
|
||||
|
||||
A utility mod that allows users to specify the starting wave and the boss that will spawn. Additionally, users can jump between waves during the match with a console command (mutate setwave, see below).
|
||||
The purpose of this mod is to allow mappers to more efficiently test their maps for later waves or for the boss. It could also be used to skip early waves if you find them boring, or to test strategies against a specific boss.
|
||||
It is designed to be compatible with every mutator and wave-based gamemode, and to require little to no maintenance after game updates.
|
||||
|
||||
[h1]Whitelisted?[/h1]
|
||||
No. This mod is not whitelisted and will unrank your server. Any XP gained will not be saved.
|
||||
|
||||
[h1]Usage (single player):[/h1]
|
||||
[olist]
|
||||
[*]Subscribe to this mutator;
|
||||
[*]Start KF2;
|
||||
[*]Open console (`) and input:
|
||||
[b]open KF-BioticsLab?Game=KFGameContent.KFGameInfo_Endless?Difficulty=0?GameLength=0?Mutator=StartWave.Mut[/b]
|
||||
(replace the map and add the parameters you need)
|
||||
[*]<Enter>.
|
||||
[/olist]
|
||||
1. Subscribe to this mutator;
|
||||
2. Start KF2;
|
||||
3. Open console (`) and input:
|
||||
[code]open KF-BioticsLab?Game=KFGameContent.KFGameInfo_Endless?Difficulty=0?GameLength=0?Mutator=StartWave.StartWave?[/code]
|
||||
Change the name of the map and the parameters of the game to the ones you need.
|
||||
Add StartWave parameters that you need to the end of the line (you can add any parameter from the config, the description is below).
|
||||
4. <Enter>.
|
||||
|
||||
[h1]Usage (server)[/h1]
|
||||
[b]Note:[/b] [i]If you don't understand what is written here, read the article [url=https://wiki.killingfloor2.com/index.php?title=Dedicated_Server_(Killing_Floor_2)][u]Dedicated Server (KF2 wiki)[/u][/url] before following these instructions.[/i]
|
||||
[olist]
|
||||
[*]Open your [b]PCServer-KFEngine.ini[/b] / [b]LinuxServer-KFEngine.ini[/b];
|
||||
[*]Find the [b][IpDrv.TcpNetDriver][/b] section and make sure that there is a line (add if not):
|
||||
[b]DownloadManagers=OnlineSubsystemSteamworks.SteamWorkshopDownload[/b]
|
||||
❗️ If there are several [b]DownloadManagers=[/b] then the line above should be the first ❗️
|
||||
[*]Add the following string to the [b][OnlineSubsystemSteamworks.KFWorkshopSteamworks][/b] section (create one if it doesn't exist):
|
||||
[b]ServerSubscribedWorkshopItems=2521731447[/b]
|
||||
[*]Start the server and wait while the mutator is downloading;
|
||||
[*]Add mutator (with parameters you need) to server start parameters: [b]?Mutator=StartWave.Mut[/b] and restart the server.
|
||||
[/olist]
|
||||
[h1]Usage (server):[/h1]
|
||||
[b]Note:[/b] If you don't understand what is written here, read the article [url=https://wiki.killingfloor2.com/index.php?title=Dedicated_Server_(Killing_Floor_2)][u]Dedicated Server (KF2 wiki)[/u][/url] before following these instructions.
|
||||
|
||||
1. Open your PCServer-KFEngine.ini / LinuxServer-KFEngine.ini;
|
||||
2. Add the following string to the [b][OnlineSubsystemSteamworks.KFWorkshopSteamworks][/b] section:
|
||||
[code]ServerSubscribedWorkshopItems=2521731447[/code]
|
||||
3. Start the server and wait while the mutator is downloading;
|
||||
4. Stop the server;
|
||||
5. Add mutator to server start line: [b]?Mutator=StartWave.StartWave[/b]
|
||||
6. Add StartWave parameters or use config (the description is below).
|
||||
7. Start the server
|
||||
|
||||
[h1]Mutator setup[/h1]
|
||||
The parameters below can be used as parameters in the startup line.
|
||||
But You can use a config if you don't want to specify parameters in the startup line:
|
||||
Create a file [b]KFGame/Config/KFStartWave.ini[/b] and copy this text into it:
|
||||
You can use a config if you don't want to specify parameters in the startup line:
|
||||
Create a file KFGame/Config/KFStartWave.ini and copy this text into it:
|
||||
[code]
|
||||
[StartWave.StartWave]
|
||||
// Any settings not specified in the launch command will use the values stored here.
|
||||
// If you use the same settings often, it is recommended to store those here
|
||||
// and only change what you need in the launch command.
|
||||
|
||||
// LogLevel (Set this to 'LL_Debug' if you need more information in the log)
|
||||
LogLevel=LL_Info
|
||||
// Whether mod-specific events should be logged.
|
||||
bUseDebug=true
|
||||
|
||||
// Whether an 'initial' trader time should occur before the first wave.
|
||||
bStartWithTrader=false
|
||||
@ -102,5 +92,10 @@ If it’s not a problem for you to download all subscriptions again, you can sim
|
||||
If you do not want to download the subscriptions again, delete only those folders that contain SetWave.u file.
|
||||
3. Try starting the game/server again.
|
||||
|
||||
[h1]Sources[/h1]
|
||||
[url=https://github.com/GenZmeY/KF2-StartWave]https://github.com/GenZmeY/KF2-StartWave[/url] [b](GNU GPLv3)[/b]
|
||||
[h1]Bug reports[/h1]
|
||||
I didn't test the mod very much because I only needed to fix a bug with Dosh.
|
||||
If you find any other problems, please describe how to reproduce them. Maybe I can fix it.
|
||||
You can do it right here, but I'll be much happier if you do it [url=https://github.com/GenZmeY/KF2-StartWave/issues]in issues on github[/url] .
|
||||
|
||||
[h1]Sources:[/h1]
|
||||
[u]https://github.com/GenZmeY/KF2-StartWave[/u] [b](GNU GPLv3)[/b]
|
34
README.md
34
README.md
@ -1,32 +1,28 @@
|
||||
# KF2-StartWave
|
||||
|
||||
[![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=2521731447)
|
||||
[![Steam Downloads](https://img.shields.io/steam/downloads/2521731447)](https://steamcommunity.com/sharedfiles/filedetails/?id=2521731447)
|
||||
[![Steam Subscriptions](https://img.shields.io/steam/subscriptions/2521731447)](https://steamcommunity.com/sharedfiles/filedetails/?id=2521731447)
|
||||
[![Steam Favorites](https://img.shields.io/steam/favorites/2521731447)](https://steamcommunity.com/sharedfiles/filedetails/?id=2521731447)
|
||||
[![MegaLinter](https://github.com/GenZmeY/KF2-StartWave/actions/workflows/mega-linter.yml/badge.svg?branch=master)](https://github.com/GenZmeY/KF2-StartWave/actions/workflows/mega-linter.yml)
|
||||
[![Steam Update Date](https://img.shields.io/steam/update-date/2521731447)](https://steamcommunity.com/sharedfiles/filedetails/?id=2521731447)
|
||||
[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/GenZmeY/KF2-StartWave)](https://github.com/GenZmeY/KF2-StartWave/tags)
|
||||
[![GitHub](https://img.shields.io/github/license/GenZmeY/KF2-StartWave)](LICENSE)
|
||||
|
||||
## Description
|
||||
# Description
|
||||
A utility mod that allows users to specify the starting wave and the boss that will spawn. Additionally, users can jump between waves during the match with a console command (mutate setwave, see below).
|
||||
The purpose of this mod is to allow mappers to more efficiently test their maps for later waves or for the boss. It could also be used to skip early waves if you find them boring, or to test strategies against a specific boss.
|
||||
It is designed to be compatible with every mutator and wave-based gamemode, and to require little to no maintenance after game updates.
|
||||
|
||||
**This is the same as [Pharrahnox's StartWave](https://steamcommunity.com/sharedfiles/filedetails/?id=1417081496), but with some fixes:**
|
||||
- fixed starting Dosh for Endless mode;
|
||||
- fixed difficulty setting when changing wave;
|
||||
- optimized boss replacement: now it always works successfully and quickly;
|
||||
- players no longer need to download StartWave when connecting to a server.
|
||||
**This is the same as [Pharrahnox's SetWave](https://steamcommunity.com/sharedfiles/filedetails/?id=1417081496), but with some fixes:**
|
||||
- fixed starting Dosh for Endless mode.
|
||||
|
||||
## Usage
|
||||
# Usage
|
||||
[See steam workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=2521731447)
|
||||
|
||||
***
|
||||
|
||||
**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.
|
||||
|
||||
## 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.
|
||||
# Build
|
||||
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 <ANY_FOLDER_YOU_WANT>`
|
||||
@ -39,13 +35,21 @@ It is designed to be compatible with every mutator and wave-based gamemode, and
|
||||
5. The compiled files will be here:
|
||||
`C:\Users\<USERNAME>\Documents\My Games\KillingFloor2\KFGame\Unpublished\BrewedPC\Script\`
|
||||
|
||||
## Bug reports
|
||||
# Testing
|
||||
Open git-bash in the source folder and run command:
|
||||
`./tools/builder -t`
|
||||
(or `./tools/builder -ct` if you haven't compiled the mutator yet)
|
||||
|
||||
A local single-user test will be launched with parameters from `test.cfg` (edit this file if you want to test mutator with different parameters).
|
||||
|
||||
# Bug reports
|
||||
If you find a bug, go to the [issue page](https://github.com/GenZmeY/KF2-StartWave/issues) and check if there is a description of your bug. If not, create a new issue.
|
||||
Describe what the bug looks like and how reproduce it.
|
||||
Attach screenshots if you think it might help.
|
||||
|
||||
If it's a crash issue, be sure to include the `Launch.log` file. You can find it here:
|
||||
If it's a crash issue, be sure to include the `Launch.log` and `Launch_2.log` files. You can find them here:
|
||||
`C:\Users\<USERNAME>\Documents\My Games\KillingFloor2\KFGame\Logs\`
|
||||
Please note that these files are overwritten every time you start the game/server. Therefore, you must take these files immediately after the game crashes in order not to lose information.
|
||||
|
||||
## License
|
||||
[![license](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)](LICENSE)
|
||||
# License
|
||||
[GNU GPLv3](LICENSE)
|
@ -1,22 +0,0 @@
|
||||
class KFGI_Access extends Object
|
||||
within KFGameInfo;
|
||||
|
||||
public function OverrideBossIndex(int Index, optional bool Force = false)
|
||||
{
|
||||
if (Index < 0 || Index >= default.AIBossClassList.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UseSpecificBossIndex(BossIndex) || Force)
|
||||
{
|
||||
BossIndex = Index;
|
||||
}
|
||||
|
||||
MyKFGRI.CacheSelectedBoss(BossIndex);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
class Mut extends KFMutator;
|
||||
|
||||
var private StartWave StartWave;
|
||||
|
||||
public simulated function bool SafeDestroy()
|
||||
{
|
||||
return (bPendingDelete || bDeleteMe || Destroy());
|
||||
}
|
||||
|
||||
public event PreBeginPlay()
|
||||
{
|
||||
Super.PreBeginPlay();
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client) return;
|
||||
|
||||
foreach WorldInfo.DynamicActors(class'StartWave', StartWave)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (StartWave == None)
|
||||
{
|
||||
StartWave = WorldInfo.Spawn(class'StartWave');
|
||||
}
|
||||
|
||||
if (StartWave == None)
|
||||
{
|
||||
`Log_Base("FATAL: Can't Spawn 'StartWave'");
|
||||
SafeDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
public function AddMutator(Mutator M)
|
||||
{
|
||||
if (M == Self) return;
|
||||
|
||||
if (M.Class == Class)
|
||||
Mut(M).SafeDestroy();
|
||||
else
|
||||
Super.AddMutator(M);
|
||||
}
|
||||
|
||||
public function Mutate(String MutateString, PlayerController Sender)
|
||||
{
|
||||
StartWave.Mutate(MutateString, Sender);
|
||||
|
||||
Super.Mutate(MutateString, Sender);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
class OptionsParser extends Object;
|
||||
|
||||
const GameInfo = class'GameInfo';
|
||||
|
||||
/**
|
||||
*** @brief Gets a int from the launch command if available.
|
||||
***
|
||||
*** @param Options - options passed in via the launch command
|
||||
*** @param ParseString - the variable we are looking for
|
||||
*** @param CurrentValue - the current value of the variable
|
||||
*** @return int value of the option we are looking for
|
||||
***/
|
||||
static function int GetIntOption( String Options, String ParseString, int CurrentValue)
|
||||
{
|
||||
return GameInfo.static.GetIntOption(Options, ParseString, CurrentValue);
|
||||
}
|
||||
|
||||
/**
|
||||
*** @brief Gets a bool from the launch command if available.
|
||||
***
|
||||
*** @param Options - options passed in via the launch command
|
||||
*** @param ParseString - the variable we are looking for
|
||||
*** @param CurrentValue - the current value of the variable
|
||||
*** @return bool value of the option we are looking for
|
||||
***/
|
||||
static public function bool GetBoolOption(String Options, String ParseString, bool CurrentValue)
|
||||
{
|
||||
local String InOpt;
|
||||
|
||||
//Find the value associated with this variable in the launch command.
|
||||
InOpt = GameInfo.static.ParseOption(Options, ParseString);
|
||||
|
||||
if (InOpt != "")
|
||||
{
|
||||
return bool(InOpt);
|
||||
}
|
||||
|
||||
//If a value for this variable was not specified in the launch command, return the original value.
|
||||
return CurrentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
*** @brief Gets a String from the launch command if available.
|
||||
***
|
||||
*** @param Options - options passed in via the launch command
|
||||
*** @param ParseString - the variable we are looking for
|
||||
*** @param CurrentValue - the current value of the variable
|
||||
*** @return String value of the option we are looking for
|
||||
***/
|
||||
static public function String GetStringOption(String Options, String ParseString, String CurrentValue)
|
||||
{
|
||||
local String InOpt;
|
||||
|
||||
//Find the value associated with this variable in the launch command.
|
||||
InOpt = GameInfo.static.ParseOption(Options, ParseString);
|
||||
|
||||
if (InOpt != "")
|
||||
{
|
||||
return InOpt;
|
||||
}
|
||||
|
||||
//If a value for this variable was not specified in the launch command, return the original value.
|
||||
return CurrentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
*** @brief Gets a LogLevel from the launch command if available.
|
||||
***
|
||||
*** @param Options - options passed in via the launch command
|
||||
*** @param ParseString - the variable we are looking for
|
||||
*** @param CurrentValue - the current value of the variable
|
||||
*** @return E_LogLevel value of the option we are looking for
|
||||
***/
|
||||
static public function E_LogLevel GetLogLevelOption(String Options, String ParseString, E_LogLevel CurrentValue)
|
||||
{
|
||||
local String InOpt;
|
||||
|
||||
//Find the value associated with this variable in the launch command.
|
||||
InOpt = GameInfo.static.ParseOption(Options, ParseString);
|
||||
|
||||
if (InOpt != "")
|
||||
{
|
||||
return class'_Logger'.static.LogLevelFromString(InOpt, CurrentValue);
|
||||
}
|
||||
|
||||
return CurrentValue;
|
||||
}
|
@ -1,16 +1,6 @@
|
||||
class StartWave extends Info
|
||||
class StartWave extends KFMutator
|
||||
config(StartWave);
|
||||
|
||||
const OptionsParser = class'OptionsParser';
|
||||
|
||||
var private KFGameInfo KFGI;
|
||||
var private KFGameInfo_Survival KFGIS;
|
||||
var private KFGameInfo_Endless KFGIE;
|
||||
|
||||
var private KFGI_Access KFGIA;
|
||||
|
||||
var private KFGameReplicationInfo KFGRI;
|
||||
|
||||
/*********************************************************************************************************
|
||||
* Config properties
|
||||
*********************************************************************************************************/
|
||||
@ -25,13 +15,12 @@ var config int TraderTime;
|
||||
var config int Dosh;
|
||||
/** Whether an 'initial' trader time should occur before the first wave. */
|
||||
var config bool bStartWithTrader;
|
||||
/** Log level. */
|
||||
var config E_LogLevel LogLevel;
|
||||
|
||||
/** Whether mod-specific events should be logged. */
|
||||
var config bool bUseDebug;
|
||||
/**
|
||||
*** The boss override index. For the default boss list, 0-Hans, 1-Patty, 2-King FP, 3-Abomination.
|
||||
*** Negative values can be used to keep the boss spawn random.
|
||||
***/
|
||||
* The boss override index. For the default boss list, 0-Hans, 1-Patty, 2-King FP, 3-Abomination. Negative
|
||||
* values can be used to keep the boss spawn random.
|
||||
*/
|
||||
var config int Boss;
|
||||
|
||||
/*********************************************************************************************************
|
||||
@ -47,125 +36,40 @@ var bool bOverridenDifficultySettings;
|
||||
/** Whether the trader duration has been overriden. */
|
||||
var bool bOverridenTraderDuration;
|
||||
|
||||
public simulated function bool SafeDestroy()
|
||||
function InitMutator(string Options, out string ErrorMessage)
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
return (bPendingDelete || bDeleteMe || Destroy());
|
||||
}
|
||||
|
||||
public event PreBeginPlay()
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
if (WorldInfo.NetMode == NM_Client)
|
||||
{
|
||||
`Log_Fatal("Wrong NetMode:" @ WorldInfo.NetMode);
|
||||
SafeDestroy();
|
||||
return;
|
||||
}
|
||||
|
||||
Super.PreBeginPlay();
|
||||
|
||||
PreInit();
|
||||
}
|
||||
|
||||
public event PostBeginPlay()
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
if (bPendingDelete || bDeleteMe) return;
|
||||
|
||||
Super.PostBeginPlay();
|
||||
|
||||
PostInit();
|
||||
}
|
||||
|
||||
private function PreInit()
|
||||
{
|
||||
local String URL;
|
||||
local String Options;
|
||||
|
||||
`Log_Trace();
|
||||
|
||||
URL = WorldInfo.GetLocalURL();
|
||||
Options = Mid(URL, InStr(URL, "?"));
|
||||
//This needs to be called first since KFMutator.InitMutator sets the MyKFGI reference.
|
||||
Super.InitMutator(Options, ErrorMessage);
|
||||
|
||||
//Parse options entered via the launch command.
|
||||
//We further restrict StartWave later when we know the maximum wave number for the selected game length.
|
||||
StartWave = OptionsParser.static.GetIntOption (Options, "StartWave", StartWave);
|
||||
InitialTraderTime = OptionsParser.static.GetIntOption (Options, "InitialTraderTime", InitialTraderTime);
|
||||
TraderTime = OptionsParser.static.GetIntOption (Options, "TraderTime", TraderTime);
|
||||
Dosh = OptionsParser.static.GetIntOption (Options, "Dosh", Dosh);
|
||||
Boss = OptionsParser.static.GetIntOption (Options, "Boss", Boss);
|
||||
bStartWithTrader = OptionsParser.static.GetBoolOption (Options, "bStartWithTrader", bStartWithTrader);
|
||||
LogLevel = OptionsParser.static.GetLogLevelOption(Options, "LogLevel", LogLevel);
|
||||
|
||||
// Adjust values if needed
|
||||
StartWave = Max(StartWave, 1);
|
||||
InitialTraderTime = Max(InitialTraderTime, 1);
|
||||
TraderTime = Max(TraderTime, 1);
|
||||
Dosh = Max(Dosh, 0);
|
||||
StartWave = Max(class'GameInfo'.static.GetIntOption(Options, "StartWave", StartWave), 1);
|
||||
InitialTraderTime = Max(class'GameInfo'.static.GetIntOption(Options, "InitialTraderTime",
|
||||
InitialTraderTime), 1);
|
||||
TraderTime = Max(class'GameInfo'.static.GetIntOption(Options, "TraderTime", TraderTime), 1);
|
||||
Dosh = Max(class'GameInfo'.static.GetIntOption(Options, "Dosh", Dosh), 0);
|
||||
Boss = class'GameInfo'.static.GetIntOption(Options, "Boss", Boss);
|
||||
bStartWithTrader = GetBoolOption(Options, "bStartWithTrader", bStartWithTrader);
|
||||
bUseDebug = GetBoolOption(Options, "bUseDebug", bUseDebug);
|
||||
|
||||
//DEBUG
|
||||
`Log_Info("LogLevel:" @ LogLevel);
|
||||
`Log_Info("StartWave:" @ StartWave);
|
||||
`Log_Info("InitialTraderTime:" @ InitialTraderTime);
|
||||
`Log_Info("TraderTime:" @ TraderTime);
|
||||
`Log_Info("Dosh:" @ Dosh);
|
||||
`Log_Info("Boss:" @ Boss);
|
||||
`Log_Info("bStartWithTrader:" @ bStartWithTrader);
|
||||
`log("StartWave: "$StartWave, bUseDebug, 'StartWave');
|
||||
`log("InitialTraderTime: "$InitialTraderTime, bUseDebug, 'StartWave');
|
||||
`log("TraderTime: "$TraderTime, bUseDebug, 'StartWave');
|
||||
`log("Dosh: "$Dosh, bUseDebug, 'StartWave');
|
||||
`log("Boss: "$Boss, bUseDebug, 'StartWave');
|
||||
`log("bStartWithTrader: "$bStartWithTrader, bUseDebug, 'StartWave');
|
||||
|
||||
bOverridenDifficultySettings = false;
|
||||
bOverridenTraderDuration = false;
|
||||
}
|
||||
|
||||
private function PostInit()
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
if (WorldInfo.Game == None || WorldInfo.GRI == None)
|
||||
{
|
||||
SetTimer(0.2, false, nameof(PostInit));
|
||||
return;
|
||||
}
|
||||
|
||||
KFGI = KFGameInfo(WorldInfo.Game);
|
||||
if (KFGI == None)
|
||||
{
|
||||
`Log_Fatal("Incompatible gamemode:" @ WorldInfo.Game $ ". Destroy...");
|
||||
SafeDestroy();
|
||||
return;
|
||||
}
|
||||
|
||||
KFGIA = new(KFGI) class'KFGI_Access';
|
||||
if (KFGIA == None)
|
||||
{
|
||||
`Log_Fatal("Can't create KFGI_Access object");
|
||||
SafeDestroy();
|
||||
return;
|
||||
}
|
||||
|
||||
KFGIS = KFGameInfo_Survival(KFGI);
|
||||
if (KFGIS == None)
|
||||
{
|
||||
`Log_Warn("The game mode does not extend KFGameInfo_Survival. Most features of this mutator are not compatible with non-wave-based game modes.");
|
||||
}
|
||||
|
||||
KFGIE = KFGameInfo_Endless(KFGIS);
|
||||
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
|
||||
if (KFGRI == None)
|
||||
{
|
||||
`Log_Fatal("Incompatible game replication info:" @ WorldInfo.GRI $ ". Destroy...");
|
||||
SafeDestroy();
|
||||
return;
|
||||
}
|
||||
|
||||
SetTimer(0.1, false, nameof(OverrideTimer));
|
||||
|
||||
//Override the boss with the boss corresponding to the specified boss index. -1 signifies random.
|
||||
KFGIA.OverrideBossIndex(Boss);
|
||||
if(Boss != -1)
|
||||
{
|
||||
SetTimer(0.1, false, nameof(OverrideBoss));
|
||||
}
|
||||
|
||||
CheckForceInitialTrader();
|
||||
|
||||
@ -173,30 +77,28 @@ private function PostInit()
|
||||
bInitialTrader = bStartWithTrader;
|
||||
|
||||
//If we want to start with the trader active or alter the starting wave number.
|
||||
if (bStartWithTrader || StartWave > 1)
|
||||
if(bStartWithTrader || StartWave > 1)
|
||||
{
|
||||
`Log_Debug("Calling StartWaveTimer() to alter the start wave or activate the trader initially.");
|
||||
`log("Calling StartWaveTimer() to alter the start wave or activate the trader initially.",
|
||||
bUseDebug, 'StartWave');
|
||||
SetTimer(0.2, false, nameof(StartWaveTimer));
|
||||
}
|
||||
|
||||
//If we will need to alter TimeBetweenWaves for later activations of the trader.
|
||||
if (bStartWithTrader && InitialTraderTime != TraderTime)
|
||||
if(bStartWithTrader && InitialTraderTime != TraderTime)
|
||||
{
|
||||
`Log_Debug("Calling UpdateTraderDurationTimer() to alter the trader duration later.");
|
||||
`log("Calling UpdateTraderDurationTimer() to alter the trader duration later.", bUseDebug,
|
||||
'StartWave');
|
||||
SetTimer(1, true, nameof(UpdateTraderDurationTimer));
|
||||
}
|
||||
|
||||
`Log_Info("Initialized.");
|
||||
}
|
||||
|
||||
/** Allows for handling player input in the console by the mutator. */
|
||||
public function Mutate(string MutateString, PlayerController Sender)
|
||||
function Mutate(string MutateString, PlayerController Sender)
|
||||
{
|
||||
local array<string> CommandBreakdown;
|
||||
|
||||
`Log_Trace();
|
||||
|
||||
if (MutateString == "")
|
||||
if(MutateString == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -205,15 +107,13 @@ public function Mutate(string MutateString, PlayerController Sender)
|
||||
ParseStringIntoArray(MutateString, CommandBreakdown, " ", true);
|
||||
|
||||
//The CheatManager check is equivalent to checking if cheats are enabled for that player.
|
||||
if (CommandBreakdown.Length > 1&&
|
||||
CommandBreakdown[0] == "setwave" &&
|
||||
Sender.CheatManager != None &&
|
||||
KFGI.GetLivingPlayerCount() > 0)
|
||||
if(CommandBreakdown.Length > 1 && CommandBreakdown[0] == "setwave" && Sender.CheatManager != None &&
|
||||
MyKFGI.GetLivingPlayerCount() > 0)
|
||||
{
|
||||
//The setwave command should be: mutate setwave WaveNum bSkipTraderTime
|
||||
//where WaveNum is an integer (or byte) and bSkipTraderTime is a bool.
|
||||
|
||||
if (CommandBreakdown.Length == 2)
|
||||
if(CommandBreakdown.Length == 2)
|
||||
{
|
||||
SetWave(int(CommandBreakdown[1]), Sender);
|
||||
}
|
||||
@ -222,23 +122,23 @@ public function Mutate(string MutateString, PlayerController Sender)
|
||||
SetWave(int(CommandBreakdown[1]), Sender, bool(CommandBreakdown[2]));
|
||||
}
|
||||
}
|
||||
|
||||
Super.Mutate(MutateString, Sender);
|
||||
}
|
||||
|
||||
/** Jumps to the specified wave, NewWaveNum, with trader time iff bSkipTraderTime is false. */
|
||||
private function SetWave(int NewWaveNum, PlayerController PC, optional bool bSkipTraderTime)
|
||||
function SetWave(int NewWaveNum, PlayerController PC, optional bool bSkipTraderTime)
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
if (NewWaveNum < 1)
|
||||
if(NewWaveNum < 1)
|
||||
{
|
||||
`Log_Error("SetWave: new wave num must be > 0.");
|
||||
`log("SetWave: new wave num must be > 0.", true, 'StartWave');
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFGIE != None)
|
||||
if(KFGameInfo_Endless(MyKFGI) != None)
|
||||
{
|
||||
//Jump straight to the final wave if the specified wave number is higher than wave max.
|
||||
if (NewWaveNum > 254)
|
||||
if(NewWaveNum > 254)
|
||||
{
|
||||
NewWaveNum = 254;
|
||||
}
|
||||
@ -246,261 +146,325 @@ private function SetWave(int NewWaveNum, PlayerController PC, optional bool bSki
|
||||
else
|
||||
{
|
||||
//Jump straight to the boss wave if the specified wave number is higher than wave max.
|
||||
if (NewWaveNum > KFGIS.WaveMax)
|
||||
if(NewWaveNum > KFGameInfo_Survival(MyKFGI).WaveMax)
|
||||
{
|
||||
NewWaveNum = KFGIS.WaveMax+1;
|
||||
NewWaveNum = KFGameInfo_Survival(MyKFGI).WaveMax+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (KFGIS != None)
|
||||
{
|
||||
KFGIS.WaveNum = NewWaveNum - 1;
|
||||
}
|
||||
KFGameInfo_Survival(MyKFGI).WaveNum = NewWaveNum - 1;
|
||||
|
||||
//Kill all zeds currently alive.
|
||||
KillZeds();
|
||||
PC.ConsoleCommand("KillZeds");
|
||||
|
||||
//Clear any current objectives.
|
||||
KFGRI.DeactivateObjective();
|
||||
MyKFGI.MyKFGRI.DeactivateObjective();
|
||||
|
||||
if (bSkipTraderTime)
|
||||
if(bSkipTraderTime)
|
||||
{
|
||||
//Go to some unused state so that PlayingWave.BeginState is called when we go to PlayingWave.
|
||||
KFGI.GotoState('TravelTheWorld');
|
||||
MyKFGI.GotoState('TravelTheWorld');
|
||||
|
||||
UpdateEndlessDifficulty();
|
||||
|
||||
//Go to PlayingWave to start the new wave.
|
||||
KFGI.GotoState('PlayingWave');
|
||||
MyKFGI.GotoState('PlayingWave');
|
||||
}
|
||||
else
|
||||
{
|
||||
//Go to trader time before starting the new wave.
|
||||
KFGI.GotoState('TraderOpen');
|
||||
MyKFGI.GotoState('TraderOpen');
|
||||
|
||||
UpdateEndlessDifficulty();
|
||||
}
|
||||
|
||||
KFGI.ResetAllPickups();
|
||||
MyKFGI.ResetAllPickups();
|
||||
}
|
||||
|
||||
/**
|
||||
*** Since the difficulty in Endless scales with the wave number, we need to update the difficulty when
|
||||
*** jumping between wave numbers to match the expected difficulty.
|
||||
***/
|
||||
private function UpdateEndlessDifficulty()
|
||||
* Since the difficulty in Endless scales with the wave number, we need to update the difficulty when
|
||||
* jumping between wave numbers to match the expected difficulty.
|
||||
*/
|
||||
function UpdateEndlessDifficulty()
|
||||
{
|
||||
local KFGameInfo_Endless Endless;
|
||||
local int i;
|
||||
|
||||
`Log_Trace();
|
||||
Endless = KFGameInfo_Endless(MyKFGI);
|
||||
|
||||
if (KFGIE == None)
|
||||
if(Endless == None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// KFGIE.ResetDifficulty() does not reset ModifiedDifficulty, so do it manually
|
||||
KFGRI.SetModifiedGameDifficulty(0);
|
||||
KFGI.GameDifficultyModifier = 0;
|
||||
|
||||
//Reflects the difficulty update in KFGameInfo_Endless.SetWave.
|
||||
KFGIE.bIsInHoePlus = false;
|
||||
KFGIE.ResetDifficulty();
|
||||
KFGIE.SpawnManager.GetWaveSettings(KFGIE.SpawnManager.WaveSettings);
|
||||
KFGIE.UpdateGameSettings();
|
||||
Endless.bIsInHoePlus = false;
|
||||
Endless.ResetDifficulty();
|
||||
Endless.SpawnManager.GetWaveSettings(Endless.SpawnManager.WaveSettings);
|
||||
Endless.UpdateGameSettings();
|
||||
|
||||
//Don't bother iterating for i=0-4, no difficulty increment can occur.
|
||||
for (i = 5; i <= KFGIE.WaveNum; ++i)
|
||||
for(i = 5; i < Endless.WaveNum; ++i)
|
||||
{
|
||||
//Simulate the death of a boss. The difficulty is incremented after each boss round.
|
||||
if (i % 5 == 0)
|
||||
if(i % 5 == 0)
|
||||
{
|
||||
KFGIE.IncrementDifficulty();
|
||||
Endless.IncrementDifficulty();
|
||||
}
|
||||
|
||||
//This should happen at the end of each wave (if we're in HoE+). The check is handled internally.
|
||||
//We do this after the simulation of a boss death so that bIsInHoePlus can be set first.
|
||||
KFGIE.HellOnEarthPlusRoundIncrement();
|
||||
Endless.HellOnEarthPlusRoundIncrement();
|
||||
}
|
||||
|
||||
`Log_Debug("Updated difficulty (Game + Modifier):" @ String(KFGRI.GameDifficulty) @ "+" @ String(KFGRI.GameDifficultyModifier));
|
||||
}
|
||||
|
||||
/** Checks whether we should force the initial trader, regardless of the config/command value. */
|
||||
private function CheckForceInitialTrader()
|
||||
function CheckForceInitialTrader()
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
//Force the initial trader for compatibility with holdout maps. Otherwise, zeds spawn in the wrong room.
|
||||
if (!bStartWithTrader && StartWave > 1)
|
||||
if(!bStartWithTrader && StartWave > 1)
|
||||
{
|
||||
bStartWithTrader = true;
|
||||
InitialTraderTime = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Overrides difficulty settings and trader duration when possible. */
|
||||
private function OverrideTimer()
|
||||
/** Overrides the boss to spawn if a valid boss index has been specified. */
|
||||
function OverrideBoss()
|
||||
{
|
||||
local KFGameDifficulty_Endless KFGDE;
|
||||
local int i;
|
||||
local bool bHalt;
|
||||
local byte MaxIters, i, MaxSameIters, PrevIndex, SameIters;
|
||||
|
||||
`Log_Trace();
|
||||
|
||||
//If we've overriden what we need to, don't call this timer again.
|
||||
if (bOverridenDifficultySettings && bOverridenTraderDuration)
|
||||
//We need a valid KFGRI reference as we use its public BossIndex field.
|
||||
if(MyKFGI.MyKFGRI == None)
|
||||
{
|
||||
`Log_Debug("All settings have been overriden.");
|
||||
SetTimer(0.2, false, nameof(OverrideBoss));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bOverridenDifficultySettings && KFGI.DifficultyInfo != None)
|
||||
//Unfortunately, we cannot directly set the boss index since KFGameInfo.BossIndex is protected. The only
|
||||
//way we can affect BossIndex is through KFGameInfo.SetBossIndex which randomly chooses a value in the
|
||||
//valid range. So we have to continue calling SetBossIndex until the desired index has been chosen. We
|
||||
//can verify this by checking KFGameReplicationInfo.BossIndex because that is public.
|
||||
|
||||
i = 0;
|
||||
MaxIters = 100;
|
||||
|
||||
//Since some events/maps could force a specific boss to be spawned (see KFGameInfo.SetBossIndex), we
|
||||
//should check whether the index hasn't changed after several iterations. If it stays the same for a
|
||||
//while we assume the index is forced, in which case we can't do anything about it.
|
||||
SameIters = 0;
|
||||
MaxSameIters = 10;
|
||||
PrevIndex = MyKFGI.MyKFGRI.BossIndex;
|
||||
|
||||
bHalt = Boss < 0 || MyKFGI.MyKFGRI.BossIndex == Boss;
|
||||
|
||||
while(!bHalt)
|
||||
{
|
||||
`Log_Debug("Overriding difficulty settings...");
|
||||
++i;
|
||||
|
||||
//Randomly select a new boss.
|
||||
MyKFGI.SetBossIndex();
|
||||
|
||||
//Track whether the boss index is changing.
|
||||
if(MyKFGI.MyKFGRI.BossIndex == PrevIndex)
|
||||
{
|
||||
++SameIters;
|
||||
}
|
||||
else
|
||||
{
|
||||
SameIters = 0;
|
||||
PrevIndex = MyKFGI.MyKFGRI.BossIndex;
|
||||
}
|
||||
|
||||
//Halt if we have the desired index or we have tried enough times.
|
||||
bHalt = MyKFGI.MyKFGRI.BossIndex == Boss || SameIters >= MaxSameIters || i >= MaxIters;
|
||||
}
|
||||
|
||||
if(MyKFGI.MyKFGRI.BossIndex == Boss)
|
||||
{
|
||||
`log("Successfully overrode boss index to "$Boss$" after "$i$" attempts.", bUseDebug, 'StartWave');
|
||||
}
|
||||
else
|
||||
{
|
||||
`log("Failed to override boss index after "$i$" attempts.", bUseDebug, 'StartWave');
|
||||
}
|
||||
}
|
||||
|
||||
/** Overrides difficulty settings and trader duration when possible. */
|
||||
function OverrideTimer()
|
||||
{
|
||||
local KFGameInfo_Survival KFGI_Surv;
|
||||
local KFGameInfo_Endless KFGI_Endl;
|
||||
local KFGameDifficulty_Endless KFGD_Endl;
|
||||
local int i;
|
||||
|
||||
//If we've overriden what we need to, don't call this timer again.
|
||||
if(bOverridenDifficultySettings && bOverridenTraderDuration)
|
||||
{
|
||||
`log("All settings have been overriden.", bUseDebug, 'StartWave');
|
||||
return;
|
||||
}
|
||||
|
||||
if(!bOverridenDifficultySettings && MyKFGI.DifficultyInfo != None)
|
||||
{
|
||||
`log("Overriding difficulty settings...", bUseDebug, 'StartWave');
|
||||
|
||||
bOverridenDifficultySettings = true;
|
||||
|
||||
//Override starting dosh.
|
||||
KFGI.DifficultyInfo.Normal.StartingDosh = Dosh;
|
||||
KFGI.DifficultyInfo.Hard.StartingDosh = Dosh;
|
||||
KFGI.DifficultyInfo.Suicidal.StartingDosh = Dosh;
|
||||
KFGI.DifficultyInfo.HellOnEarth.StartingDosh = Dosh;
|
||||
MyKFGI.DifficultyInfo.Normal.StartingDosh = Dosh;
|
||||
MyKFGI.DifficultyInfo.Hard.StartingDosh = Dosh;
|
||||
MyKFGI.DifficultyInfo.Suicidal.StartingDosh = Dosh;
|
||||
MyKFGI.DifficultyInfo.HellOnEarth.StartingDosh = Dosh;
|
||||
|
||||
if (KFGIE != None)
|
||||
KFGI_Endl = KFGameInfo_Endless(MyKFGI);
|
||||
if (KFGI_Endl != None)
|
||||
{
|
||||
KFGDE = KFGameDifficulty_Endless(KFGIE.DifficultyInfo);
|
||||
if (KFGDE != None)
|
||||
KFGD_Endl = KFGameDifficulty_Endless(KFGI_Endl.DifficultyInfo);
|
||||
if (KFGD_Endl != None)
|
||||
{
|
||||
for (i = 0; i < KFGDE.CurrentDifficultyScaling.Difficulties.length; ++i)
|
||||
for (i = 0; i < KFGD_Endl.CurrentDifficultyScaling.Difficulties.length; ++i)
|
||||
{
|
||||
KFGDE.CurrentDifficultyScaling.Difficulties[i].StartingDosh = Dosh;
|
||||
KFGD_Endl.CurrentDifficultyScaling.Difficulties[i].StartingDosh = Dosh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`Log_Debug("Starting dosh has been set to:" @ Dosh @ "dosh.");
|
||||
`log("Starting dosh has been set to: "$Dosh$" dosh.", bUseDebug, 'StartWave');
|
||||
|
||||
//We need to set the difficulty settings again - normally done in KFGameInfo.InitGame - to apply
|
||||
//these changes, since this happens after InitGame is executed.
|
||||
KFGI.DifficultyInfo.SetDifficultySettings(KFGI.GameDifficulty);
|
||||
MyKFGI.DifficultyInfo.SetDifficultySettings(MyKFGI.GameDifficulty);
|
||||
}
|
||||
|
||||
//Set the starting wave number.
|
||||
if (!bOverridenTraderDuration)
|
||||
if(!bOverridenTraderDuration)
|
||||
{
|
||||
if (KFGIS != None)
|
||||
KFGI_Surv = KFGameInfo_Survival(MyKFGI);
|
||||
|
||||
if(KFGI_Surv != None)
|
||||
{
|
||||
//We require the SpawnManager to be set, because this signifies that InitSpawnManager has been
|
||||
//executed, which sets WaveMax.
|
||||
if (KFGI.SpawnManager != None)
|
||||
if(MyKFGI.SpawnManager != None)
|
||||
{
|
||||
`Log_Debug("Overriding trader duration...");
|
||||
`log("Overriding trader duration...", bUseDebug, 'StartWave');
|
||||
|
||||
bOverridenTraderDuration = true;
|
||||
|
||||
//Since InitSpawnManager has been executed, then PreBeginPlay must have been executed. This
|
||||
//means that PostBeginPlay will have been executed as well since it happens straight after.
|
||||
//Now we can override TimeBetweenWaves.
|
||||
KFGIS.TimeBetweenWaves = bInitialTrader ? InitialTraderTime : TraderTime;
|
||||
KFGI_Surv.TimeBetweenWaves = bInitialTrader ? InitialTraderTime : TraderTime;
|
||||
|
||||
`Log_Debug("Trader duration has been set to:" @ KFGIS.TimeBetweenWaves @ "seconds.");
|
||||
`log("Trader duration has been set to: "$KFGI_Surv.TimeBetweenWaves$" seconds.", bUseDebug,
|
||||
'StartWave');
|
||||
}
|
||||
else
|
||||
{
|
||||
`Log_Debug("KFGI.SpawnManager hasn't been set yet. Calling StartWaveTimer again.");
|
||||
`log("MyKFGI.SpawnManager hasn't been set yet. Calling StartWaveTimer again.", bUseDebug,
|
||||
'StartWave');
|
||||
|
||||
//We don't know WaveMax yet, so we need to wait longer.
|
||||
SetTimer(0.1, false, nameof(StartWaveTimer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
`warn("The game mode does not extend KFGameInfo_Survival. Most features of this mutator are not"
|
||||
$"compatible with non-wave-based game modes.", true, 'StartWave');
|
||||
}
|
||||
}
|
||||
|
||||
//If the difficulty info isn't set yet, wait.
|
||||
SetTimer(0.1, false, nameof(OverrideTimer));
|
||||
}
|
||||
|
||||
private function StartWaveTimer()
|
||||
function StartWaveTimer()
|
||||
{
|
||||
local KFGameInfo_Survival KFGI_Surv;
|
||||
local PlayerController PC;
|
||||
|
||||
`Log_Trace();
|
||||
|
||||
//We need to wait for the wave to be active, as this will signify that StartMatch has been executed.
|
||||
if (!KFGI.IsWaveActive())
|
||||
if(!MyKFGI.IsWaveActive())
|
||||
{
|
||||
//If the wave isn't active yet (probably still in lobby), wait.
|
||||
SetTimer(0.1, false, nameof(StartWaveTimer));
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFGIS == None)
|
||||
KFGI_Surv = KFGameInfo_Survival(MyKFGI);
|
||||
|
||||
if(KFGI_Surv == None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
`Log_Debug("Clearing the current wave.");
|
||||
`log("Clearing the current wave.", bUseDebug, 'StartWave');
|
||||
|
||||
//Clear the current wave.
|
||||
foreach WorldInfo.AllControllers(class'PlayerController', PC)
|
||||
{
|
||||
if (KFDemoRecSpectator(PC) == none)
|
||||
{
|
||||
KillZeds();
|
||||
PC.ConsoleCommand("KillZeds");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Set the starting wave number.
|
||||
//Keep the assignments separated so that we can used the restricted StartWave later if we want.
|
||||
StartWave = Min(StartWave, KFGIS.WaveMax);
|
||||
StartWave = Min(StartWave, KFGI_Surv.WaveMax);
|
||||
//We need to subtract 1 because when the state is eventually reset to PlayingWave, this will be
|
||||
//incremented by 1.
|
||||
KFGIS.WaveNum = StartWave - 1;
|
||||
KFGI_Surv.WaveNum = StartWave - 1;
|
||||
|
||||
UpdateEndlessDifficulty();
|
||||
`log("WaveNum set to: "$KFGI_Surv.WaveNum, bUseDebug, 'StartWave');
|
||||
|
||||
`Log_Info("WaveNum set to:" @ KFGIS.WaveNum);
|
||||
|
||||
if (bStartWithTrader)
|
||||
if(bStartWithTrader)
|
||||
{
|
||||
`Log_Debug("Switching to state: TraderOpen.");
|
||||
`log("Switching to state: TraderOpen.", bUseDebug, 'StartWave');
|
||||
|
||||
//We need to update GRI's WaveNum and update the HUD element that shows the last wave.
|
||||
KFGRI.WaveNum = KFGIS.WaveNum;
|
||||
KFGRI.UpdateHUDWaveCount();
|
||||
MyKFGI.MyKFGRI.WaveNum = KFGI_Surv.WaveNum;
|
||||
MyKFGI.MyKFGRI.UpdateHUDWaveCount();
|
||||
|
||||
//Start with the trader active.
|
||||
KFGI.GotoState('TraderOpen', 'Begin');
|
||||
MyKFGI.GotoState('TraderOpen', 'Begin');
|
||||
}
|
||||
else
|
||||
{
|
||||
`Log_Debug("Switching to state: PlayingWave.");
|
||||
`log("Switching to state: PlayingWave.", bUseDebug, 'StartWave');
|
||||
|
||||
//Start with a wave as usual - but our StartWave number will be used.
|
||||
KFGI.GotoState('PlayingWave');
|
||||
MyKFGI.GotoState('PlayingWave');
|
||||
}
|
||||
|
||||
//Since we've updated the wave number, we need to update the game settings (which includes the
|
||||
//current wave number).
|
||||
KFGI.UpdateGameSettings();
|
||||
MyKFGI.UpdateGameSettings();
|
||||
|
||||
bInitialTrader = false;
|
||||
}
|
||||
|
||||
/** Updates the trader duration. Waits until the initial trader has closed. */
|
||||
private function UpdateTraderDurationTimer()
|
||||
function UpdateTraderDurationTimer()
|
||||
{
|
||||
`Log_Trace();
|
||||
|
||||
//If the initial trader has already been opened, and the wave is now active.
|
||||
if (!bInitialTrader && KFGI.IsWaveActive())
|
||||
if(!bInitialTrader && MyKFGI.IsWaveActive())
|
||||
{
|
||||
if (KFGIS != None)
|
||||
if(KFGameInfo_Survival(MyKFGI) != None)
|
||||
{
|
||||
`Log_Debug("Updating trader duration to" @ TraderTime @ "seconds.");
|
||||
`log("Updating trader duration to "$TraderTime$" seconds.", bUseDebug, 'StartWave');
|
||||
//We can update TimeBetweenWaves to be the TraderTime we specified in the launch command.
|
||||
KFGIS.TimeBetweenWaves = TraderTime;
|
||||
KFGameInfo_Survival(MyKFGI).TimeBetweenWaves = TraderTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
`warn("The game mode does not extend KFGameInfo_Survival. Most features of this mutator are not"
|
||||
$"compatible with non-wave-based game modes.", true, 'StartWave');
|
||||
}
|
||||
|
||||
//We don't need to call this timer again.
|
||||
@ -508,22 +472,50 @@ private function UpdateTraderDurationTimer()
|
||||
}
|
||||
}
|
||||
|
||||
private function KillZeds()
|
||||
/**
|
||||
* @brief Gets a bool from the launch command if available.
|
||||
*
|
||||
* @param Options - options passed in via the launch command
|
||||
* @param ParseString - the variable we are looking for
|
||||
* @param CurrentValue - the current value of the variable
|
||||
* @return bool value of the option we are looking for
|
||||
*/
|
||||
static function bool GetBoolOption(string Options, string ParseString, bool CurrentValue)
|
||||
{
|
||||
local KFPawn_Monster KFPM;
|
||||
local string InOpt;
|
||||
|
||||
foreach WorldInfo.AllPawns(class'KFPawn_Monster', KFPM)
|
||||
{
|
||||
if (!KFPM.IsAliveAndWell()) continue;
|
||||
//Find the value associated with this variable in the launch command.
|
||||
InOpt = class'GameInfo'.static.ParseOption(Options, ParseString);
|
||||
|
||||
if (KFPM.Health > 0 && PlayerController(KFPM.Controller) == None)
|
||||
if(InOpt != "")
|
||||
{
|
||||
KFPM.Died(None, None, KFPM.Location);
|
||||
}
|
||||
return bool(InOpt);
|
||||
}
|
||||
|
||||
//If a value for this variable was not specified in the launch command, return the original value.
|
||||
return CurrentValue;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
/**
|
||||
* @brief Gets a string from the launch command if available.
|
||||
*
|
||||
* @param Options - options passed in via the launch command
|
||||
* @param ParseString - the variable we are looking for
|
||||
* @param CurrentValue - the current value of the variable
|
||||
* @return string value of the option we are looking for
|
||||
*/
|
||||
static function string GetStringOption(string Options, string ParseString, string CurrentValue)
|
||||
{
|
||||
local string InOpt;
|
||||
|
||||
//Find the value associated with this variable in the launch command.
|
||||
InOpt = class'GameInfo'.static.ParseOption(Options, ParseString);
|
||||
|
||||
if(InOpt != "")
|
||||
{
|
||||
return InOpt;
|
||||
}
|
||||
|
||||
//If a value for this variable was not specified in the launch command, return the original value.
|
||||
return CurrentValue;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
[Flags]
|
||||
AllowDownload=False
|
||||
ClientOptional=False
|
||||
ServerSideOnly=True
|
@ -1 +0,0 @@
|
||||
class StartWaveMut extends Mut; // backward compatibility
|
@ -1,74 +0,0 @@
|
||||
class _Logger extends Object
|
||||
abstract;
|
||||
|
||||
enum E_LogLevel
|
||||
{
|
||||
LL_WrongLevel,
|
||||
LL_None,
|
||||
LL_Fatal,
|
||||
LL_Error,
|
||||
LL_Warning,
|
||||
LL_Info,
|
||||
LL_Debug,
|
||||
LL_Trace,
|
||||
LL_All
|
||||
};
|
||||
|
||||
public static function E_LogLevel LogLevelFromString(String LogLevel, optional E_LogLevel DefaultLogLevel)
|
||||
{
|
||||
switch (LogLevel)
|
||||
{
|
||||
case "0":
|
||||
case "WrongLevel":
|
||||
case "LL_WrongLevel":
|
||||
return LL_WrongLevel;
|
||||
|
||||
case "1":
|
||||
case "None":
|
||||
case "LL_None":
|
||||
return LL_None;
|
||||
|
||||
case "2":
|
||||
case "Fatal":
|
||||
case "LL_Fatal":
|
||||
return LL_Fatal;
|
||||
|
||||
case "3":
|
||||
case "Error":
|
||||
case "LL_Error":
|
||||
return LL_Error;
|
||||
|
||||
case "4":
|
||||
case "Warning":
|
||||
case "LL_Warning":
|
||||
return LL_Warning;
|
||||
|
||||
case "5":
|
||||
case "Info":
|
||||
case "LL_Info":
|
||||
return LL_Info;
|
||||
|
||||
case "6":
|
||||
case "Debug":
|
||||
case "LL_Debug":
|
||||
return LL_Debug;
|
||||
|
||||
case "7":
|
||||
case "Trace":
|
||||
case "LL_Trace":
|
||||
return LL_Trace;
|
||||
|
||||
case "8":
|
||||
case "All":
|
||||
case "LL_All":
|
||||
return LL_All;
|
||||
|
||||
default:
|
||||
return DefaultLogLevel;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
// Imports
|
||||
`include(Logger.uci)
|
@ -1,15 +0,0 @@
|
||||
// Logger
|
||||
`define Log_Tag 'StartWave'
|
||||
|
||||
`define LocationStatic "`{ClassName}::" $ GetFuncName()
|
||||
|
||||
`define Log_Base(msg, cond) `log(`msg `if(`cond), `cond`{endif}, `Log_Tag)
|
||||
|
||||
`define Log_Fatal(msg) `log("FATAL:" @ `msg, (LogLevel >= LL_Fatal), `Log_Tag)
|
||||
`define Log_Error(msg) `log("ERROR:" @ `msg, (LogLevel >= LL_Error), `Log_Tag)
|
||||
`define Log_Warn(msg) `log("WARN:" @ `msg, (LogLevel >= LL_Warning), `Log_Tag)
|
||||
`define Log_Info(msg) `log("INFO:" @ `msg, (LogLevel >= LL_Info), `Log_Tag)
|
||||
`define Log_Debug(msg) `log("DEBUG:" @ `msg, (LogLevel >= LL_Debug), `Log_Tag)
|
||||
|
||||
`define Log_Trace(msg) `log("TRACE:" @ `Location `if(`msg) @ `msg`{endif}, (LogLevel >= LL_Trace), `Log_Tag)
|
||||
`define Log_TraceStatic(msg) `log("TRACE:" @ `LocationStatic `if(`msg) @ `msg`{endif}, (LogLevel >= LL_Trace), `Log_Tag)
|
16
build.cfg
Normal file
16
build.cfg
Normal file
@ -0,0 +1,16 @@
|
||||
# Build parameters
|
||||
|
||||
# If True - compresses the mutator when compiling
|
||||
# Scripts will be stored in binary form
|
||||
# (reduces the size of the output file)
|
||||
StripSource="True"
|
||||
|
||||
# Mutators to be compiled
|
||||
# Specify them with a space as a separator,
|
||||
# Mutators will be compiled in the specified order
|
||||
PackageBuildOrder="StartWave"
|
||||
|
||||
# Mutators that will be uploaded to the workshop
|
||||
# Specify them with a space as a separator,
|
||||
# The order doesn't matter
|
||||
PackageUpload="StartWave"
|
61
builder.cfg
61
builder.cfg
@ -1,61 +0,0 @@
|
||||
### Build parameters ###
|
||||
|
||||
# If True - compresses the mutator when compiling
|
||||
# Scripts will be stored in binary form
|
||||
# (reduces the size of the output file)
|
||||
StripSource="True"
|
||||
|
||||
# Mutators to be compiled
|
||||
# Specify them with a space as a separator,
|
||||
# Mutators will be compiled in the specified order
|
||||
PackageBuildOrder="StartWave"
|
||||
|
||||
|
||||
### Brew parameters ###
|
||||
|
||||
# Packages you want to brew using @peelz's patched KFEditor.
|
||||
# Useful for cases where regular brew doesn't put *.upk inside the package.
|
||||
# Specify them with a space as a separator,
|
||||
# The order doesn't matter
|
||||
PackagePeelzBrew=""
|
||||
|
||||
|
||||
### Steam Workshop upload parameters ###
|
||||
|
||||
# Mutators that will be uploaded to the workshop
|
||||
# Specify them with a space as a separator,
|
||||
# The order doesn't matter
|
||||
PackageUpload="StartWave"
|
||||
|
||||
|
||||
### Test parameters ###
|
||||
|
||||
# Map:
|
||||
Map="KF-Nuked"
|
||||
|
||||
# Game:
|
||||
# Survival: KFGameContent.KFGameInfo_Survival
|
||||
# WeeklyOutbreak: KFGameContent.KFGameInfo_WeeklySurvival
|
||||
# Endless: KFGameContent.KFGameInfo_Endless
|
||||
# Objective: KFGameContent.KFGameInfo_Objective
|
||||
# Versus: KFGameContent.KFGameInfo_VersusSurvival
|
||||
Game="KFGameContent.KFGameInfo_Endless"
|
||||
|
||||
# Difficulty:
|
||||
# Normal: 0
|
||||
# Hard: 1
|
||||
# Suicide: 2
|
||||
# Hell: 3
|
||||
Difficulty="0"
|
||||
|
||||
# GameLength:
|
||||
# 4 waves: 0
|
||||
# 7 waves: 1
|
||||
# 10 waves: 2
|
||||
GameLength="0"
|
||||
|
||||
# Mutators
|
||||
Mutators="StartWave.StartWaveMut"
|
||||
|
||||
# Additional parameters
|
||||
Args="Dosh=10000?StartWave=16?LogLevel=LL_Debug?TraderTime=60?InitialTraderTime=60?bStartWithTrader=true?Boss=3"
|
31
test.cfg
Normal file
31
test.cfg
Normal file
@ -0,0 +1,31 @@
|
||||
# Test parameters
|
||||
|
||||
# Map:
|
||||
Map="KF-Outpost"
|
||||
|
||||
# Game:
|
||||
# Survival: KFGameContent.KFGameInfo_Survival
|
||||
# WeeklyOutbreak: KFGameContent.KFGameInfo_WeeklySurvival
|
||||
# Endless: KFGameContent.KFGameInfo_Endless
|
||||
# Objective: KFGameContent.KFGameInfo_Objective
|
||||
# Versus: KFGameContent.KFGameInfo_VersusSurvival
|
||||
Game="KFGameContent.KFGameInfo_Endless"
|
||||
|
||||
# Difficulty:
|
||||
# Normal: 0
|
||||
# Hard: 1
|
||||
# Suicide: 2
|
||||
# Hell: 3
|
||||
Difficulty="0"
|
||||
|
||||
# GameLength:
|
||||
# 4 waves: 0
|
||||
# 7 waves: 1
|
||||
# 10 waves: 2
|
||||
GameLength="2"
|
||||
|
||||
# Mutators
|
||||
Mutators="StartWave.StartWave"
|
||||
|
||||
# Additional parameters
|
||||
Args="Dosh=999?StartWave=7?bUseDebug=True"
|
2
tools
2
tools
@ -1 +1 @@
|
||||
Subproject commit fb458ac61f7e6c6426b8dff366dd5e7499e0d95f
|
||||
Subproject commit 3d96a1e6c6e31163266d628c11202479ea429f94
|
Loading…
Reference in New Issue
Block a user