7 Commits

Author SHA1 Message Date
7395ff04bf add bSmoothSpawn feature 2022-07-13 12:09:18 +03:00
681870536b replace logger 2022-07-13 10:12:35 +03:00
c7e9087f6e refactoring 2022-07-13 09:56:35 +03:00
91e199a2e1 update description 2022-07-11 10:24:24 +03:00
9f3153b43f update build tools 2022-07-11 10:24:03 +03:00
e12c70bdbe Merge branch 'master' of https://github.com/GenZmeY/KF2-ZedSpawner 2022-06-13 17:09:13 +03:00
42cf263785 Update README.md 2022-06-06 11:03:13 +03:00
15 changed files with 214 additions and 159 deletions

View File

@ -1,3 +1,5 @@
[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-ZedSpawner[/img] [img]https://img.shields.io/steam/subscriptions/2811290931[/img] [img]https://img.shields.io/steam/favorites/2811290931[/img] [img]https://img.shields.io/steam/update-date/2811290931[/img] [url=https://steamcommunity.com/sharedfiles/filedetails/changelog/2811290931][img]https://img.shields.io/github/v/tag/GenZmeY/KF2-ZedSpawner[/img][/url]
[h1]Description[/h1] [h1]Description[/h1]
Spawner for zeds. Started as a modification of [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2488241348]this version[/url], but now there is almost nothing left of the previous mutator, lol xD Spawner for zeds. Started as a modification of [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2488241348]this version[/url], but now there is almost nothing left of the previous mutator, lol xD
@ -9,24 +11,30 @@ Spawner for zeds. Started as a modification of [url=https://steamcommunity.com/s
- spawn after a certain percentage of killed zeds. - spawn after a certain percentage of killed zeds.
[h1]Whitelisted?[/h1] [h1]Whitelisted?[/h1]
No. This mod is not whitelisted and will unrank your server. Any XP gained will not be saved. No. This mod is not whitelisted and will de-rank your server. Any XP gained will not be saved.
[h1]Usage (single player)[/h1] [h1]Usage (single player)[/h1]
1. Subscribe to this mutator; [olist]
2. Start KF2; [*]Subscribe to this mutator;
3. Open console (`) and input: [*]Start KF2;
[*]Open console (`) and input:
[b]open KF-BioticsLab?Mutator=ZedSpawner.ZedSpawnerMut[/b] [b]open KF-BioticsLab?Mutator=ZedSpawner.ZedSpawnerMut[/b]
(replace the map and add the parameters you need) (replace the map and add the parameters you need)
4. <Enter>. [*]<Enter>.
[/olist]
[h1]Usage (server)[/h1] [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] [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]
1. Open your [b]PCServer-KFEngine.ini[/b] / [b]LinuxServer-KFEngine.ini[/b]; [*]Open your [b]PCServer-KFEngine.ini[/b] / [b]LinuxServer-KFEngine.ini[/b];
2. Add the following string to the [b][OnlineSubsystemSteamworks.KFWorkshopSteamworks][/b] section (create one if it doesn't exist): [*]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=2811290931[/b] [b]ServerSubscribedWorkshopItems=2811290931[/b]
3. Start the server and wait while the mutator is downloading; [*]Start the server and wait while the mutator is downloading;
4. Add mutator to server start parameters: [b]?Mutator=ZedSpawner.ZedSpawnerMut[/b] and restart the server. [*]Add mutator to server start parameters: [b]?Mutator=ZedSpawner.ZedSpawnerMut[/b] and restart the server.
[/olist]
[h1]Setup[/h1] [h1]Setup[/h1]
At the first start, the [b]KFZedSpawner.ini[/b] config will be created. There are already default settings and spawn lists, but you still need to change them because this is just an example. At the first start, the [b]KFZedSpawner.ini[/b] config will be created. There are already default settings and spawn lists, but you still need to change them because this is just an example.
@ -61,8 +69,8 @@ Use the [b][ZedSpawner.SpawnListBossWaves][/b] and [b][ZedSpawner.SpawnListSpeci
[h1]Spawn logic[/h1] [h1]Spawn logic[/h1]
I really tried to describe in text how it works, but every time I got some kind of crap. Therefore, I decided to explain it a little differently and made a small calculator for this. It is interactive, you can change the parameters and see what happens. It has all the necessary explanations, so I think you will quickly figure out how the spawner works. I really tried to describe in text how it works, but every time I got some kind of crap. Therefore, I decided to explain it a little differently and made a small calculator for this. It is interactive, you can change the parameters and see what happens. It has all the necessary explanations, so I think you will quickly figure out how the spawner works.
[h1]📌[url=https://redirect.genzmey.su/kf2-zedspawner-calc]Spawn calculator[/url][/h1] [url=https://redirect.genzmey.su/kf2-zedspawner-calc][img]https://img.shields.io/static/v1?message=Spawn%20Calculator&logo=Google%20Sheets&labelColor=34A853&color=gray&logoColor=white&label=Google%20Sheets%20[/img][/url]
[i]Just please try not to interfere with each other if you see that someone is already using a calculator.[/i] [i]Just please try not to interfere with each other if you see that someone is already using a calculator.[/i]
[h1]Sources[/h1] [h1]Sources[/h1]
[url=https://github.com/GenZmeY/KF2-ZedSpawner]https://github.com/GenZmeY/KF2-ZedSpawner[/url] (GNU GPLv3) [url=https://github.com/GenZmeY/KF2-ZedSpawner]https://github.com/GenZmeY/KF2-ZedSpawner[/url] (GNU GPLv3)

View File

@ -50,4 +50,4 @@ Describe what the bug looks like and how reproduce it.
Attaching your KFZedSpawner.ini and Launch.log can also be helpful. Attaching your KFZedSpawner.ini and Launch.log can also be helpful.
# License # License
[GNU GPLv3](LICENSE) [GNU GPLv3](LICENSE)

View File

@ -11,6 +11,7 @@ var public config float SingleSpawnLimitMultiplier;
var public config float SingleSpawnLimitPlayerMultiplier; var public config float SingleSpawnLimitPlayerMultiplier;
var public config float SingleSpawnLimitCycleMultiplier; var public config float SingleSpawnLimitCycleMultiplier;
var public config int AliveSpawnLimit; var public config int AliveSpawnLimit;
var public config bool bSmoothSpawn;
public static function InitConfig(int Version, int LatestVersion) public static function InitConfig(int Version, int LatestVersion)
{ {
@ -19,6 +20,9 @@ public static function InitConfig(int Version, int LatestVersion)
case `NO_CONFIG: case `NO_CONFIG:
ApplyDefault(); ApplyDefault();
case 3:
default.bSmoothSpawn = false;
default: break; default: break;
} }
@ -32,6 +36,7 @@ private static function ApplyDefault()
{ {
default.bCyclicalSpawn = true; default.bCyclicalSpawn = true;
default.bShadowSpawn = true; default.bShadowSpawn = true;
default.bSmoothSpawn = true;
default.ZedTotalMultiplier = 1.0; default.ZedTotalMultiplier = 1.0;
default.SpawnTotalPlayerMultiplier = 0.75; default.SpawnTotalPlayerMultiplier = 0.75;
default.SpawnTotalCycleMultiplier = 0.75; default.SpawnTotalCycleMultiplier = 0.75;
@ -47,43 +52,43 @@ public static function bool Load(E_LogLevel LogLevel)
if (default.ZedTotalMultiplier <= 0.f) if (default.ZedTotalMultiplier <= 0.f)
{ {
`ZS_Error("ZedTotalMultiplier" @ "(" $ default.ZedTotalMultiplier $ ")" @ "must be greater than 0.0"); `Log_Error("ZedTotalMultiplier" @ "(" $ default.ZedTotalMultiplier $ ")" @ "must be greater than 0.0");
Errors = true; Errors = true;
} }
if (default.SpawnTotalPlayerMultiplier < 0.f) if (default.SpawnTotalPlayerMultiplier < 0.f)
{ {
`ZS_Error("SpawnTotalPlayerMultiplier" @ "(" $ default.SpawnTotalPlayerMultiplier $ ")" @ "must be greater than or equal 0.0"); `Log_Error("SpawnTotalPlayerMultiplier" @ "(" $ default.SpawnTotalPlayerMultiplier $ ")" @ "must be greater than or equal 0.0");
Errors = true; Errors = true;
} }
if (default.SpawnTotalCycleMultiplier < 0.f) if (default.SpawnTotalCycleMultiplier < 0.f)
{ {
`ZS_Error("SpawnTotalCycleMultiplier" @ "(" $ default.SpawnTotalCycleMultiplier $ ")" @ "must be greater than or equal 0.0"); `Log_Error("SpawnTotalCycleMultiplier" @ "(" $ default.SpawnTotalCycleMultiplier $ ")" @ "must be greater than or equal 0.0");
Errors = true; Errors = true;
} }
if (default.SingleSpawnLimitMultiplier <= 0.f) if (default.SingleSpawnLimitMultiplier <= 0.f)
{ {
`ZS_Error("SingleSpawnLimitMultiplier" @ "(" $ default.SingleSpawnLimitMultiplier $ ")" @ "must be greater than 0.0"); `Log_Error("SingleSpawnLimitMultiplier" @ "(" $ default.SingleSpawnLimitMultiplier $ ")" @ "must be greater than 0.0");
Errors = true; Errors = true;
} }
if (default.SingleSpawnLimitPlayerMultiplier < 0.f) if (default.SingleSpawnLimitPlayerMultiplier < 0.f)
{ {
`ZS_Error("SingleSpawnLimitPlayerMultiplier" @ "(" $ default.SingleSpawnLimitPlayerMultiplier $ ")" @ "must be greater than or equal 0.0"); `Log_Error("SingleSpawnLimitPlayerMultiplier" @ "(" $ default.SingleSpawnLimitPlayerMultiplier $ ")" @ "must be greater than or equal 0.0");
Errors = true; Errors = true;
} }
if (default.SingleSpawnLimitCycleMultiplier < 0.f) if (default.SingleSpawnLimitCycleMultiplier < 0.f)
{ {
`ZS_Error("SingleSpawnLimitCycleMultiplier" @ "(" $ default.SingleSpawnLimitCycleMultiplier $ ")" @ "must be greater than or equal 0.0"); `Log_Error("SingleSpawnLimitCycleMultiplier" @ "(" $ default.SingleSpawnLimitCycleMultiplier $ ")" @ "must be greater than or equal 0.0");
Errors = true; Errors = true;
} }
if (default.AliveSpawnLimit < 0) if (default.AliveSpawnLimit < 0)
{ {
`ZS_Error("AliveSpawnLimit" @ "(" $ default.AliveSpawnLimit $ ")" @ "must be greater than or equal 0"); `Log_Error("AliveSpawnLimit" @ "(" $ default.AliveSpawnLimit $ ")" @ "must be greater than or equal 0");
Errors = true; Errors = true;
} }

View File

@ -39,33 +39,30 @@ public static function Array<class<KFPawn_Monster> > Load(E_LogLevel LogLevel)
local Array<class<KFPawn_Monster> > ZedList; local Array<class<KFPawn_Monster> > ZedList;
local class<KFPawn_Monster> KFPMC; local class<KFPawn_Monster> KFPMC;
local String ZedClassTmp; local String ZedClassTmp;
local int Line, Loaded; local int Line;
Loaded = 0; `Log_Info("Load zeds to spawn at player start:");
`ZS_Info("Load zeds to spawn at player start:");
foreach default.ZedClass(ZedClassTmp, Line) foreach default.ZedClass(ZedClassTmp, Line)
{ {
KFPMC = class<KFPawn_Monster>(DynamicLoadObject(ZedClassTmp, class'Class')); KFPMC = class<KFPawn_Monster>(DynamicLoadObject(ZedClassTmp, class'Class'));
if (KFPMC == None) if (KFPMC == None)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ ZedClassTmp); `Log_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ ZedClassTmp);
} }
else else
{ {
Loaded++;
ZedList.AddItem(KFPMC); ZedList.AddItem(KFPMC);
`ZS_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully:" @ ZedClassTmp); `Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully:" @ ZedClassTmp);
} }
} }
if (Loaded == default.ZedClass.Length) if (ZedList.Length == default.ZedClass.Length)
{ {
`ZS_Info("Spawn at player start list (Zeds) loaded successfully (" $ default.ZedClass.Length @ "entries)"); `Log_Info("Spawn at player start list (Zeds) loaded successfully (" $ default.ZedClass.Length @ "entries)");
} }
else else
{ {
`ZS_Info("Spawn at player start list (Zeds): loaded" @ Loaded @ "of" @ default.ZedClass.Length @ "entries"); `Log_Info("Spawn at player start list (Zeds): loaded" @ ZedList.Length @ "of" @ default.ZedClass.Length @ "entries");
} }
return ZedList; return ZedList;

View File

@ -61,9 +61,8 @@ public static function Array<S_SpawnEntry> Load(E_LogLevel LogLevel)
local S_SpawnEntry SpawnEntry; local S_SpawnEntry SpawnEntry;
local int Line; local int Line;
local bool Errors; local bool Errors;
local int Loaded;
`ZS_Info("Load boss waves spawn list:"); `Log_Info("Load boss waves spawn list:");
foreach default.Spawn(SpawnEntryCfg, Line) foreach default.Spawn(SpawnEntryCfg, Line)
{ {
Errors = false; Errors = false;
@ -71,14 +70,14 @@ public static function Array<S_SpawnEntry> Load(E_LogLevel LogLevel)
SpawnEntry.BossClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.BossClass, class'Class')); SpawnEntry.BossClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.BossClass, class'Class'));
if (SpawnEntry.BossClass == None) if (SpawnEntry.BossClass == None)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Can't load boss class:" @ SpawnEntryCfg.BossClass); `Log_Warn("[" $ Line + 1 $ "]" @ "Can't load boss class:" @ SpawnEntryCfg.BossClass);
Errors = true; Errors = true;
} }
SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class')); SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class'));
if (SpawnEntry.ZedClass == None) if (SpawnEntry.ZedClass == None)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass); `Log_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass);
Errors = true; Errors = true;
} }
@ -87,46 +86,45 @@ public static function Array<S_SpawnEntry> Load(E_LogLevel LogLevel)
SpawnEntry.DelayDefault = SpawnEntryCfg.Delay; SpawnEntry.DelayDefault = SpawnEntryCfg.Delay;
if (SpawnEntryCfg.Delay <= 0) if (SpawnEntryCfg.Delay <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f; SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f;
if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100) if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100"); `Log_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100");
Errors = true; Errors = true;
} }
SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase; SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase;
if (SpawnEntry.SpawnCountBase <= 0) if (SpawnEntry.SpawnCountBase <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit; SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit;
if (SpawnEntry.SingleSpawnLimit < 0) if (SpawnEntry.SingleSpawnLimit < 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0");
Errors = true; Errors = true;
} }
if (!Errors) if (!Errors)
{ {
Loaded++;
SpawnList.AddItem(SpawnEntry); SpawnList.AddItem(SpawnEntry);
`ZS_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (" $ SpawnEntryCfg.BossClass $ ")" @ SpawnEntryCfg.ZedClass); `Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (" $ SpawnEntryCfg.BossClass $ ")" @ SpawnEntryCfg.ZedClass);
} }
} }
if (Loaded == default.Spawn.Length) if (SpawnList.Length == default.Spawn.Length)
{ {
`ZS_Info("Boss spawn list loaded successfully (" $ default.Spawn.Length @ "entries)"); `Log_Info("Boss spawn list loaded successfully (" $ default.Spawn.Length @ "entries)");
} }
else else
{ {
`ZS_Info("Boss spawn list: loaded" @ Loaded @ "of" @ default.Spawn.Length @ "entries"); `Log_Info("Boss spawn list: loaded" @ SpawnList.Length @ "of" @ default.Spawn.Length @ "entries");
} }
return SpawnList; return SpawnList;

