Anton Tarasenko
4 years ago
13 changed files with 892 additions and 116 deletions
@ -0,0 +1,38 @@
|
||||
/** |
||||
* Signal class implementation for `UnrealAPI`'s `OnTick` signal. |
||||
* 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 Unreal_OnTick_Signal extends Signal; |
||||
|
||||
public final function Emit(float delta, float dilationCoefficient) |
||||
{ |
||||
local Slot nextSlot; |
||||
StartIterating(); |
||||
nextSlot = GetNextSlot(); |
||||
while (nextSlot != none) |
||||
{ |
||||
Unreal_OnTick_Slot(nextSlot).connect(delta, dilationCoefficient); |
||||
nextSlot = GetNextSlot(); |
||||
} |
||||
CleanEmptySlots(); |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
relatedSlotClass = class'Unreal_OnTick_Slot' |
||||
} |
@ -0,0 +1,40 @@
|
||||
/** |
||||
* Slot class implementation for `UnrealAPI`'s `OnTick` signal. |
||||
* 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 Unreal_OnTick_Slot extends Slot; |
||||
|
||||
delegate connect(float delta, float dilationCoefficient) |
||||
{ |
||||
DummyCall(); |
||||
} |
||||
|
||||
protected function Constructor() |
||||
{ |
||||
connect = none; |
||||
} |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
super.Finalizer(); |
||||
connect = none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,109 @@
|
||||
/** |
||||
* Acedia's `GameRules` class that provides `GameRules`'s events through |
||||
* the signal/slot functionality. |
||||
* 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 AcediaGameRules extends GameRules; |
||||
|
||||
var private GameRules_OnFindPlayerStart_Signal onFindPlayerStartSignal; |
||||
var private GameRules_OnOverridePickupQuery_Signal onOverridePickupQuery; |
||||
var private GameRules_OnNetDamage_Signal onNetDamage; |
||||
|
||||
public final function Initialize(unrealService service) |
||||
{ |
||||
if (service == none) { |
||||
return; |
||||
} |
||||
onFindPlayerStartSignal = GameRules_OnFindPlayerStart_Signal( |
||||
service.GetSignal(class'GameRules_OnFindPlayerStart_Signal')); |
||||
onOverridePickupQuery = GameRules_OnOverridePickupQuery_Signal( |
||||
service.GetSignal(class'GameRules_OnOverridePickupQuery_Signal')); |
||||
onNetDamage = GameRules_OnNetDamage_Signal( |
||||
service.GetSignal(class'GameRules_OnNetDamage_Signal')); |
||||
} |
||||
|
||||
function string GetRules() |
||||
{ |
||||
local string resultSet; |
||||
resultSet = "acedia"; |
||||
if (nextGameRules != none) { |
||||
resultSet = resultSet $ nextGameRules.GetRules(); |
||||
} |
||||
return resultSet; |
||||
} |
||||
|
||||
function NavigationPoint FindPlayerStart( |
||||
Controller player, |
||||
optional byte inTeam, |
||||
optional string incomingName) |
||||
{ |
||||
local NavigationPoint result; |
||||
if (onFindPlayerStartSignal != none) { |
||||
result = onFindPlayerStartSignal.Emit(player, inTeam, incomingName); |
||||
} |
||||
if (result == none && nextGameRules != none) { |
||||
return nextGameRules.FindPlayerStart(player, inTeam, incomingName); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
function bool OverridePickupQuery( |
||||
Pawn other, |
||||
Pickup item, |
||||
out byte allowPickup) |
||||
{ |
||||
local bool shouldOverride; |
||||
if (onOverridePickupQuery != none) { |
||||
shouldOverride = onOverridePickupQuery.Emit(other, item, allowPickup); |
||||
} |
||||
if (shouldOverride) { |
||||
return true; |
||||
} |
||||
if (nextGameRules != none) { |
||||
return nextGameRules.OverridePickupQuery(other, item, allowPickup); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
function int NetDamage( |
||||
int originalDamage, |
||||
int damage, |
||||
Pawn injured, |
||||
Pawn instigatedBy, |
||||
Vector hitLocation, |
||||
out Vector momentum, |
||||
class<DamageType> damageType) |
||||
{ |
||||
if (onNetDamage != none) |
||||
{ |
||||
damage = onNetDamage.Emit( originalDamage, damage, injured, |
||||
instigatedBy, hitLocation, momentum, |
||||
damageType); |
||||
} |
||||
if (nextGameRules != none) |
||||
{ |
||||
return nextGameRules.NetDamage( originalDamage, damage, injured, |
||||
instigatedBy, hitLocation, momentum, |
||||
damageType); |
||||
} |
||||
return damage; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,48 @@
|
||||
/** |
||||
* Signal class implementation for `GameRulesAPI`'s `OnFindPlayerStart` signal. |
||||
* 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 GameRules_OnFindPlayerStart_Signal extends Signal; |
||||
|
||||
public final function NavigationPoint Emit( |
||||
Controller player, |
||||
optional byte inTeam, |
||||
optional string incomingName |
||||
) |
||||
{ |
||||
local Slot nextSlot; |
||||
local NavigationPoint nextPoint; |
||||
StartIterating(); |
||||
nextSlot = GetNextSlot(); |
||||
while (nextSlot != none) |
||||
{ |
||||
nextPoint = GameRules_OnFindPlayerStart_Slot(nextSlot) |
||||
.connect(player, inTeam, incomingName); |
||||
if (nextPoint != none && !nextSlot.IsEmpty()) { |
||||
return nextPoint; |
||||
} |
||||
nextSlot = GetNextSlot(); |
||||
} |
||||
CleanEmptySlots(); |
||||
return none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
relatedSlotClass = class'GameRules_OnFindPlayerStart_Slot' |
||||
} |
@ -0,0 +1,44 @@
|
||||
/** |
||||
* Slot class implementation for `GameRulesAPI`'s `OnFindPlayerStart` signal. |
||||
* 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 GameRules_OnFindPlayerStart_Slot extends Slot; |
||||
|
||||
delegate NavigationPoint connect( |
||||
Controller player, |
||||
optional byte inTeam, |
||||
optional string incomingName) |
||||
{ |
||||
DummyCall(); |
||||
return none; |
||||
} |
||||
|
||||
protected function Constructor() |
||||
{ |
||||
connect = none; |
||||
} |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
super.Finalizer(); |
||||
connect = none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,52 @@
|
||||
/** |
||||
* Signal class implementation for `GameRulesAPI`'s `OnNetDamage` signal. |
||||
* 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 GameRules_OnNetDamage_Signal extends Signal; |
||||
|
||||
public final function int Emit( |
||||
int originalDamage, |
||||
int damage, |
||||
Pawn injured, |
||||
Pawn instigatedBy, |
||||
Vector hitLocation, |
||||
out Vector momentum, |
||||
class<DamageType> damageType) |
||||
{ |
||||
local Slot nextSlot; |
||||
local int newDamage; |
||||
StartIterating(); |
||||
nextSlot = GetNextSlot(); |
||||
while (nextSlot != none) |
||||
{ |
||||
newDamage = GameRules_OnNetDamage_Slot(nextSlot) |
||||
.connect( originalDamage, damage, injured, instigatedBy, |
||||
hitLocation, momentum, damageType); |
||||
if (!nextSlot.IsEmpty()) { |
||||
damage = newDamage; |
||||
} |
||||
nextSlot = GetNextSlot(); |
||||
} |
||||
CleanEmptySlots(); |
||||
return damage; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
relatedSlotClass = class'GameRules_OnNetDamage_Slot' |
||||
} |
@ -0,0 +1,49 @@
|
||||
/** |
||||
* Slot class implementation for `GameRulesAPI`'s `OnNetDamage` signal. |
||||
* 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 GameRules_OnNetDamage_Slot extends Slot; |
||||
|
||||
delegate int connect( |
||||
int originalDamage, |
||||
int damage, |
||||
Pawn injured, |
||||
Pawn instigatedBy, |
||||
Vector hitLocation, |
||||
out Vector momentum, |
||||
class<DamageType> damageType) |
||||
{ |
||||
DummyCall(); |
||||
// Do not alter any already made modifications |
||||
return damage; |
||||
} |
||||
|
||||
protected function Constructor() |
||||
{ |
||||
connect = none; |
||||
} |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
super.Finalizer(); |
||||
connect = none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,45 @@
|
||||
/** |
||||
* Signal class implementation for `GameRulesAPI`'s |
||||
* `OnOverridePickupQuerySignal` signal. |
||||
* 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 GameRules_OnOverridePickupQuery_Signal extends Signal; |
||||
|
||||
public final function bool Emit(Pawn other, Pickup item, out byte allowPickup) |
||||
{ |
||||
local Slot nextSlot; |
||||
local bool shouldOverride; |
||||
StartIterating(); |
||||
nextSlot = GetNextSlot(); |
||||
while (nextSlot != none) |
||||
{ |
||||
shouldOverride = GameRules_OnOverridePickupQuery_Slot(nextSlot) |
||||
.connect(other, item, allowPickup); |
||||
if (shouldOverride && !nextSlot.IsEmpty()) { |
||||
return shouldOverride; |
||||
} |
||||
nextSlot = GetNextSlot(); |
||||
} |
||||
CleanEmptySlots(); |
||||
return false; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
relatedSlotClass = class'GameRules_OnOverridePickupQuery_Slot' |
||||
} |
@ -0,0 +1,46 @@
|
||||
/** |
||||
* Slot class implementation for `GameRulesAPI`'s |
||||
* `OnOverridePickupQuerySignal` signal. |
||||
* 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 GameRules_OnOverridePickupQuery_Slot extends Slot; |
||||
|
||||
delegate bool connect( |
||||
Pawn other, |
||||
Pickup item, |
||||
out byte allowPickup) |
||||
{ |
||||
DummyCall(); |
||||
// Do not override pickup queue by default |
||||
return false; |
||||
} |
||||
|
||||
protected function Constructor() |
||||
{ |
||||
connect = none; |
||||
} |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
super.Finalizer(); |
||||
connect = none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,232 @@
|
||||
/** |
||||
* Low-level API that provides set of utility methods for working with |
||||
* `GameRule`s. |
||||
* 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 GameRulesAPI extends AcediaObject; |
||||
|
||||
var private LoggerAPI.Definition errNoService; |
||||
|
||||
/** |
||||
* Called when game decides on a player's spawn point. If a `NavigationPoint` |
||||
* is returned, signal propagation will be interrupted and returned value will |
||||
* be used as the player start. |
||||
* |
||||
* [Signature] |
||||
* NavigationPoint <slot>( |
||||
* Controller player, |
||||
* optional byte inTeam, |
||||
* optional string incomingName) |
||||
* |
||||
* @param player Player for whom we are picking a spawn point. |
||||
* @param inTeam Player's team number. |
||||
* @param incomingName `Portal` parameter from `GameInfo.Login()` event. |
||||
* @return `NavigationPoint` that will player must be spawned at. |
||||
* `none` means that slot does not want to modify it. |
||||
*/ |
||||
/* SIGNAL */ |
||||
public final function GameRules_OnFindPlayerStart_Slot OnFindPlayerStart( |
||||
AcediaObject receiver) |
||||
{ |
||||
local Signal signal; |
||||
local UnrealService service; |
||||
service = UnrealService(class'UnrealService'.static.Require()); |
||||
if (service == none) |
||||
{ |
||||
_.logger.Auto(errNoService); |
||||
return none; |
||||
} |
||||
signal = service.GetSignal(class'GameRules_OnFindPlayerStart_Signal'); |
||||
return GameRules_OnFindPlayerStart_Slot(signal.NewSlot(receiver)); |
||||
} |
||||
|
||||
/** |
||||
* When pawn wants to pickup something, `GameRule`s are given a chance to |
||||
* modify it. If one of the `Slot`s returns `true`, `allowPickup` will |
||||
* determine if the object can be picked up. |
||||
* Overriding via this method allows to completely bypass check against |
||||
* `Pawn`'s inventory's `HandlePickupQuery()` method. |
||||
* |
||||
* [Signature] |
||||
* bool <slot>(Pawn other, Pickup item, out byte allowPickup) |
||||
* |
||||
* @param other Pawn which will potentially pickup `item`. |
||||
* @param item Pickup which `other` might potentially pickup. |
||||
* @param allowPickup `true` if you want to force `other` to pickup an item |
||||
* and `false` otherwise. This parameter is ignored if returned value of |
||||
* your slot call is `false`. |
||||
* @return `true` if you wish to override decision about pickup with |
||||
* `allowPickup` and `false` if you do not want to make that decision. |
||||
* If you do decide to override decision by returning `true` - this signal |
||||
* will not be propagated to the rest of the slots. |
||||
*/ |
||||
/* SIGNAL */ |
||||
public final function GameRules_OnOverridePickupQuery_Slot |
||||
OnOverridePickupQuery(AcediaObject receiver) |
||||
{ |
||||
local Signal signal; |
||||
local UnrealService service; |
||||
service = UnrealService(class'UnrealService'.static.Require()); |
||||
if (service == none) |
||||
{ |
||||
_.logger.Auto(errNoService); |
||||
return none; |
||||
} |
||||
signal = service.GetSignal(class'GameRules_OnOverridePickupQuery_Signal'); |
||||
return GameRules_OnOverridePickupQuery_Slot(signal.NewSlot(receiver)); |
||||
} |
||||
|
||||
// TODO: rewrite |
||||
/** |
||||
* When pawn wants to pickup something, `GameRule`s are given a chance to |
||||
* modify it. If one of the `Slot`s returns `true`, `allowPickup` will |
||||
* determine if the object can be picked up. |
||||
* Overriding via this method allows to completely bypass check against |
||||
* `Pawn`'s inventory's `HandlePickupQuery()` method. |
||||
* |
||||
* [Signature] |
||||
* bool <slot>(Pawn other, Pickup item, out byte allowPickup) |
||||
* |
||||
* @param other Pawn which will potentially pickup `item`. |
||||
* @param item Pickup which `other` might potentially pickup. |
||||
* @param allowPickup `true` if you want to force `other` to pickup an item |
||||
* and `false` otherwise. This parameter is ignored if returned value of |
||||
* your slot call is `false`. |
||||
* @return `true` if you wish to override decision about pickup with |
||||
* `allowPickup` and `false` if you do not want to make that decision. |
||||
* If you do decide to override decision by returning `true` - this signal |
||||
* will not be propagated to the rest of the slots. |
||||
*/ |
||||
/* SIGNAL */ |
||||
public final function GameRules_OnNetDamage_Slot OnNetDamage( |
||||
AcediaObject receiver) |
||||
{ |
||||
local Signal signal; |
||||
local UnrealService service; |
||||
service = UnrealService(class'UnrealService'.static.Require()); |
||||
if (service == none) |
||||
{ |
||||
_.logger.Auto(errNoService); |
||||
return none; |
||||
} |
||||
signal = service.GetSignal(class'GameRules_OnNetDamage_Signal'); |
||||
return GameRules_OnNetDamage_Slot(signal.NewSlot(receiver)); |
||||
} |
||||
|
||||
/** |
||||
* 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 Add(class<GameRules> newRulesClass) |
||||
{ |
||||
if (AreAdded(newRulesClass)) { |
||||
return false; |
||||
} |
||||
_.unreal.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 Remove(class<GameRules> rulesClassToRemove) |
||||
{ |
||||
local GameInfo game; |
||||
local GameRules rulesIter; |
||||
local GameRules rulesToDestroy; |
||||
if (rulesClassToRemove == none) return false; |
||||
game = _.unreal.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; |
||||
} |
||||
|
||||
/** |
||||
* Finds given class of `GameRules` if it's currently active in `GameInfo`. |
||||
* Returns `none` otherwise. |
||||
* |
||||
* @param rulesClassToFind Class of rules to find. |
||||
* @return `GameRules` of given class `rulesClassToFind` instance added to |
||||
* `GameInfo`'s records and `none` if no such rules are currently added. |
||||
*/ |
||||
public final function GameRules FindInstance( |
||||
class<GameRules> rulesClassToFind) |
||||
{ |
||||
local GameRules rulesIter; |
||||
if (rulesClassToFind == none) { |
||||
return none; |
||||
} |
||||
rulesIter = _.unreal.GetGameType().gameRulesModifiers; |
||||
while (rulesIter != none) |
||||
{ |
||||
if (rulesIter.class == rulesClassToFind) { |
||||
return rulesIter; |
||||
} |
||||
rulesIter = rulesIter.nextGameRules; |
||||
} |
||||
return none; |
||||
} |
||||
|
||||
/** |
||||
* 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 AreAdded( |
||||
class<GameRules> rulesClassToCheck) |
||||
{ |
||||
return (FindInstance(rulesClassToCheck) != none); |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
errNoService = (l=LOG_Error,m="`UnrealService` could not be reached.") |
||||
} |
@ -0,0 +1,92 @@
|
||||
/** |
||||
* Service for the needs of `UnrealAPI`. Mainly tasked with creating API's |
||||
* `Signal`s. |
||||
* 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 UnrealService extends Service; |
||||
|
||||
struct SignalRecord |
||||
{ |
||||
var class<Signal> signalClass; |
||||
var Signal instance; |
||||
}; |
||||
var private array<SignalRecord> serviceSignals; |
||||
var private Unreal_OnTick_Signal onTickSignal; |
||||
|
||||
protected function OnLaunch() |
||||
{ |
||||
local AcediaGameRules gameRules; |
||||
CreateSignals(); |
||||
_.unreal.gameRules.Add(class'AcediaGameRules'); |
||||
gameRules = AcediaGameRules( |
||||
_.unreal.gameRules.FindInstance(class'AcediaGameRules')); |
||||
gameRules.Initialize(self); |
||||
} |
||||
|
||||
protected function OnShutdown() |
||||
{ |
||||
_.unreal.gameRules.Remove(class'AcediaGameRules'); |
||||
} |
||||
|
||||
private final function CreateSignals() |
||||
{ |
||||
local int i; |
||||
onTickSignal = Unreal_OnTick_Signal( |
||||
_.memory.Allocate(class'Unreal_OnTick_Signal')); |
||||
for (i = 0; i < serviceSignals.length; i += 1) |
||||
{ |
||||
if (serviceSignals[i].instance != none) continue; |
||||
if (serviceSignals[i].signalClass == none) continue; |
||||
|
||||
serviceSignals[i].instance = |
||||
Signal(_.memory.Allocate(serviceSignals[i].signalClass)); |
||||
} |
||||
} |
||||
|
||||
public final function Signal GetSignal(class<Signal> requiredClass) |
||||
{ |
||||
local int i; |
||||
if (requiredClass == class'Unreal_OnTick_Signal') { |
||||
return onTickSignal; |
||||
} |
||||
for (i = 0; i < serviceSignals.length; i += 1) |
||||
{ |
||||
if (serviceSignals[i].signalClass == requiredClass) { |
||||
return serviceSignals[i].instance; |
||||
} |
||||
} |
||||
return none; |
||||
} |
||||
|
||||
|
||||
public event Tick(float delta) |
||||
{ |
||||
local float dilationCoefficient; |
||||
if (onTickSignal != none) |
||||
{ |
||||
dilationCoefficient = level.timeDilation / 1.1; |
||||
onTickSignal.Emit(delta, dilationCoefficient); |
||||
} |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
serviceSignals(0) = (signalClass=class'GameRules_OnFindPlayerStart_Signal') |
||||
serviceSignals(1) = (signalClass=class'GameRules_OnOverridePickupQuery_Signal') |
||||
serviceSignals(2) = (signalClass=class'GameRules_OnNetDamage_Signal') |
||||
} |
Loading…
Reference in new issue