Anton Tarasenko
4 years ago
9 changed files with 619 additions and 16 deletions
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* Mock `GameRules` class for testing `UnrealAPI` and it' methods for |
||||||
|
* adding / removing `GameRules`. |
||||||
|
* Copyright 2021 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 MockGameRulesA extends GameRules; |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* Mock `GameRules` class for testing `UnrealAPI` and it's methods for |
||||||
|
* adding / removing `GameRules`. |
||||||
|
* Copyright 2021 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 MockGameRulesB extends GameRules; |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* Mock inventory class for testing `UnrealAPI` and it's methods for |
||||||
|
* adding / removing `GameRules`. |
||||||
|
* Copyright 2021 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 MockInventoryA extends Inventory; |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* Mock inventory class for testing `UnrealAPI` and it's methods for |
||||||
|
* adding / removing `GameRules`. |
||||||
|
* Copyright 2021 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 MockInventoryAChild extends MockInventoryA; |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* Mock inventory class for testing `UnrealAPI` and it's methods for |
||||||
|
* adding / removing `GameRules`. |
||||||
|
* Copyright 2021 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 MockInventoryB extends Inventory; |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,230 @@ |
|||||||
|
/** |
||||||
|
* Set of tests for `UnrealAPI` class. |
||||||
|
* Copyright 2021 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 TEST_UnrealAPI extends TestCase; |
||||||
|
|
||||||
|
protected static function int CountRulesAmount(class<GameRules> gameRulesClass) |
||||||
|
{ |
||||||
|
local int counter; |
||||||
|
local GameRules rulesIter; |
||||||
|
if (gameRulesClass == none) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
rulesIter = __().unreal.GetGameType().gameRulesModifiers; |
||||||
|
while (rulesIter != none) |
||||||
|
{ |
||||||
|
if (rulesIter.class == gameRulesClass) { |
||||||
|
counter += 1; |
||||||
|
} |
||||||
|
rulesIter = rulesIter.nextGameRules; |
||||||
|
} |
||||||
|
return counter; |
||||||
|
} |
||||||
|
|
||||||
|
protected static function TESTS() |
||||||
|
{ |
||||||
|
Test_GameType(); |
||||||
|
Test_GameRules(); |
||||||
|
Test_InventoryChainFetching(); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function Test_GameType() |
||||||
|
{ |
||||||
|
Context("Testing methods for returning `GameType` class."); |
||||||
|
Issue("`GetGameType()` returns `none`."); |
||||||
|
TEST_ExpectNotNone(__().unreal.GetGameType()); |
||||||
|
Issue("`GetKFGameType()` returns `none`."); |
||||||
|
TEST_ExpectNotNone(__().unreal.GetKFGameType()); |
||||||
|
Issue("`GetGameType()` and `GetKFGameType()` return different values."); |
||||||
|
TEST_ExpectTrue(__().unreal.GetGameType() == __().unreal.GetKFGameType()); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function Test_GameRules() |
||||||
|
{ |
||||||
|
Context("Testing methods for working with `GameRules`."); |
||||||
|
SubTest_AddRemoveGameRules(); |
||||||
|
SubTest_CheckGameRules(); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function SubTest_AddRemoveGameRules() |
||||||
|
{ |
||||||
|
Issue("`AddGameRules()` does not add game rules."); |
||||||
|
__().unreal.AddGameRules(class'MockGameRulesA'); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1); |
||||||
|
|
||||||
|
__().unreal.AddGameRules(class'MockGameRulesA'); |
||||||
|
Issue("Calling `AddGameRules()` twice leads to rule duplication."); |
||||||
|
TEST_ExpectFalse(CountRulesAmount(class'MockGameRulesA') > 1); |
||||||
|
Issue("Calling `AddGameRules()` leads to rule not being added."); |
||||||
|
TEST_ExpectFalse(CountRulesAmount(class'MockGameRulesA') == 0); |
||||||
|
|
||||||
|
Issue("Adding new rules with `AddGameRules()` does not work properly."); |
||||||
|
__().unreal.AddGameRules(class'MockGameRulesB'); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 1); |
||||||
|
|
||||||
|
Issue("Adding/removing rules with `RemoveGameRules()` leads to" @ |
||||||
|
"unexpected results."); |
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesB'); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 1); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 0); |
||||||
|
__().unreal.AddGameRules(class'MockGameRulesB'); |
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesA'); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 0); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 1); |
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesB'); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesA') == 0); |
||||||
|
TEST_ExpectTrue(CountRulesAmount(class'MockGameRulesB') == 0); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function SubTest_CheckGameRules() |
||||||
|
{ |
||||||
|
local string issueForAdded, issueForNotAdded; |
||||||
|
issueForAdded = "`AreGameRulesAdded()` returns `false` for rules that are" @ |
||||||
|
"currently added."; |
||||||
|
issueForNotAdded = "`AreGameRulesAdded()` returns `true` for rules that" @ |
||||||
|
"are not currently added."; |
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesA'); |
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesB'); |
||||||
|
Issue(issueForNotAdded); |
||||||
|
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesA')); |
||||||
|
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesB')); |
||||||
|
|
||||||
|
__().unreal.AddGameRules(class'MockGameRulesB'); |
||||||
|
Issue(issueForNotAdded); |
||||||
|
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesA')); |
||||||
|
Issue(issueForAdded); |
||||||
|
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesB')); |
||||||
|
|
||||||
|
__().unreal.AddGameRules(class'MockGameRulesA'); |
||||||
|
Issue(issueForAdded); |
||||||
|
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesA')); |
||||||
|
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesB')); |
||||||
|
|
||||||
|
__().unreal.RemoveGameRules(class'MockGameRulesB'); |
||||||
|
Issue(issueForAdded); |
||||||
|
TEST_ExpectTrue(__().unreal.AreGameRulesAdded(class'MockGameRulesA')); |
||||||
|
Issue(issueForNotAdded); |
||||||
|
TEST_ExpectFalse(__().unreal.AreGameRulesAdded(class'MockGameRulesB')); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function Test_InventoryChainFetching() |
||||||
|
{ |
||||||
|
local Inventory chainStart, chainEnd; |
||||||
|
// a - B - A - a - B - a - A, |
||||||
|
// where A = `MockInventoryA` |
||||||
|
// a = `MockInventoryAChild` |
||||||
|
// B = `MockInventoryB` |
||||||
|
chainStart = Inventory(__().memory.Allocate(class'MockInventoryAChild')); |
||||||
|
chainEnd = chainStart; |
||||||
|
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryB')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryA')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryAChild')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryB')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
chainEnd.inventory = |
||||||
|
Inventory(__().memory.Allocate(class'MockInventoryAChild')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
chainEnd.inventory = Inventory(__().memory.Allocate(class'MockInventoryA')); |
||||||
|
chainEnd = chainEnd.inventory; |
||||||
|
Context("Testing auxiliary methods for working with inventory chains."); |
||||||
|
SubTest_InventoryChainFetchingSingle(chainStart); |
||||||
|
SubTest_InventoryChainFetchingMany(chainStart); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function SubTest_InventoryChainFetchingSingle(Inventory chain) |
||||||
|
{ |
||||||
|
Issue("Does not find correct first entry inside the inventory chain."); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryA', chain) |
||||||
|
== chain.inventory.inventory); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryB', chain) |
||||||
|
== chain.inventory); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryAChild', chain) |
||||||
|
== chain); |
||||||
|
|
||||||
|
Issue("Incorrectly finds missing inventory entries."); |
||||||
|
TEST_ExpectNone(__().unreal.GetInventoryFrom(none, chain)); |
||||||
|
TEST_ExpectNone(__().unreal.GetInventoryFrom(class'Winchester', chain)); |
||||||
|
|
||||||
|
Issue("Does not find correct first entry inside the inventory chain when" @ |
||||||
|
"allowing for child classes."); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryA', chain, true) |
||||||
|
== chain); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryB', chain, true) |
||||||
|
== chain.inventory); |
||||||
|
TEST_ExpectTrue( |
||||||
|
__().unreal.GetInventoryFrom(class'MockInventoryAChild', chain, true) |
||||||
|
== chain); |
||||||
|
|
||||||
|
Issue("Incorrectly finds missing inventory entries when allowing for" @ |
||||||
|
"child classes."); |
||||||
|
TEST_ExpectNone(__().unreal.GetInventoryFrom(none, chain, true)); |
||||||
|
TEST_ExpectNone(__().unreal.GetInventoryFrom( class'Winchester', chain, |
||||||
|
true)); |
||||||
|
} |
||||||
|
|
||||||
|
protected static function SubTest_InventoryChainFetchingMany(Inventory chain) |
||||||
|
{ |
||||||
|
local array<Inventory> result; |
||||||
|
Issue("Does not find correct entries inside the inventory chain."); |
||||||
|
result = __().unreal.GetAllInventoryFrom(class'MockInventoryB', chain); |
||||||
|
TEST_ExpectTrue(result.length == 2); |
||||||
|
TEST_ExpectTrue(result[0] == chain.inventory); |
||||||
|
TEST_ExpectTrue(result[1] == chain.inventory.inventory.inventory.inventory); |
||||||
|
|
||||||
|
Issue("Does not find correct entries inside the inventory chain when" @ |
||||||
|
"allowing for child classes."); |
||||||
|
result = |
||||||
|
__().unreal.GetAllInventoryFrom(class'MockInventoryB', chain, true); |
||||||
|
TEST_ExpectTrue(result.length == 2); |
||||||
|
TEST_ExpectTrue(result[0] == chain.inventory); |
||||||
|
TEST_ExpectTrue(result[1] == chain.inventory.inventory.inventory.inventory); |
||||||
|
result = |
||||||
|
__().unreal.GetAllInventoryFrom(class'MockInventoryA', chain, true); |
||||||
|
TEST_ExpectTrue(result.length == 5); |
||||||
|
TEST_ExpectTrue(result[0] == chain); |
||||||
|
TEST_ExpectTrue(result[1] == chain.inventory.inventory); |
||||||
|
TEST_ExpectTrue(result[2] == chain.inventory.inventory.inventory); |
||||||
|
TEST_ExpectTrue( |
||||||
|
result[3] |
||||||
|
== chain.inventory.inventory.inventory.inventory.inventory); |
||||||
|
TEST_ExpectTrue( |
||||||
|
result[4] |
||||||
|
== chain.inventory.inventory.inventory.inventory.inventory.inventory); |
||||||
|
|
||||||
|
Issue("Does not return empty array for non-existing inventory class."); |
||||||
|
result = __().unreal.GetAllInventoryFrom(class'Winchester', chain); |
||||||
|
TEST_ExpectTrue(result.length == 0); |
||||||
|
result = __().unreal.GetAllInventoryFrom(class'Winchester', chain, true); |
||||||
|
TEST_ExpectTrue(result.length == 0); |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
caseName = "UnrealAPI" |
||||||
|
caseGroup = "Unreal" |
||||||
|
} |
@ -0,0 +1,246 @@ |
|||||||
|
/** |
||||||
|
* Low-level API that provides set of utility methods for working with |
||||||
|
* unreal script classes. |
||||||
|
* Copyright 2021 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 UnrealAPI extends AcediaObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns current game's `LevelInfo`. Useful because `level` variable |
||||||
|
* is not defined inside objects. |
||||||
|
* |
||||||
|
* @return `LevelInfo` instance for the current game. Guaranteed to |
||||||
|
* not be `none`. |
||||||
|
*/ |
||||||
|
public final function LevelInfo GetLevel() |
||||||
|
{ |
||||||
|
return class'CoreService'.static.GetInstance().level; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns current game's `GameInfo`. Useful because `level.game` is not |
||||||
|
* accessible inside objects. |
||||||
|
* |
||||||
|
* @return `GameInfo` instance for the current game. Guaranteed to |
||||||
|
* not be `none`. |
||||||
|
*/ |
||||||
|
public final function GameInfo GetGameType() |
||||||
|
{ |
||||||
|
return class'CoreService'.static.GetInstance().level.game; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns current game's `GameInfo` as `KFGameType`. Useful because |
||||||
|
* `level.game` is not accessible inside objects and because it auto converts |
||||||
|
* game type to `KFGameType`, which virtually all mods for killing floor use |
||||||
|
* (by itself or as a base class). |
||||||
|
* |
||||||
|
* @return `KFGameType` instance for the current game. Can be `none` only if |
||||||
|
* game was modded to run a `GameInfo` not derived from `KFGameType`. |
||||||
|
*/ |
||||||
|
public final function KFGameType GetKFGameType() |
||||||
|
{ |
||||||
|
return KFGameType(GetGameType()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns current local player's `Controller`. Useful because `level` |
||||||
|
* is not accessible inside objects. |
||||||
|
* |
||||||
|
* @return `PlayerController` instance for the local player. `none` iff run on |
||||||
|
* dedicated servers. |
||||||
|
*/ |
||||||
|
public final function PlayerController GetLocalPlayer() |
||||||
|
{ |
||||||
|
return class'CoreService'.static.GetInstance().level |
||||||
|
.GetLocalPlayerController(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if given class of `GameRules` is currently active in `GameInfo`. |
||||||
|
* |
||||||
|
* @param rulesClassToCheck Class of rules to check for. |
||||||
|
* @return `true` if `GameRules` are active and `false` otherwise. |
||||||
|
*/ |
||||||
|
public final function bool AreGameRulesAdded( |
||||||
|
class<GameRules> rulesClassToCheck) |
||||||
|
{ |
||||||
|
local GameRules rulesIter; |
||||||
|
if (rulesClassToCheck == none) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
rulesIter = GetGameType().gameRulesModifiers; |
||||||
|
while (rulesIter != none) |
||||||
|
{ |
||||||
|
if (rulesIter.class == rulesClassToCheck) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
rulesIter = rulesIter.nextGameRules; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds new `GameRules` class to the current `GameInfo`. |
||||||
|
* Does nothing if give `GameRules` class was already added before. |
||||||
|
* |
||||||
|
* @param newRulesClass Class of rules to add. |
||||||
|
* @return `true` if `GameRules` were added and `false` otherwise |
||||||
|
* (because they were already active.) |
||||||
|
*/ |
||||||
|
public final function bool AddGameRules(class<GameRules> newRulesClass) |
||||||
|
{ |
||||||
|
if (AreGameRulesAdded(newRulesClass)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
GetGameType().AddGameModifier(GameRules(_.memory.Allocate(newRulesClass))); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes given `GameRules` class from the current `GameInfo`, |
||||||
|
* if they are active. Does nothing otherwise. |
||||||
|
* |
||||||
|
* @param rulesClassToRemove Class of rules to try and remove. |
||||||
|
* @return `true` if `GameRules` were removed and `false` otherwise |
||||||
|
* (if they were not active in the first place). |
||||||
|
*/ |
||||||
|
public final function bool RemoveGameRules(class<GameRules> rulesClassToRemove) |
||||||
|
{ |
||||||
|
local GameInfo game; |
||||||
|
local GameRules rulesIter; |
||||||
|
local GameRules rulesToDestroy; |
||||||
|
if (rulesClassToRemove == none) return false; |
||||||
|
game = GetGameType(); |
||||||
|
if (game.gameRulesModifiers == none) return false; |
||||||
|
|
||||||
|
// Check root rules |
||||||
|
rulesToDestroy = game.gameRulesModifiers; |
||||||
|
if (rulesToDestroy.class == rulesClassToRemove) |
||||||
|
{ |
||||||
|
game.gameRulesModifiers = rulesToDestroy.nextGameRules; |
||||||
|
rulesToDestroy.Destroy(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
// Check rest of the rules |
||||||
|
rulesIter = game.gameRulesModifiers; |
||||||
|
while (rulesIter != none) |
||||||
|
{ |
||||||
|
rulesToDestroy = rulesIter.nextGameRules; |
||||||
|
if ( rulesToDestroy != none |
||||||
|
&& rulesToDestroy.class == rulesClassToRemove) |
||||||
|
{ |
||||||
|
rulesIter.nextGameRules = rulesToDestroy.nextGameRules; |
||||||
|
rulesToDestroy.Destroy(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
rulesIter = rulesIter.nextGameRules; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convenience method for finding a first inventory entry of the given |
||||||
|
* class `inventoryClass` in the given inventory chain `inventoryChain`. |
||||||
|
* |
||||||
|
* Inventory is stored as a linked list, where next inventory item is available |
||||||
|
* through the `inventory` reference. This method follows this list, starting |
||||||
|
* from `inventoryChain` until it finds `Inventory` of the appropriate class |
||||||
|
* or reaches the end of the list. |
||||||
|
* |
||||||
|
* @param inventoryClass Class of the inventory we are interested in. |
||||||
|
* @param inventoryChain Inventory chain in which we should search for |
||||||
|
* the given class. |
||||||
|
* @param acceptChildClass `true` if method should also return any |
||||||
|
* `Inventory` of class derived from `inventoryClass` and `false` if |
||||||
|
* we want given class specifically (default). |
||||||
|
* @return First inventory from `inventoryChain` that matches given |
||||||
|
* `inventoryClass` class (whether exactly or as a child class, |
||||||
|
* in case `acceptChildClass == true`). |
||||||
|
*/ |
||||||
|
public final function Inventory GetInventoryFrom( |
||||||
|
class<Inventory> inventoryClass, |
||||||
|
Inventory inventoryChain, |
||||||
|
optional bool acceptChildClass) |
||||||
|
{ |
||||||
|
if (inventoryClass == none) { |
||||||
|
return none; |
||||||
|
} |
||||||
|
while (inventoryChain != none) |
||||||
|
{ |
||||||
|
if (inventoryChain.class == inventoryClass) { |
||||||
|
return inventoryChain; |
||||||
|
} |
||||||
|
if ( acceptChildClass |
||||||
|
&& ClassIsChildOf(inventoryChain.class, inventoryClass)) |
||||||
|
{ |
||||||
|
return inventoryChain; |
||||||
|
} |
||||||
|
inventoryChain = inventoryChain.inventory; |
||||||
|
} |
||||||
|
return none; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convenience method for finding a all inventory entries of the given |
||||||
|
* class `inventoryClass` in the given inventory chain `inventoryChain`. |
||||||
|
* |
||||||
|
* Inventory is stored as a linked list, where next inventory item is available |
||||||
|
* through the `inventory` reference. This method follows this list, starting |
||||||
|
* from `inventoryChain` until the end of the list. |
||||||
|
* |
||||||
|
* @param inventoryClass Class of the inventory we are interested in. |
||||||
|
* @param inventoryChain Inventory chain in which we should search for |
||||||
|
* the given class. |
||||||
|
* @param acceptChildClass `true` if method should also return any |
||||||
|
* `Inventory` of class derived from `inventoryClass` and `false` if |
||||||
|
* we want given class specifically (default). |
||||||
|
* @return Array of inventory items from `inventoryChain` that match given |
||||||
|
* `inventoryClass` class (whether exactly or as a child class, |
||||||
|
* in case `acceptChildClass == true`). |
||||||
|
*/ |
||||||
|
public final function array<Inventory> GetAllInventoryFrom( |
||||||
|
class<Inventory> inventoryClass, |
||||||
|
Inventory inventoryChain, |
||||||
|
optional bool acceptChildClass) |
||||||
|
{ |
||||||
|
local bool shouldAdd; |
||||||
|
local array<Inventory> result; |
||||||
|
if (inventoryClass == none) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
while (inventoryChain != none) |
||||||
|
{ |
||||||
|
shouldAdd = false; |
||||||
|
if (inventoryChain.class == inventoryClass) { |
||||||
|
shouldAdd = true; |
||||||
|
} |
||||||
|
else if (acceptChildClass) { |
||||||
|
shouldAdd = ClassIsChildOf(inventoryChain.class, inventoryClass); |
||||||
|
} |
||||||
|
if (shouldAdd) { |
||||||
|
result[result.length] = inventoryChain; |
||||||
|
} |
||||||
|
inventoryChain = inventoryChain.inventory; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
} |
Loading…
Reference in new issue