View File

@ -67,9 +67,8 @@ public static function Array<S_SpawnEntry> Load(E_LogLevel LogLevel)
local S_SpawnEntry SpawnEntry; local S_SpawnEntry SpawnEntry;
local int Line; local int Line;
local bool Errors; local bool Errors;
local int Loaded;
`ZS_Info("Load spawn list:"); `Log_Info("Load spawn list:");
foreach default.Spawn(SpawnEntryCfg, Line) foreach default.Spawn(SpawnEntryCfg, Line)
{ {
Errors = false; Errors = false;
@ -77,69 +76,68 @@ public static function Array<S_SpawnEntry> Load(E_LogLevel LogLevel)
SpawnEntry.Wave = SpawnEntryCfg.Wave; SpawnEntry.Wave = SpawnEntryCfg.Wave;
if (SpawnEntryCfg.Wave <= 0 || SpawnEntryCfg.Wave > 255) if (SpawnEntryCfg.Wave <= 0 || SpawnEntryCfg.Wave > 255)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Wave" @ "(" $ SpawnEntryCfg.ZedClass $ ")" @ "must be greater than 0 and less than 256"); `Log_Warn("[" $ Line + 1 $ "]" @ "Wave" @ "(" $ SpawnEntryCfg.ZedClass $ ")" @ "must be greater than 0 and less than 256");
Errors = true; Errors = true;
} }
SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class')); SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class'));
if (SpawnEntry.ZedClass == None) if (SpawnEntry.ZedClass == None)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass); `Log_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass);
Errors = true; Errors = true;
} }
SpawnEntry.RelativeStartDefault = SpawnEntryCfg.RelativeStart / 100.f; SpawnEntry.RelativeStartDefault = SpawnEntryCfg.RelativeStart / 100.f;
if (SpawnEntryCfg.RelativeStart < 0 || SpawnEntryCfg.RelativeStart > 100) if (SpawnEntryCfg.RelativeStart < 0 || SpawnEntryCfg.RelativeStart > 100)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "RelativeStart" @ "(" $ SpawnEntryCfg.RelativeStart $ ")" @ "must be greater than or equal 0 and less than or equal 100"); `Log_Warn("[" $ Line + 1 $ "]" @ "RelativeStart" @ "(" $ SpawnEntryCfg.RelativeStart $ ")" @ "must be greater than or equal 0 and less than or equal 100");
Errors = true; Errors = true;
} }
SpawnEntry.DelayDefault = SpawnEntryCfg.Delay; SpawnEntry.DelayDefault = SpawnEntryCfg.Delay;
if (SpawnEntryCfg.Delay <= 0) if (SpawnEntryCfg.Delay <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f; SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f;
if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100) if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100"); `Log_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100");
Errors = true; Errors = true;
} }
SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase; SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase;
if (SpawnEntry.SpawnCountBase <= 0) if (SpawnEntry.SpawnCountBase <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit; SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit;
if (SpawnEntry.SingleSpawnLimit < 0) if (SpawnEntry.SingleSpawnLimit < 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0");
Errors = true; Errors = true;
} }
if (!Errors) if (!Errors)
{ {
Loaded++;
SpawnList.AddItem(SpawnEntry); SpawnList.AddItem(SpawnEntry);
`ZS_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (w" $ SpawnEntryCfg.Wave $ ")" @ SpawnEntryCfg.ZedClass); `Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (w" $ SpawnEntryCfg.Wave $ ")" @ SpawnEntryCfg.ZedClass);
} }
} }
default.Spawn.Sort(SpawnListSort); default.Spawn.Sort(SpawnListSort);
if (Loaded == default.Spawn.Length) if (SpawnList.Length == default.Spawn.Length)
{ {
`ZS_Info("Regular spawn list loaded successfully (" $ default.Spawn.Length @ "entries)"); `Log_Info("Regular spawn list loaded successfully (" $ default.Spawn.Length @ "entries)");
} }
else else
{ {
`ZS_Info("Regular spawn list: loaded" @ Loaded @ "of" @ default.Spawn.Length @ "entries"); `Log_Info("Regular spawn list: loaded" @ SpawnList.Length @ "of" @ default.Spawn.Length @ "entries");
} }
return SpawnList; return SpawnList;

