Compare commits
No commits in common. '1dca6ccbd8530d1e4e9921179416ebe77a110e1a' and '76fdcc46de27628b2c2db16247520c1bb64d01bb' have entirely different histories.
1dca6ccbd8
...
76fdcc46de
9 changed files with 55 additions and 605 deletions
@ -1,48 +1,7 @@ |
|||||||
[hard GameMode] |
[hard GameMode] |
||||||
;= Add a section like this one for every voting option |
title={$green Hard difficulty} |
||||||
;= |
|
||||||
;= `title` will be displayed in a drop-down list in the voting dialog |
|
||||||
title={$green Hard} |
|
||||||
;= `difficulty` determines... difficulty and for vanilla Killing Floor can be one of |
|
||||||
;= the following values: |
|
||||||
;= |
|
||||||
;= * Beginner: "easy", "beginner" |
|
||||||
;= * Normal: "normal", "default", "regular" |
|
||||||
;= * Hard: "harder" |
|
||||||
;= * Suicidal: "suicidal" |
|
||||||
;= * Hell On Earth: "hellonearth", "hell on earth", "hoe" |
|
||||||
;= |
|
||||||
;= Any prefixes will also work, e.g. "sui", "hard", etc. |
|
||||||
difficulty=hard |
difficulty=hard |
||||||
;= How long should game last? For vanilla Killing Floor its "short", |
|
||||||
;= "normal" (also "default" and "regular"), "long". |
|
||||||
length=long |
|
||||||
;= A short game mode name that will be displayed after map vote has finished |
|
||||||
acronym={$green hard} |
|
||||||
;= Use this to add map lists (from "AcediaMaps.ini") to this game mode |
|
||||||
;= NOTE: map lists, NOT maps |
|
||||||
includeMaps=default |
|
||||||
;= Use this to add mutators to this game mode, one mutator per line |
|
||||||
;includeMutator= |
|
||||||
;= Use this do add one of Acedia's Features into this game mode with "default" config |
|
||||||
;includeFeature= |
|
||||||
;= Use this to add feature with specified config |
|
||||||
;includeFeatureAs=(feature=,config=) |
|
||||||
;= Use this to disable one of the Acedia's features for this game mode. |
|
||||||
;= This overrides all other settings. |
|
||||||
;= Purpose of this setting is to disable auto-enabled features. |
|
||||||
;excludeFeature= |
|
||||||
|
|
||||||
[sui GameMode] |
|
||||||
title={$orange Suicidal} |
|
||||||
difficulty=suicidal |
|
||||||
length=long |
|
||||||
acronym={$orange sui} |
|
||||||
includeMaps=default |
|
||||||
|
|
||||||
[hell GameMode] |
[hell GameMode] |
||||||
title={$crimson Hell On Earth} |
title={$crimson Hell On Earth} |
||||||
difficulty=hoe |
difficulty=hoe |
||||||
length=long |
|
||||||
acronym={$crimson hoe} |
|
||||||
includeMaps=default |
|
@ -1,39 +0,0 @@ |
|||||||
[default MapList] |
|
||||||
map=KF-AbusementPark |
|
||||||
map=KF-Aperture |
|
||||||
map=KF-Bedlam |
|
||||||
map=KF-Biohazard |
|
||||||
map=KF-BioticsLab |
|
||||||
map=KF-Clandestine |
|
||||||
map=KF-Crash |
|
||||||
map=KF-Departed |
|
||||||
map=KF-EvilSantasLair |
|
||||||
map=KF-Farm |
|
||||||
map=KF-FilthsCross |
|
||||||
map=KF-Forgotten |
|
||||||
map=KF-Foundry |
|
||||||
map=KF-FrightYard |
|
||||||
map=KF-Hell |
|
||||||
map=KF-Hellride |
|
||||||
map=KF-HillbillyHorror |
|
||||||
map=KF-Hospitalhorrors |
|
||||||
map=KF-Icebreaker |
|
||||||
map=KF-IceCave |
|
||||||
map=KF-Manor |
|
||||||
map=KF-MoonBase |
|
||||||
map=KF-MountainPass |
|
||||||
map=KF-Offices |
|
||||||
map=KF-SirensBelch |
|
||||||
map=KF-Steamland |
|
||||||
map=KF-Stronghold |
|
||||||
map=KF-Suburbia |
|
||||||
map=KF-ThrillsChills |
|
||||||
map=KF-Transit |
|
||||||
map=KF-Waterworks |
|
||||||
map=KF-WestLondon |
|
||||||
map=KF-Wyre |
|
||||||
|
|
||||||
[objective MapList] |
|
||||||
map=KFO-FrightYard |
|
||||||
map=KFO-Steamland |
|
||||||
map=KFO-Transit |
|
@ -1,99 +0,0 @@ |
|||||||
/** |
|
||||||
* Config class for storing map lists. |
|
||||||
* Copyright 2023 Anton Tarasenko |
|
||||||
* 2023 Shtoyan |
|
||||||
*------------------------------------------------------------------------------ |
|
||||||
* This file is part of Acedia. |
|
||||||
* |
|
||||||
* Acedia is free software: you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation, version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* Acedia is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
|
||||||
*/ |
|
||||||
class MapList extends AcediaConfig |
|
||||||
perObjectConfig |
|
||||||
config(AcediaMaps); |
|
||||||
|
|
||||||
var public config array<string> map; |
|
||||||
|
|
||||||
protected function HashTable ToData() { |
|
||||||
local int i; |
|
||||||
local ArrayList commandArray; |
|
||||||
local HashTable result; |
|
||||||
|
|
||||||
result = _.collections.EmptyHashTable(); |
|
||||||
commandArray = _.collections.EmptyArrayList(); |
|
||||||
for (i = 0; i < map.length; i += 1) { |
|
||||||
commandArray.AddString(map[i]); |
|
||||||
} |
|
||||||
result.SetItem(P("maps"), commandArray); |
|
||||||
_.memory.Free(commandArray); |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
protected function FromData(HashTable source) { |
|
||||||
local int i; |
|
||||||
local ArrayList commandArray; |
|
||||||
|
|
||||||
if (source == none) { |
|
||||||
return; |
|
||||||
} |
|
||||||
commandArray = source.GetArrayList(P("maps")); |
|
||||||
if (commandArray == none) { |
|
||||||
return; |
|
||||||
} |
|
||||||
map.length = 0; |
|
||||||
for (i = 0; i < commandArray.GetLength(); i += 1) { |
|
||||||
map[map.length] = commandArray.GetString(i); |
|
||||||
} |
|
||||||
_.memory.Free(commandArray); |
|
||||||
} |
|
||||||
|
|
||||||
protected function DefaultIt() { |
|
||||||
map.length = 0; |
|
||||||
map[0] = "KF-AbusementPark"; |
|
||||||
map[1] = "KF-Aperture"; |
|
||||||
map[2] = "KF-Bedlam"; |
|
||||||
map[3] = "KF-Biohazard"; |
|
||||||
map[4] = "KF-BioticsLab"; |
|
||||||
map[5] = "KF-Clandestine"; |
|
||||||
map[6] = "KF-Crash"; |
|
||||||
map[7] = "KF-Departed"; |
|
||||||
map[8] = "KF-EvilSantasLair"; |
|
||||||
map[9] = "KF-Farm"; |
|
||||||
map[10] = "KF-FilthsCross"; |
|
||||||
map[11] = "KF-Forgotten"; |
|
||||||
map[12] = "KF-Foundry"; |
|
||||||
map[13] = "KF-FrightYard"; |
|
||||||
map[14] = "KF-Hell"; |
|
||||||
map[15] = "KF-Hellride"; |
|
||||||
map[16] = "KF-HillbillyHorror"; |
|
||||||
map[17] = "KF-Hospitalhorrors"; |
|
||||||
map[18] = "KF-Icebreaker"; |
|
||||||
map[19] = "KF-IceCave"; |
|
||||||
map[20] = "KF-Manor"; |
|
||||||
map[21] = "KF-MoonBase"; |
|
||||||
map[22] = "KF-MountainPass"; |
|
||||||
map[23] = "KF-Offices"; |
|
||||||
map[24] = "KF-SirensBelch"; |
|
||||||
map[25] = "KF-Steamland"; |
|
||||||
map[26] = "KF-Stronghold"; |
|
||||||
map[27] = "KF-Suburbia"; |
|
||||||
map[28] = "KF-ThrillsChills"; |
|
||||||
map[29] = "KF-Transit"; |
|
||||||
map[30] = "KF-Waterworks"; |
|
||||||
map[31] = "KF-WestLondon"; |
|
||||||
map[32] = "KF-Wyre"; |
|
||||||
} |
|
||||||
|
|
||||||
defaultproperties { |
|
||||||
configName = "AcediaMaps" |
|
||||||
} |
|
@ -1,346 +0,0 @@ |
|||||||
/** |
|
||||||
* Author: Anton Tarasenko |
|
||||||
* Home repo: https://insultplayers.ru/git/AcediaFramework/AcediaCore/ |
|
||||||
* License: GPL |
|
||||||
* Copyright 2023 Anton Tarasenko |
|
||||||
*------------------------------------------------------------------------------ |
|
||||||
* This file is part of Acedia. |
|
||||||
* |
|
||||||
* Acedia is free software: you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation, version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* Acedia is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
|
||||||
*/ |
|
||||||
class MapTool extends AcediaObject; |
|
||||||
|
|
||||||
//! Tool for adapting AcediaLauncher's map lists for [`xVotingHandler`]. |
|
||||||
//! |
|
||||||
//! This class is responsible for making [`xVotingHandler`] use specific maps (defined in |
|
||||||
//! AcediaLauncer's configs) for specific game modes. |
|
||||||
//! To achieve that it abuses [`xVotingHandler`]'s ability to filter maps by |
|
||||||
//! game mode-specific prefix. |
|
||||||
//! Normally prefix filtering for [`xVotingHandler`] is of limited use, because most Killing Floor |
|
||||||
//! maps start with the same prefix `KF-` (and some objective ones starting with `KFO-`). |
|
||||||
//! However we swap that prefix for something unique for each game mode: `MapSet0-`, `MapSet1-`, |
|
||||||
//! etc, allowing us to pick the precise map set we want. |
|
||||||
//! |
|
||||||
//! There's two main challenges: |
|
||||||
//! |
|
||||||
//! 1. *Altered map names break voting* - since [`xVotingHandler`] expects to be provided real map |
|
||||||
//! names and our mangled ones. We deal with it by catching a map change message broadcasted |
|
||||||
//! right before actual map change occurs and swap our names with real ones. |
|
||||||
//! 2. *Increased amount of maps to replicate* - if we implement this name mangling by using |
|
||||||
//! a naive approach, in which we separately add maps for every game mode, then it will lead to |
|
||||||
//! drastic increase in replication time of the complete map list to players. |
|
||||||
//! Consider, for example, that you have 10 different game modes with exactly the same maps: |
|
||||||
//! we will be needlessly replicating the exact same thing 10 times! |
|
||||||
//! To solve this issue we specifically track map lists other game modes use, along with |
|
||||||
//! prefixes assigned to them, and reuse already added maps in case two game modes are defined |
|
||||||
//! to use the exactly same ones. |
|
||||||
|
|
||||||
/// For storing which map sequences have which prefixes. Storage order is important. |
|
||||||
struct MapSequenceRecord { |
|
||||||
var public array<string> sequence; |
|
||||||
var public string prefix; |
|
||||||
}; |
|
||||||
|
|
||||||
// To avoid doing excesive work when injecting maps for a second time |
|
||||||
var private bool injectedMaps; |
|
||||||
|
|
||||||
// Finding voting handler is not cheap, so only do it once and then store it. |
|
||||||
var private NativeActorRef votingHandlerReference; |
|
||||||
// Resulting full map list with pseudonim (with replaced prefixes) and real names of maps. |
|
||||||
var private array<VotingHandler.MapVoteMapList> pseudonimMapList; |
|
||||||
var private array<VotingHandler.MapVoteMapList> realMapList; |
|
||||||
|
|
||||||
// Map sequences used by game modes we've seen so far. |
|
||||||
var private array<MapSequenceRecord> usedMapSequences; |
|
||||||
|
|
||||||
// To more easily detect broadcasted message about map change we replace it with our own that is |
|
||||||
// both unlikely to occur and is easy to get voted map name from. |
|
||||||
var private string backupMessageMapWon; |
|
||||||
var private string backupMessageAdminMapChange; |
|
||||||
var private const string ACEDIA_ADMIN_MAP_CHANGE_COMMAND; |
|
||||||
var private const string ACEDIA_MAP_WON_COMMAND; |
|
||||||
|
|
||||||
var private LoggerAPI.Definition fatVotingHandlerMissing, warnMissingMapList; |
|
||||||
|
|
||||||
protected function Finalizer() { |
|
||||||
_server.unreal.broadcasts.OnHandleText(self).Disconnect(); |
|
||||||
_.memory.Free(votingHandlerReference); |
|
||||||
votingHandlerReference = none; |
|
||||||
pseudonimMapList.length = 0; |
|
||||||
realMapList.length = 0; |
|
||||||
usedMapSequences.length = 0; |
|
||||||
injectedMaps = false; |
|
||||||
} |
|
||||||
|
|
||||||
/// Initializes [`MapTool`] by associating it with an [`XVotingHandler`]. |
|
||||||
/// |
|
||||||
/// Initialization fails if [`initVotingHandlerReference`] doesn't provide reference to |
|
||||||
/// [`XVotingHandler`] or caller [`MapTool`] already was initialized. |
|
||||||
/// Returns `true` iff initialization was successful. |
|
||||||
public final function bool Initialize(NativeActorRef initVotingHandlerReference) { |
|
||||||
if (initVotingHandlerReference == none) return false; |
|
||||||
if (XVotingHandler(initVotingHandlerReference.Get()) == none) return false; |
|
||||||
|
|
||||||
initVotingHandlerReference.NewRef(); |
|
||||||
votingHandlerReference = initVotingHandlerReference; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
/// Adds map information from the new game mode. |
|
||||||
/// |
|
||||||
/// Returns prefix that given game mode must use to display maps configured for it. |
|
||||||
public final function string AddGameMode(GameMode gameMode) { |
|
||||||
local XVotingHandler votingHandler; |
|
||||||
local string gameModePrefix; |
|
||||||
|
|
||||||
votingHandler = GetVotingHandler(); |
|
||||||
if (votingHandler == none) { |
|
||||||
_.logger.Auto(fatVotingHandlerMissing); |
|
||||||
return "KF"; |
|
||||||
} |
|
||||||
if (CheckNeedToLoadMaps(gameMode, gameModePrefix)) { |
|
||||||
LoadGameModeMaps(gameMode, gameModePrefix, votingHandler); |
|
||||||
} |
|
||||||
return gameModePrefix; |
|
||||||
} |
|
||||||
|
|
||||||
/// Injects final map list into [`XVotingHandler`]. |
|
||||||
/// |
|
||||||
/// Call this after all game modes have been added. |
|
||||||
/// Shouldn't be called more than once. |
|
||||||
public final function Inject() { |
|
||||||
local XVotingHandler votingHandler; |
|
||||||
|
|
||||||
votingHandler = GetVotingHandler(); |
|
||||||
if (votingHandler == none) { |
|
||||||
_.logger.Auto(fatVotingHandlerMissing); |
|
||||||
return; |
|
||||||
} |
|
||||||
votingHandler.mapList = pseudonimMapList; |
|
||||||
votingHandler.mapCount = pseudonimMapList.length; |
|
||||||
// Replace map change messages with our commands and make sure it is done only once, |
|
||||||
// in case we mess up somewhere else and call this method second time |
|
||||||
if (!injectedMaps) { |
|
||||||
backupMessageMapWon = votingHandler.lmsgMapWon; |
|
||||||
backupMessageAdminMapChange = votingHandler.lmsgAdminMapChange; |
|
||||||
votingHandler.lmsgMapWon = ACEDIA_MAP_WON_COMMAND $ "::%mapname%"; |
|
||||||
votingHandler.lmsgAdminMapChange = ACEDIA_ADMIN_MAP_CHANGE_COMMAND $ "::%mapname%"; |
|
||||||
_server.unreal.broadcasts.OnHandleText(self).connect = HandleMapChange; |
|
||||||
} |
|
||||||
injectedMaps = true; |
|
||||||
} |
|
||||||
|
|
||||||
/// Builds arrays of [`VotingHandler::MapVoteMapList`] (each such item describes a map + |
|
||||||
/// its meta data in a way [`XVotingHandler`] understands). |
|
||||||
private function string LoadGameModeMaps( |
|
||||||
GameMode gameMode, |
|
||||||
string gameModePrefix, |
|
||||||
XVotingHandler votingHandler |
|
||||||
) { |
|
||||||
local int i; |
|
||||||
local ArrayList gameModeMaps; |
|
||||||
local Text mapNameReal, mapNamePseudonim; |
|
||||||
local VotingHandler.MapHistoryInfo nextMapInfo; |
|
||||||
local VotingHandler.MapVoteMapList nextRecord; |
|
||||||
local array<VotingHandler.MapVoteMapList> newMapsPseudonim, newMapReal; |
|
||||||
|
|
||||||
nextRecord.bEnabled = true; |
|
||||||
gameModeMaps = GetAllGameModeMaps(gameMode); |
|
||||||
for (i = 0; i < gameModeMaps.GetLength(); i += 1) { |
|
||||||
mapNameReal = gameModeMaps.GetText(i); |
|
||||||
mapNamePseudonim = MakeMapPseudonim(mapNameReal, gameModePrefix); |
|
||||||
if (votingHandler.history != none) { |
|
||||||
nextMapInfo = votingHandler.history.GetMapHistory(mapNameReal.ToString()); |
|
||||||
nextRecord.playCount = nextMapInfo.p; |
|
||||||
nextRecord.sequence = nextMapInfo.s; |
|
||||||
} |
|
||||||
nextRecord.mapName = _.text.IntoString(mapNamePseudonim); |
|
||||||
newMapsPseudonim[newMapsPseudonim.length] = nextRecord; |
|
||||||
nextRecord.mapName = _.text.IntoString(mapNameReal); |
|
||||||
newMapReal[newMapReal.length] = nextRecord; |
|
||||||
} |
|
||||||
AppendMapsIntoVotingHandler(newMapsPseudonim, newMapReal); |
|
||||||
_.memory.Free(gameModeMaps); |
|
||||||
return gameModePrefix; |
|
||||||
} |
|
||||||
|
|
||||||
private function bool CheckNeedToLoadMaps(GameMode gameMode, out string prefix) { |
|
||||||
local int mapSequenceIndex, mapListIndex; |
|
||||||
local bool sameMapList, foundMatch; |
|
||||||
local array<string> existingMapSequence, newMapSequence; |
|
||||||
local MapSequenceRecord newRecord; |
|
||||||
|
|
||||||
// We don't need to load maps for the `gameMode` only when we've already added the exactly same |
|
||||||
// map sequence, order being important |
|
||||||
newMapSequence = gameMode.GetIncludedMapLists_S(); |
|
||||||
for (mapSequenceIndex = 0; mapSequenceIndex < usedMapSequences.length; mapSequenceIndex += 1) { |
|
||||||
existingMapSequence = usedMapSequences[mapSequenceIndex].sequence; |
|
||||||
if (existingMapSequence.length != newMapSequence.length) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
foundMatch = true; |
|
||||||
for (mapListIndex = 0; mapListIndex < newMapSequence.length; mapListIndex += 1) { |
|
||||||
// Map lists are ASCII config names, so we can compare them with case-ignoring |
|
||||||
// built-in `~=` operator works (it can only handle properly ASCII input) |
|
||||||
sameMapList = (existingMapSequence[mapListIndex] ~= newMapSequence[mapListIndex]); |
|
||||||
if (!sameMapList) { |
|
||||||
foundMatch = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (foundMatch) { |
|
||||||
prefix = usedMapSequences[mapSequenceIndex].prefix; |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
newRecord.sequence = newMapSequence; |
|
||||||
newRecord.prefix = "MapSet" $ usedMapSequences.length; |
|
||||||
usedMapSequences[usedMapSequences.length] = newRecord; |
|
||||||
prefix = newRecord.prefix; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
// Replaces prefixes like "KF-", "KFO-" or "KFS-" with "{gameModePrefix}-". |
|
||||||
private function Text MakeMapPseudonim(Text realName, string gameModePrefix) { |
|
||||||
local Parser parser; |
|
||||||
local MutableText prefix, nameBody; |
|
||||||
local MutableText result; |
|
||||||
|
|
||||||
result = _.text.FromStringM(gameModePrefix); |
|
||||||
result.Append(P("-")); |
|
||||||
parser = realName.Parse(); |
|
||||||
parser.MUntil(prefix, _.text.GetCharacter("-")); |
|
||||||
parser.Match(P("-")); |
|
||||||
if (parser.Ok()) { |
|
||||||
nameBody = parser.GetRemainderM(); |
|
||||||
result.Append(nameBody); |
|
||||||
} |
|
||||||
else { |
|
||||||
result.Append(realName); |
|
||||||
} |
|
||||||
_.memory.Free(nameBody); |
|
||||||
_.memory.Free(prefix); |
|
||||||
_.memory.Free(parser); |
|
||||||
return result.IntoText(); |
|
||||||
} |
|
||||||
|
|
||||||
private function ArrayList GetAllGameModeMaps(GameMode gameMode) { |
|
||||||
local int i, j; |
|
||||||
local HashTable uniqueMapSet; |
|
||||||
local ArrayList result; |
|
||||||
local array<Text> usedMapLists; |
|
||||||
local array<string> nextMapArray; |
|
||||||
local Text nextMapName, lowerMapName; |
|
||||||
|
|
||||||
uniqueMapSet = _.collections.EmptyHashTable(); // for testing map name uniqueness |
|
||||||
result = _.collections.EmptyArrayList(); |
|
||||||
usedMapLists = gameMode.GetIncludedMapLists(); |
|
||||||
for (i = 0; i < usedMapLists.length; i += 1) { |
|
||||||
nextMapArray = GetMapNameFromConfig(usedMapLists[i]); |
|
||||||
for (j = 0; j < nextMapArray.length; j += 1) { |
|
||||||
nextMapName = _.text.FromString(nextMapArray[j]); |
|
||||||
// Use lower case version of map name for uniqueness testing to ignore characters' case |
|
||||||
lowerMapName = nextMapName.LowerCopy(); |
|
||||||
if (!uniqueMapSet.HasKey(lowerMapName)) { |
|
||||||
uniqueMapSet.SetItem(lowerMapName, none); |
|
||||||
result.AddItem(nextMapName); |
|
||||||
} |
|
||||||
_.memory.Free(lowerMapName); |
|
||||||
_.memory.Free(nextMapName); |
|
||||||
} |
|
||||||
} |
|
||||||
_.memory.Free(uniqueMapSet); |
|
||||||
_.memory.FreeMany(usedMapLists); |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
private function array<string> GetMapNameFromConfig(Text configName) { |
|
||||||
local MapList mapConfig; |
|
||||||
local array<string> result; |
|
||||||
|
|
||||||
mapConfig = MapList(class'MapList'.static.GetConfigInstance(configName)); |
|
||||||
if (mapConfig == none) { |
|
||||||
_.logger.Auto(warnMissingMapList).Arg(configName.Copy()); |
|
||||||
} else { |
|
||||||
result = mapConfig.map; |
|
||||||
_.memory.Free(mapConfig); |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
private function AppendMapsIntoVotingHandler( |
|
||||||
array<VotingHandler.MapVoteMapList> newMapsPseudonim, |
|
||||||
array<VotingHandler.MapVoteMapList> newMapsReal) { |
|
||||||
local int i; |
|
||||||
local XVotingHandler votingHandler; |
|
||||||
|
|
||||||
votingHandler = GetVotingHandler(); |
|
||||||
if (votingHandler == none) { |
|
||||||
_.logger.Auto(fatVotingHandlerMissing); |
|
||||||
return; |
|
||||||
} |
|
||||||
for (i = 0; i < newMapsPseudonim.length; i += 1) { |
|
||||||
pseudonimMapList[pseudonimMapList.length] = newMapsPseudonim[i]; |
|
||||||
} |
|
||||||
for (i = 0; i < newMapsReal.length; i += 1) { |
|
||||||
realMapList[realMapList.length] = newMapsReal[i]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private function bool HandleMapChange( |
|
||||||
Actor sender, |
|
||||||
out string message, |
|
||||||
name type, |
|
||||||
bool teamMessage |
|
||||||
) { |
|
||||||
local Parser parser; |
|
||||||
local XVotingHandler votingHandler; |
|
||||||
|
|
||||||
votingHandler = GetVotingHandler(); |
|
||||||
if (sender == none) return true; |
|
||||||
if (votingHandler != sender) return true; |
|
||||||
|
|
||||||
parser = _.text.ParseString(message); |
|
||||||
parser.Match(P(ACEDIA_MAP_WON_COMMAND)); |
|
||||||
parser.Match(P("::")); |
|
||||||
if (parser.Ok()) { |
|
||||||
message = Repl(backupMessageMapWon, "%mapname%", parser.GetRemainderS()); |
|
||||||
} else { |
|
||||||
parser.Match(P(ACEDIA_ADMIN_MAP_CHANGE_COMMAND)); |
|
||||||
parser.Match(P("::")); |
|
||||||
if (parser.Ok()) { |
|
||||||
message = Repl(backupMessageAdminMapChange, "%mapname%", parser.GetRemainderS()); |
|
||||||
} |
|
||||||
} |
|
||||||
if (parser.Ok()) { |
|
||||||
votingHandler.mapList = realMapList; |
|
||||||
votingHandler.mapCount = realMapList.length; |
|
||||||
} |
|
||||||
_.memory.Free(parser); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
private function XVotingHandler GetVotingHandler() { |
|
||||||
if (votingHandlerReference != none) { |
|
||||||
return XVotingHandler(votingHandlerReference.Get()); |
|
||||||
} |
|
||||||
return none; |
|
||||||
} |
|
||||||
|
|
||||||
defaultproperties { |
|
||||||
ACEDIA_ADMIN_MAP_CHANGE_COMMAND = "ACEDIA_LAUNCHER:ADMIN_MAP_CHANGE:DEADBEEF" |
|
||||||
ACEDIA_MAP_WON_COMMAND = "ACEDIA_LAUNCHER:MAP_WON:DEADBEEF" |
|
||||||
fatVotingHandlerMissing = (l=LOG_Fatal,m="No voting `XVotingHandler` available. This is unexpected at this stage. Report this issue.") |
|
||||||
warnMissingMapList = (l=LOG_Warning,m="Cannot find map list `%1`.") |
|
||||||
} |
|
Loading…
Reference in new issue