View File

@ -59,15 +59,14 @@ public static function Array<S_SpawnEntry> Load(KFGameInfo_Endless KFGIE, E_LogL
local S_SpawnEntry SpawnEntry; local S_SpawnEntry SpawnEntry;
local int Line; local int Line;
local bool Errors; local bool Errors;
local int Loaded;
if (KFGIE == None) if (KFGIE == None)
{ {
`ZS_Info("Not Endless mode, skip loading special waves"); `Log_Info("Not Endless mode, skip loading special waves");
return SpawnList; return SpawnList;
} }
`ZS_Info("Load special waves spawn list:"); `Log_Info("Load special waves spawn list:");
foreach default.Spawn(SpawnEntryCfg, Line) foreach default.Spawn(SpawnEntryCfg, Line)
{ {
Errors = false; Errors = false;
@ -75,67 +74,66 @@ public static function Array<S_SpawnEntry> Load(KFGameInfo_Endless KFGIE, E_LogL
SpawnEntry.Wave = SpawnEntryCfg.Wave; SpawnEntry.Wave = SpawnEntryCfg.Wave;
if (KFGIE.SpecialWaveTypes.Find(EAIType(SpawnEntryCfg.Wave)) == INDEX_NONE) if (KFGIE.SpecialWaveTypes.Find(EAIType(SpawnEntryCfg.Wave)) == INDEX_NONE)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Unknown special wave:" @ SpawnEntryCfg.Wave); `Log_Warn("[" $ Line + 1 $ "]" @ "Unknown special wave:" @ SpawnEntryCfg.Wave);
Errors = true; Errors = true;
} }
SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class')); SpawnEntry.ZedClass = class<KFPawn_Monster>(DynamicLoadObject(SpawnEntryCfg.ZedClass, class'Class'));
if (SpawnEntry.ZedClass == None) if (SpawnEntry.ZedClass == None)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass); `Log_Warn("[" $ Line + 1 $ "]" @ "Can't load zed class:" @ SpawnEntryCfg.ZedClass);
Errors = true; Errors = true;
} }
SpawnEntry.RelativeStartDefault = SpawnEntryCfg.RelativeStart / 100.f; SpawnEntry.RelativeStartDefault = SpawnEntryCfg.RelativeStart / 100.f;
if (SpawnEntryCfg.RelativeStart < 0 || SpawnEntryCfg.RelativeStart > 100) if (SpawnEntryCfg.RelativeStart < 0 || SpawnEntryCfg.RelativeStart > 100)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "RelativeStart" @ "(" $ SpawnEntryCfg.RelativeStart $ ")" @ "must be greater than or equal 0 and less than or equal 100"); `Log_Warn("[" $ Line + 1 $ "]" @ "RelativeStart" @ "(" $ SpawnEntryCfg.RelativeStart $ ")" @ "must be greater than or equal 0 and less than or equal 100");
Errors = true; Errors = true;
} }
SpawnEntry.DelayDefault = SpawnEntryCfg.Delay; SpawnEntry.DelayDefault = SpawnEntryCfg.Delay;
if (SpawnEntryCfg.Delay <= 0) if (SpawnEntryCfg.Delay <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "Delay" @ "(" $ SpawnEntryCfg.Delay $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f; SpawnEntry.Probability = SpawnEntryCfg.Probability / 100.f;
if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100) if (SpawnEntryCfg.Probability <= 0 || SpawnEntryCfg.Probability > 100)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100"); `Log_Warn("[" $ Line + 1 $ "]" @ "Probability" @ "(" $ SpawnEntryCfg.Probability $ ")" @ "must be greater than 0 and less than or equal 100");
Errors = true; Errors = true;
} }
SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase; SpawnEntry.SpawnCountBase = SpawnEntryCfg.SpawnCountBase;
if (SpawnEntry.SpawnCountBase <= 0) if (SpawnEntry.SpawnCountBase <= 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SpawnCountBase" @ "(" $ SpawnEntryCfg.SpawnCountBase $ ")" @ "must be greater than 0");
Errors = true; Errors = true;
} }
SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit; SpawnEntry.SingleSpawnLimitDefault = SpawnEntryCfg.SingleSpawnLimit;
if (SpawnEntry.SingleSpawnLimit < 0) if (SpawnEntry.SingleSpawnLimit < 0)
{ {
`ZS_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0"); `Log_Warn("[" $ Line + 1 $ "]" @ "SingleSpawnLimit" @ "(" $ SpawnEntryCfg.SingleSpawnLimit $ ")" @ "must be equal or greater than 0");
Errors = true; Errors = true;
} }
if (!Errors) if (!Errors)
{ {
Loaded++;
SpawnList.AddItem(SpawnEntry); SpawnList.AddItem(SpawnEntry);
`ZS_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (" $ SpawnEntryCfg.Wave $ ")" @ SpawnEntryCfg.ZedClass); `Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully: (" $ SpawnEntryCfg.Wave $ ")" @ SpawnEntryCfg.ZedClass);
} }
} }
if (Loaded == default.Spawn.Length) if (SpawnList.Length == default.Spawn.Length)
{ {
`ZS_Info("Special spawn list loaded successfully (" $ default.Spawn.Length @ "entries)"); `Log_Info("Special spawn list loaded successfully (" $ default.Spawn.Length @ "entries)");
} }
else else
{ {
`ZS_Info("Special spawn list: loaded" @ Loaded @ "of" @ default.Spawn.Length @ "entries"); `Log_Info("Special spawn list: loaded" @ SpawnList.Length @ "of" @ default.Spawn.Length @ "entries");
} }
return SpawnList; return SpawnList;

View File

@ -1,7 +1,7 @@
class ZedSpawner extends Info class ZedSpawner extends Info
config(ZedSpawner); config(ZedSpawner);
const LatestVersion = 3; const LatestVersion = 4;
const CfgSpawn = class'Spawn'; const CfgSpawn = class'Spawn';
const CfgSpawnAtPlayerStart = class'SpawnAtPlayerStart'; const CfgSpawnAtPlayerStart = class'SpawnAtPlayerStart';
@ -9,18 +9,6 @@ const CfgSpawnListRW = class'SpawnListRegular';
const CfgSpawnListBW = class'SpawnListBossWaves'; const CfgSpawnListBW = class'SpawnListBossWaves';
const CfgSpawnListSW = class'SpawnListSpecialWaves'; const CfgSpawnListSW = class'SpawnListSpecialWaves';
enum E_LogLevel
{
LL_WrongLevel,
LL_Fatal,
LL_Error,
LL_Warning,
LL_Info,
LL_Debug,
LL_Trace,
LL_All
};
struct S_SpawnEntry struct S_SpawnEntry
{ {
var class<KFPawn_Monster> BossClass; var class<KFPawn_Monster> BossClass;
@ -38,6 +26,7 @@ struct S_SpawnEntry
var int PawnsTotal; var int PawnsTotal;
var bool ForceSpawn; var bool ForceSpawn;
var String ZedNameFiller; var String ZedNameFiller;
var int SmoothPawnPool;
}; };
var private config int Version; var private config int Version;
@ -84,11 +73,11 @@ public simulated function bool SafeDestroy()
public event PreBeginPlay() public event PreBeginPlay()
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
if (WorldInfo.NetMode == NM_Client) if (WorldInfo.NetMode == NM_Client)
{ {
`ZS_Fatal("NetMode == NM_Client, Destroy..."); `Log_Fatal("NetMode == NM_Client, Destroy...");
SafeDestroy(); SafeDestroy();
return; return;
} }
@ -98,7 +87,7 @@ public event PreBeginPlay()
public event PostBeginPlay() public event PostBeginPlay()
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
if (bPendingDelete || bDeleteMe) return; if (bPendingDelete || bDeleteMe) return;
@ -124,25 +113,26 @@ private function InitConfig()
switch (Version) switch (Version)
{ {
case `NO_CONFIG: case `NO_CONFIG:
`ZS_Info("Config created"); `Log_Info("Config created");
case 1: case 1:
Tickrate = 1.0f; Tickrate = 1.0f;
case 2: case 2:
case 3:
case MaxInt: case MaxInt:
`ZS_Info("Config updated to version"@LatestVersion); `Log_Info("Config updated to version"@LatestVersion);
break; break;
case LatestVersion: case LatestVersion:
`ZS_Info("Config is up-to-date"); `Log_Info("Config is up-to-date");
break; break;
default: default:
`ZS_Warn("The config version is higher than the current version (are you using an old mutator?)"); `Log_Warn("The config version is higher than the current version (are you using an old mutator?)");
`ZS_Warn("Config version is" @ Version @ "but current version is" @ LatestVersion); `Log_Warn("Config version is" @ Version @ "but current version is" @ LatestVersion);
`ZS_Warn("The config version will be changed to" @ LatestVersion); `Log_Warn("The config version will be changed to" @ LatestVersion);
break; break;
} }
@ -158,12 +148,12 @@ private function Init()
local S_SpawnEntry SE; local S_SpawnEntry SE;
local String CurrentMap; local String CurrentMap;
`ZS_Trace(`Location); `Log_Trace(`Location);
KFGIS = KFGameInfo_Survival(WorldInfo.Game); KFGIS = KFGameInfo_Survival(WorldInfo.Game);
if (KFGIS == None) if (KFGIS == None)
{ {
`ZS_Fatal("Incompatible gamemode:" @ WorldInfo.Game $ ". Destroy..."); `Log_Fatal("Incompatible gamemode:" @ WorldInfo.Game $ ". Destroy...");
SafeDestroy(); SafeDestroy();
return; return;
} }
@ -176,25 +166,25 @@ private function Init()
if (LogLevel == LL_WrongLevel) if (LogLevel == LL_WrongLevel)
{ {
LogLevel = LL_Info; LogLevel = LL_Info;
`ZS_Warn("Wrong 'LogLevel', return to default value"); `Log_Warn("Wrong 'LogLevel', return to default value");
SaveConfig(); SaveConfig();
} }
`ZS_Log("LogLevel:" @ LogLevel); `Log_Base("LogLevel:" @ LogLevel);
if (Tickrate <= 0) if (Tickrate <= 0)
{ {
`ZS_Error("Spawner tickrate must be positive (current value:" @ Tickrate $ ")"); `Log_Error("Spawner tickrate must be positive (current value:" @ Tickrate $ ")");
} }
if (!CfgSpawn.static.Load(LogLevel) || Tickrate <= 0) if (!CfgSpawn.static.Load(LogLevel) || Tickrate <= 0)
{ {
`ZS_Fatal("Wrong settings, Destroy..."); `Log_Fatal("Wrong settings, Destroy...");
SafeDestroy(); SafeDestroy();
return; return;
} }
dt = 1 / Tickrate; dt = 1 / Tickrate;
`ZS_Info("Spawner tickrate:" @ Tickrate @ "(update every" @ dt $ "s)"); `Log_Info("Spawner tickrate:" @ Tickrate @ "(update every" @ dt $ "s)");
SpawnListRW = CfgSpawnListRW.static.Load(LogLevel); SpawnListRW = CfgSpawnListRW.static.Load(LogLevel);
SpawnListBW = CfgSpawnListBW.static.Load(LogLevel); SpawnListBW = CfgSpawnListBW.static.Load(LogLevel);
@ -203,7 +193,7 @@ private function Init()
CurrentMap = String(WorldInfo.GetPackageName()); CurrentMap = String(WorldInfo.GetPackageName());
GlobalSpawnAtPlayerStart = (CfgSpawnAtPlayerStart.default.Map.Find(CurrentMap) != INDEX_NONE); GlobalSpawnAtPlayerStart = (CfgSpawnAtPlayerStart.default.Map.Find(CurrentMap) != INDEX_NONE);
`ZS_Info("GlobalSpawnAtPlayerStart:" @ GlobalSpawnAtPlayerStart $ GlobalSpawnAtPlayerStart ? "(" $ CurrentMap $ ")" : ""); `Log_Info("GlobalSpawnAtPlayerStart:" @ GlobalSpawnAtPlayerStart $ GlobalSpawnAtPlayerStart ? "(" $ CurrentMap $ ")" : "");
CurrentWave = INDEX_NONE; CurrentWave = INDEX_NONE;
SpecialWave = INDEX_NONE; SpecialWave = INDEX_NONE;
@ -236,7 +226,7 @@ private function PreloadContent()
foreach CustomZeds(PawnClass) foreach CustomZeds(PawnClass)
{ {
`ZS_Info("Preload content:" @ PawnClass); `Log_Info("Preload content:" @ PawnClass);
PawnClass.static.PreloadContent(); PawnClass.static.PreloadContent();
} }
} }
@ -261,7 +251,7 @@ private function SpawnTimer()
local int Index; local int Index;
local float Threshold; local float Threshold;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (KFGIS.WaveNum != 0 && CurrentWave < KFGIS.WaveNum) if (KFGIS.WaveNum != 0 && CurrentWave < KFGIS.WaveNum)
{ {
@ -333,12 +323,12 @@ private function SetupWave()
local S_SpawnEntry SE; local S_SpawnEntry SE;
local EAIType SWType; local EAIType SWType;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (CfgSpawn.default.bCyclicalSpawn && KFGIS.WaveNum > 1 && KFGIS.WaveNum == CycleWaveShift + CycleWaveSize * CurrentCycle) if (CfgSpawn.default.bCyclicalSpawn && KFGIS.WaveNum > 1 && KFGIS.WaveNum == CycleWaveShift + CycleWaveSize * CurrentCycle)
{ {
CurrentCycle++; CurrentCycle++;
`ZS_Info("Spawn cycle started:" @ CurrentCycle); `Log_Info("Spawn cycle started:" @ CurrentCycle);
} }
CurrentWave = KFGIS.WaveNum; CurrentWave = KFGIS.WaveNum;
@ -363,7 +353,7 @@ private function SetupWave()
CurrentBossClass = KFGIA.BossAITypePawn(EBossAIType(KFGIS.MyKFGRI.BossIndex)); CurrentBossClass = KFGIA.BossAITypePawn(EBossAIType(KFGIS.MyKFGRI.BossIndex));
if (CurrentBossClass == None) if (CurrentBossClass == None)
{ {
`ZS_Error("Can't determine boss class. Boss index:" @ KFGIS.MyKFGRI.BossIndex); `Log_Error("Can't determine boss class. Boss index:" @ KFGIS.MyKFGRI.BossIndex);
} }
else else
{ {
@ -380,7 +370,7 @@ private function SetupWave()
if (WaveTotalAIDef != KFGIS.SpawnManager.WaveTotalAI) if (WaveTotalAIDef != KFGIS.SpawnManager.WaveTotalAI)
{ {
`ZS_Info("increase WaveTotalAI from" @ WaveTotalAIDef @ "to" @ WaveTotalAI @ "due to ZedTotalMultiplier" @ "(" $ CfgSpawn.default.ZedTotalMultiplier $ ")"); `Log_Info("increase WaveTotalAI from" @ WaveTotalAIDef @ "to" @ WaveTotalAI @ "due to ZedTotalMultiplier" @ "(" $ CfgSpawn.default.ZedTotalMultiplier $ ")");
} }
CurrentBossClass = None; CurrentBossClass = None;
@ -429,7 +419,7 @@ private function SetupWave()
WaveTypeInfo = "(" $ WaveTypeInfo $ ")"; WaveTypeInfo = "(" $ WaveTypeInfo $ ")";
} }
`ZS_Info("Wave" @ CurrentWave @ WaveTypeInfo); `Log_Info("Wave" @ CurrentWave @ WaveTypeInfo);
} }
private function AdjustSpawnList(out Array<S_SpawnEntry> List) private function AdjustSpawnList(out Array<S_SpawnEntry> List)
@ -442,7 +432,7 @@ private function AdjustSpawnList(out Array<S_SpawnEntry> List)
local float PawnTotalF, PawnLimitF; local float PawnTotalF, PawnLimitF;
local int ZedNameMaxLength; local int ZedNameMaxLength;
`ZS_Trace(`Location); `Log_Trace(`Location);
Cycle = float(CurrentCycle); Cycle = float(CurrentCycle);
Players = float(PlayerCount()); Players = float(PlayerCount());
@ -497,7 +487,7 @@ private function SpawnTimerLogger(bool Stop, optional String Comment)
{ {
local String Message; local String Message;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (Stop) if (Stop)
Message = "Stop spawn"; Message = "Stop spawn";
@ -509,7 +499,7 @@ private function SpawnTimerLogger(bool Stop, optional String Comment)
if (SpawnActive == Stop) if (SpawnActive == Stop)
{ {
`ZS_Info(Message); `Log_Info(Message);
SpawnActive = !Stop; SpawnActive = !Stop;
} }
} }
@ -521,11 +511,12 @@ private function SpawnEntry(out Array<S_SpawnEntry> SpawnList, int Index)
local String Action, Comment, NextSpawn; local String Action, Comment, NextSpawn;
local bool SpawnAtPlayerStart; local bool SpawnAtPlayerStart;
`ZS_Trace(`Location); `Log_Trace(`Location);
SE = SpawnList[Index]; SE = SpawnList[Index];
SpawnList[Index].Delay = float(SE.DelayDefault); SpawnList[Index].Delay = float(SE.DelayDefault);
if (FRand() <= SE.Probability || SE.ForceSpawn) if (FRand() <= SE.Probability || SE.ForceSpawn)
{ {
if (SE.SingleSpawnLimit == 0 || SE.PawnsLeft < SE.SingleSpawnLimit) if (SE.SingleSpawnLimit == 0 || SE.PawnsLeft < SE.SingleSpawnLimit)
@ -537,6 +528,15 @@ private function SpawnEntry(out Array<S_SpawnEntry> SpawnList, int Index)
PawnCount = SE.SingleSpawnLimit; PawnCount = SE.SingleSpawnLimit;
} }
if (CfgSpawn.default.bSmoothSpawn)
{
if (SE.SmoothPawnPool <= 0)
{
SpawnList[Index].SmoothPawnPool = PawnCount;
}
PawnCount = 1;
}
if (CfgSpawn.default.bShadowSpawn && !KFGIS.MyKFGRI.IsBossWave()) if (CfgSpawn.default.bShadowSpawn && !KFGIS.MyKFGRI.IsBossWave())
{ {
FreeSpawnSlots = KFGIS.MyKFGRI.AIRemaining - KFGIS.AIAliveCount; FreeSpawnSlots = KFGIS.MyKFGRI.AIRemaining - KFGIS.AIAliveCount;
@ -570,9 +570,26 @@ private function SpawnEntry(out Array<S_SpawnEntry> SpawnList, int Index)
} }
else else
{ {
SpawnList[Index].ForceSpawn = false;
Action = "Spawned"; Action = "Spawned";
Comment = "x" $ Spawned; Comment = "x" $ Spawned;
if (CfgSpawn.default.bSmoothSpawn)
{
SpawnList[Index].SmoothPawnPool -= Spawned;
if (SpawnList[Index].SmoothPawnPool > 0)
{
SpawnList[Index].Delay = 1.0f;
SpawnList[Index].ForceSpawn = true;
}
else
{
SpawnList[Index].Delay = float(SE.DelayDefault);
SpawnList[Index].ForceSpawn = false;
}
}
else
{
SpawnList[Index].ForceSpawn = false;
}
} }
} }
else else
@ -585,7 +602,14 @@ private function SpawnEntry(out Array<S_SpawnEntry> SpawnList, int Index)
SpawnList[Index].PawnsLeft -= Spawned; SpawnList[Index].PawnsLeft -= Spawned;
if (SpawnList[Index].PawnsLeft > 0) if (SpawnList[Index].PawnsLeft > 0)
{ {
NextSpawn = "next after" @ SE.DelayDefault $ "sec," @ "pawns left:" @ SpawnList[Index].PawnsLeft; if (CfgSpawn.default.bSmoothSpawn && SpawnList[Index].SmoothPawnPool > 0)
{
NextSpawn = "next after" @ Round(SpawnList[Index].Delay) $ "sec," @ "pawns left:" @ SpawnList[Index].SmoothPawnPool @ "(" $ SpawnList[Index].PawnsLeft $ ")";
}
else
{
NextSpawn = "next after" @ SE.DelayDefault $ "sec," @ "pawns left:" @ SpawnList[Index].PawnsLeft;
}
} }
SpawnLog(SE, Action, Comment, NextSpawn); SpawnLog(SE, Action, Comment, NextSpawn);
} }
@ -595,7 +619,7 @@ private function SpawnLog(S_SpawnEntry SE, String Action, optional String Commen
if (Comment != "") Comment = ":" @ Comment; if (Comment != "") Comment = ":" @ Comment;
if (NextSpawn != "") NextSpawn = "(" $ NextSpawn $ ")"; if (NextSpawn != "") NextSpawn = "(" $ NextSpawn $ ")";
`ZS_Info(String(SE.ZedClass) $ SE.ZedNameFiller @ ">" @ Action $ Comment @ NextSpawn); `Log_Info(String(SE.ZedClass) $ SE.ZedNameFiller @ ">" @ Action $ Comment @ NextSpawn);
} }
private function int PlayerCount() private function int PlayerCount()
@ -604,7 +628,7 @@ private function int PlayerCount()
local int HumanPlayers; local int HumanPlayers;
local KFOnlineGameSettings KFGameSettings; local KFOnlineGameSettings KFGameSettings;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (KFGIS.PlayfabInter != None && KFGIS.PlayfabInter.GetGameSettings() != None) if (KFGIS.PlayfabInter != None && KFGIS.PlayfabInter.GetGameSettings() != None)
{ {
@ -629,7 +653,7 @@ private function Vector PlayerStartLocation()
{ {
local PlayerController PC; local PlayerController PC;
`ZS_Trace(`Location); `Log_Trace(`Location);
foreach WorldInfo.AllControllers(class'PlayerController', PC) foreach WorldInfo.AllControllers(class'PlayerController', PC)
return KFGIS.FindPlayerStart(PC, 0).Location; return KFGIS.FindPlayerStart(PC, 0).Location;
@ -648,7 +672,7 @@ private function int SpawnZed(class<KFPawn_Monster> ZedClass, int PawnCount, opt
local int Failed, Spawned; local int Failed, Spawned;
local int Index; local int Index;
`ZS_Trace(`Location); `Log_Trace(`Location);
PlayerStart = PlayerStartLocation(); PlayerStart = PlayerStartLocation();
if (SpawnAtPlayerStart) if (SpawnAtPlayerStart)
@ -691,7 +715,7 @@ private function int SpawnZed(class<KFPawn_Monster> ZedClass, int PawnCount, opt
KFPM = Spawn(ZedClass,,, SpawnLocation, rot(0,0,1),, true); KFPM = Spawn(ZedClass,,, SpawnLocation, rot(0,0,1),, true);
if (KFPM == None) if (KFPM == None)
{ {
`ZS_Error("Can't spawn" @ ZedClass); `Log_Error("Can't spawn" @ ZedClass);
Failed++; Failed++;
continue; continue;
} }
@ -699,7 +723,7 @@ private function int SpawnZed(class<KFPawn_Monster> ZedClass, int PawnCount, opt
C = KFPM.Spawn(KFPM.ControllerClass); C = KFPM.Spawn(KFPM.ControllerClass);
if (C == None) if (C == None)
{ {
`ZS_Error("Can't spawn controller for" @ ZedClass $ ". Destroy this" @ KFPM $ "..."); `Log_Error("Can't spawn controller for" @ ZedClass $ ". Destroy this" @ KFPM $ "...");
KFPM.Destroy(); KFPM.Destroy();
Failed++; Failed++;
continue; continue;
@ -726,27 +750,30 @@ private function int SpawnZed(class<KFPawn_Monster> ZedClass, int PawnCount, opt
public function NotifyLogin(Controller C) public function NotifyLogin(Controller C)
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
CreateRepLink(C); CreateRepLink(C);
} }
public function NotifyLogout(Controller C) public function NotifyLogout(Controller C)
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
DestroyRepLink(C); DestroyRepLink(C);
} }
public function CreateRepLink(Controller C) public function bool CreateRepLink(Controller C)
{ {
local ZedSpawnerRepLink RepLink; local ZedSpawnerRepLink RepLink;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (C == None) return; if (C == None) return false;
RepLink = Spawn(class'ZedSpawnerRepLink', C); RepLink = Spawn(class'ZedSpawnerRepLink', C);
if (RepLink == None) return false;
RepLink.LogLevel = LogLevel; RepLink.LogLevel = LogLevel;
RepLink.CustomZeds = CustomZeds; RepLink.CustomZeds = CustomZeds;
RepLink.ZS = Self; RepLink.ZS = Self;
@ -754,22 +781,24 @@ public function CreateRepLink(Controller C)
RepLinks.AddItem(RepLink); RepLinks.AddItem(RepLink);
RepLink.ServerSync(); RepLink.ServerSync();
return true;
} }
public function bool DestroyRepLink(Controller C) public function bool DestroyRepLink(Controller C)
{ {
local int i; local ZedSpawnerRepLink RepLink;
`ZS_Trace(`Location); `Log_Trace(`Location);
if (C == None) return false; if (C == None) return false;
for (i = RepLinks.Length - 1; i >= 0; --i) foreach RepLinks(RepLink)
{ {
if (RepLinks[i].Owner == C) if (RepLink.Owner == C)
{ {
RepLinks[i].SafeDestroy(); RepLink.SafeDestroy();
RepLinks.Remove(i, 1); RepLinks.RemoveItem(RepLink);
return true; return true;
} }
} }

View File

@ -3,7 +3,7 @@ class ZedSpawnerMut extends KFMutator
var private ZedSpawner ZS; var private ZedSpawner ZS;
event PreBeginPlay() public event PreBeginPlay()
{ {
Super.PreBeginPlay(); Super.PreBeginPlay();
@ -11,19 +11,19 @@ event PreBeginPlay()
foreach WorldInfo.DynamicActors(class'ZedSpawner', ZS) foreach WorldInfo.DynamicActors(class'ZedSpawner', ZS)
{ {
`ZS_Log("Found 'ZedSpawner'"); `Log_Base("Found 'ZedSpawner'");
break; break;
} }
if (ZS == None) if (ZS == None)
{ {
`ZS_Log("Spawn 'ZedSpawner'"); `Log_Base("Spawn 'ZedSpawner'");
ZS = WorldInfo.Spawn(class'ZedSpawner'); ZS = WorldInfo.Spawn(class'ZedSpawner');
} }
if (ZS == None) if (ZS == None)
{ {
`ZS_Log("Can't Spawn 'ZedSpawner', Destroy..."); `Log_Base("Can't Spawn 'ZedSpawner', Destroy...");
Destroy(); Destroy();
} }
} }
@ -38,14 +38,14 @@ public function AddMutator(Mutator Mut)
Super.AddMutator(Mut); Super.AddMutator(Mut);
} }
function NotifyLogin(Controller C) public function NotifyLogin(Controller C)
{ {
Super.NotifyLogin(C); Super.NotifyLogin(C);
ZS.NotifyLogin(C); ZS.NotifyLogin(C);
} }
function NotifyLogout(Controller C) public function NotifyLogout(Controller C)
{ {
Super.NotifyLogout(C); Super.NotifyLogout(C);

View File

@ -13,15 +13,14 @@ replication
public simulated function bool SafeDestroy() public simulated function bool SafeDestroy()
{ {
`ZS_Debug(`Location @ "bPendingDelete:" @ bPendingDelete @ "bDeleteMe" @ bDeleteMe);
return (bPendingDelete || bDeleteMe || Destroy()); return (bPendingDelete || bDeleteMe || Destroy());
} }
public reliable client function ClientSync(class<KFPawn_Monster> CustomZed) public reliable client function ClientSync(class<KFPawn_Monster> CustomZed)
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
`ZS_Debug("Received:" @ CustomZed); `Log_Debug("Received:" @ CustomZed);
CustomZeds.AddItem(CustomZed); CustomZeds.AddItem(CustomZed);
ServerSync(); ServerSync();
} }
@ -30,11 +29,11 @@ public reliable client function SyncFinished()
{ {
local class<KFPawn_Monster> CustomZed; local class<KFPawn_Monster> CustomZed;
`ZS_Trace(`Location); `Log_Trace(`Location);
foreach CustomZeds(CustomZed) foreach CustomZeds(CustomZed)
{ {
`ZS_Debug("Preload Content for" @ CustomZed); `Log_Debug("Preload Content for" @ CustomZed);
CustomZed.static.PreloadContent(); CustomZed.static.PreloadContent();
} }
@ -43,13 +42,13 @@ public reliable client function SyncFinished()
public reliable server function ServerSync() public reliable server function ServerSync()
{ {
`ZS_Trace(`Location); `Log_Trace(`Location);
if (bPendingDelete || bDeleteMe) return; if (bPendingDelete || bDeleteMe) return;
if (CustomZeds.Length == Recieved || WorldInfo.NetMode == NM_StandAlone) if (CustomZeds.Length == Recieved || WorldInfo.NetMode == NM_StandAlone)
{ {
`ZS_Debug("Sync finished"); `Log_Debug("Sync finished");
SyncFinished(); SyncFinished();
if (!ZS.DestroyRepLink(Controller(Owner))) if (!ZS.DestroyRepLink(Controller(Owner)))
{ {
@ -58,7 +57,7 @@ public reliable server function ServerSync()
} }
else else
{ {
`ZS_Debug("Sync:" @ CustomZeds[Recieved]); `Log_Debug("Sync:" @ CustomZeds[Recieved]);
ClientSync(CustomZeds[Recieved++]); ClientSync(CustomZeds[Recieved++]);
} }
} }

View File

@ -0,0 +1,19 @@
class _Logger extends Object
abstract;
enum E_LogLevel
{
LL_WrongLevel,
LL_Fatal,
LL_Error,
LL_Warning,
LL_Info,
LL_Debug,
LL_Trace,
LL_All
};
defaultproperties
{
}

2
ZedSpawner/Constants.uci Normal file
View File

@ -0,0 +1,2 @@
// Constants
`define NO_CONFIG 0

View File

@ -1,12 +1,3 @@
`define ZS_Tag 'ZedSpawner' // Imports
`include(Logger.uci)
`define ZS_Log(msg, cond) `log(`msg `if(`cond), `cond`{endif}, `ZS_Tag) `include(Constants.uci)
`define ZS_Fatal(msg) `log("FATAL:" @ `msg, (LogLevel >= LL_Fatal), `ZS_Tag)
`define ZS_Error(msg) `log("ERROR:" @ `msg, (LogLevel >= LL_Error), `ZS_Tag)
`define ZS_Warn(msg) `log("WARN:" @ `msg, (LogLevel >= LL_Warning), `ZS_Tag)
`define ZS_Info(msg) `log("INFO:" @ `msg, (LogLevel >= LL_Info), `ZS_Tag)
`define ZS_Debug(msg) `log("DEBUG:" @ `msg, (LogLevel >= LL_Debug), `ZS_Tag)
`define ZS_Trace(msg) `log("TRACE:" @ `msg, (LogLevel >= LL_Trace), `ZS_Tag)
`define NO_CONFIG 0

11
ZedSpawner/Logger.uci Normal file
View File

@ -0,0 +1,11 @@
// Logger
`define Log_Tag 'ZedSpawner'
`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:" @ `msg, (LogLevel >= LL_Trace), `Log_Tag)

2
tools

Submodule tools updated: 02222cf453...2f173aad7a