diff --git a/sources/Unreal/GameRules/AcediaGameRules.uc b/sources/Unreal/GameRules/AcediaGameRules.uc
index 8552e9f..cc02d05 100644
--- a/sources/Unreal/GameRules/AcediaGameRules.uc
+++ b/sources/Unreal/GameRules/AcediaGameRules.uc
@@ -21,6 +21,9 @@
class AcediaGameRules extends GameRules;
var private GameRules_OnFindPlayerStart_Signal onFindPlayerStartSignal;
+var private GameRules_OnHandleRestartGame_Signal onHandleRestartGameSignal;
+var private GameRules_OnCheckEndGame_Signal onCheckEndGameSignal;
+var private GameRules_OnCheckScore_Signal onCheckScoreSignal;
var private GameRules_OnOverridePickupQuery_Signal onOverridePickupQuery;
var private GameRules_OnNetDamage_Signal onNetDamage;
@@ -31,6 +34,12 @@ public final function Initialize(unrealService service)
}
onFindPlayerStartSignal = GameRules_OnFindPlayerStart_Signal(
service.GetSignal(class'GameRules_OnFindPlayerStart_Signal'));
+ onHandleRestartGameSignal = GameRules_OnHandleRestartGame_Signal(
+ service.GetSignal(class'GameRules_OnHandleRestartGame_Signal'));
+ onCheckEndGameSignal = GameRules_OnCheckEndGame_Signal(
+ service.GetSignal(class'GameRules_OnCheckEndGame_Signal'));
+ onCheckScoreSignal = GameRules_OnCheckScore_Signal(
+ service.GetSignal(class'GameRules_OnCheckScore_Signal'));
onOverridePickupQuery = GameRules_OnOverridePickupQuery_Signal(
service.GetSignal(class'GameRules_OnOverridePickupQuery_Signal'));
onNetDamage = GameRules_OnNetDamage_Signal(
@@ -62,6 +71,43 @@ function NavigationPoint FindPlayerStart(
return result;
}
+function bool HandleRestartGame()
+{
+ local bool result;
+ if (onHandleRestartGameSignal != none) {
+ result = onHandleRestartGameSignal.Emit();
+ }
+ if (nextGameRules != none && nextGameRules.HandleRestartGame()) {
+ return true;
+ }
+ return result;
+}
+
+function bool CheckEndGame(PlayerReplicationInfo winner, string reason)
+{
+ local bool result;
+ result = true;
+ if (onCheckEndGameSignal != none) {
+ result = onCheckEndGameSignal.Emit(winner, reason);
+ }
+ if (nextGameRules != none && !nextGameRules.HandleRestartGame()) {
+ return false;
+ }
+ return result;
+}
+
+function bool CheckScore(PlayerReplicationInfo scorer)
+{
+ local bool result;
+ if (onCheckScoreSignal != none) {
+ result = onCheckScoreSignal.Emit(scorer);
+ }
+ if (nextGameRules != none && nextGameRules.CheckScore(Scorer)) {
+ return true;
+ }
+ return result;
+}
+
function bool OverridePickupQuery(
Pawn other,
Pickup item,
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Signal.uc b/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Signal.uc
new file mode 100644
index 0000000..59a9cd3
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Signal.uc
@@ -0,0 +1,47 @@
+/**
+ * Signal class implementation for `GameRulesAPI`'s `OnCheckEndGame` 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 .
+ */
+class GameRules_OnCheckEndGame_Signal extends Signal;
+
+public final function bool Emit(
+ PlayerReplicationInfo winner,
+ string reason)
+{
+ local Slot nextSlot;
+ local bool result, nextReply;
+ StartIterating();
+ nextSlot = GetNextSlot();
+ result = true;
+ while (nextSlot != none)
+ {
+ nextReply = GameRules_OnCheckEndGame_Slot(nextSlot)
+ .connect(winner, reason);
+ if (!nextReply && !nextSlot.IsEmpty()) {
+ result = result && nextReply;
+ }
+ nextSlot = GetNextSlot();
+ }
+ CleanEmptySlots();
+ return result;
+}
+
+defaultproperties
+{
+ relatedSlotClass = class'GameRules_OnCheckEndGame_Slot'
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Slot.uc b/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Slot.uc
new file mode 100644
index 0000000..7395e4f
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnCheckEndGame_Slot.uc
@@ -0,0 +1,41 @@
+/**
+ * Slot class implementation for `GameRulesAPI`'s `OnCheckEndGame` 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 .
+ */
+class GameRules_OnCheckEndGame_Slot extends Slot;
+
+delegate bool connect(PlayerReplicationInfo winner, string reason)
+{
+ DummyCall();
+ return true;
+}
+
+protected function Constructor()
+{
+ connect = none;
+}
+
+protected function Finalizer()
+{
+ super.Finalizer();
+ connect = none;
+}
+
+defaultproperties
+{
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Signal.uc b/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Signal.uc
new file mode 100644
index 0000000..012612f
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Signal.uc
@@ -0,0 +1,44 @@
+/**
+ * Signal class implementation for `GameRulesAPI`'s `OnCheckScore` 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 .
+ */
+class GameRules_OnCheckScore_Signal extends Signal;
+
+public final function bool Emit(PlayerReplicationInfo scorer)
+{
+ local Slot nextSlot;
+ local bool result, nextReply;
+ StartIterating();
+ nextSlot = GetNextSlot();
+ result = true;
+ while (nextSlot != none)
+ {
+ nextReply = GameRules_OnCheckScore_Slot(nextSlot).connect(scorer);
+ if (!nextReply && !nextSlot.IsEmpty()) {
+ result = result && nextReply;
+ }
+ nextSlot = GetNextSlot();
+ }
+ CleanEmptySlots();
+ return result;
+}
+
+defaultproperties
+{
+ relatedSlotClass = class'GameRules_OnCheckScore_Slot'
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Slot.uc b/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Slot.uc
new file mode 100644
index 0000000..e931aec
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnCheckScore_Slot.uc
@@ -0,0 +1,41 @@
+/**
+ * Slot class implementation for `GameRulesAPI`'s `OnCheckScore` 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 .
+ */
+class GameRules_OnCheckScore_Slot extends Slot;
+
+delegate bool connect(PlayerReplicationInfo scorer)
+{
+ DummyCall();
+ return true;
+}
+
+protected function Constructor()
+{
+ connect = none;
+}
+
+protected function Finalizer()
+{
+ super.Finalizer();
+ connect = none;
+}
+
+defaultproperties
+{
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnFindPlayerStart_Signal.uc b/sources/Unreal/GameRules/Events/GameRules_OnFindPlayerStart_Signal.uc
index 61cba42..6978309 100644
--- a/sources/Unreal/GameRules/Events/GameRules_OnFindPlayerStart_Signal.uc
+++ b/sources/Unreal/GameRules/Events/GameRules_OnFindPlayerStart_Signal.uc
@@ -22,8 +22,7 @@ class GameRules_OnFindPlayerStart_Signal extends Signal;
public final function NavigationPoint Emit(
Controller player,
optional byte inTeam,
- optional string incomingName
-)
+ optional string incomingName)
{
local Slot nextSlot;
local NavigationPoint nextPoint;
@@ -33,7 +32,9 @@ public final function NavigationPoint Emit(
{
nextPoint = GameRules_OnFindPlayerStart_Slot(nextSlot)
.connect(player, inTeam, incomingName);
- if (nextPoint != none && !nextSlot.IsEmpty()) {
+ if (nextPoint != none && !nextSlot.IsEmpty())
+ {
+ CleanEmptySlots();
return nextPoint;
}
nextSlot = GetNextSlot();
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Signal.uc b/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Signal.uc
new file mode 100644
index 0000000..e5b9ea2
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Signal.uc
@@ -0,0 +1,44 @@
+/**
+ * Signal class implementation for `GameRulesAPI`'s
+ * `OnHandleRestartGame` 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 .
+ */
+class GameRules_OnHandleRestartGame_Signal extends Signal;
+
+public final function bool Emit()
+{
+ local Slot nextSlot;
+ local bool doPrevent, nextResult;
+ StartIterating();
+ nextSlot = GetNextSlot();
+ while (nextSlot != none)
+ {
+ nextResult = GameRules_OnHandleRestartGame_Slot(nextSlot).connect();
+ if (nextResult && !nextSlot.IsEmpty()) {
+ doPrevent = doPrevent || nextResult;
+ }
+ nextSlot = GetNextSlot();
+ }
+ CleanEmptySlots();
+ return doPrevent;
+}
+
+defaultproperties
+{
+ relatedSlotClass = class'GameRules_OnHandleRestartGame_Slot'
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Slot.uc b/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Slot.uc
new file mode 100644
index 0000000..2386429
--- /dev/null
+++ b/sources/Unreal/GameRules/Events/GameRules_OnHandleRestartGame_Slot.uc
@@ -0,0 +1,41 @@
+/**
+ * Slot class implementation for `GameRulesAPI`'s `OnHandleRestartGame` 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 .
+ */
+class GameRules_OnHandleRestartGame_Slot extends Slot;
+
+delegate bool connect()
+{
+ DummyCall();
+ return false;
+}
+
+protected function Constructor()
+{
+ connect = none;
+}
+
+protected function Finalizer()
+{
+ super.Finalizer();
+ connect = none;
+}
+
+defaultproperties
+{
+}
\ No newline at end of file
diff --git a/sources/Unreal/GameRules/Events/GameRules_OnOverridePickupQuery_Signal.uc b/sources/Unreal/GameRules/Events/GameRules_OnOverridePickupQuery_Signal.uc
index ff54155..c52a00e 100644
--- a/sources/Unreal/GameRules/Events/GameRules_OnOverridePickupQuery_Signal.uc
+++ b/sources/Unreal/GameRules/Events/GameRules_OnOverridePickupQuery_Signal.uc
@@ -30,7 +30,9 @@ public final function bool Emit(Pawn other, Pickup item, out byte allowPickup)
{
shouldOverride = GameRules_OnOverridePickupQuery_Slot(nextSlot)
.connect(other, item, allowPickup);
- if (shouldOverride && !nextSlot.IsEmpty()) {
+ if (shouldOverride && !nextSlot.IsEmpty())
+ {
+ CleanEmptySlots();
return shouldOverride;
}
nextSlot = GetNextSlot();
diff --git a/sources/Unreal/GameRules/GameRulesAPI.uc b/sources/Unreal/GameRules/GameRulesAPI.uc
index 6b19cfb..a97013e 100644
--- a/sources/Unreal/GameRules/GameRulesAPI.uc
+++ b/sources/Unreal/GameRules/GameRulesAPI.uc
@@ -20,8 +20,6 @@
*/
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
@@ -46,15 +44,84 @@ public final function GameRules_OnFindPlayerStart_Slot OnFindPlayerStart(
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));
}
+/**
+ * Called in `GameInfo`'s `RestartGame()` method and allows to prevent
+ * game's restart.
+ *
+ * This signal will always be propagated to all registered slots.
+ *
+ * [Signature]
+ * bool ()
+ *
+ * @return `true` if you want to prevent game restart and `false` otherwise.
+ */
+/* SIGNAL */
+public final function GameRules_OnHandleRestartGame_Slot OnHandleRestartGame(
+ AcediaObject receiver)
+{
+ local Signal signal;
+ local UnrealService service;
+ service = UnrealService(class'UnrealService'.static.Require());
+ signal = service.GetSignal(class'GameRules_OnHandleRestartGame_Signal');
+ return GameRules_OnHandleRestartGame_Slot(signal.NewSlot(receiver));
+}
+
+/**
+ * Allows modification of game ending conditions.
+ * Return `false` to prevent game from ending.
+ *
+ * This signal will always be propagated to all registered slots.
+ *
+ * [Signature]
+ * bool (PlayerReplicationInfo winner, string reason)
+ *
+ * @param winner Replication info of the supposed winner of the game.
+ * @param reason String with a description about how/why `winner` has won.
+ * @return `false` if you want to prevent game from ending
+ * and `false` otherwise.
+ */
+/* SIGNAL */
+public final function GameRules_OnCheckEndGame_Slot OnCheckEndGame(
+ AcediaObject receiver)
+{
+ local Signal signal;
+ local UnrealService service;
+ service = UnrealService(class'UnrealService'.static.Require());
+ signal = service.GetSignal(class'GameRules_OnHandleRestartGame_Signal');
+ return GameRules_OnCheckEndGame_Slot(signal.NewSlot(receiver));
+}
+
+/* CheckScore()
+
+*/
+/**
+ * Check if this score means the game ends.
+ *
+ * Return `true` to override `GameInfo`'s `CheckScore()`, or if game was ended
+ * (with a call to `Level.Game.EndGame()`).
+ *
+ * [Signature]
+ * bool (PlayerReplicationInfo scorer)
+ *
+ * @param scorer For whom to do a score check.
+ * @return `true` to override `GameInfo`'s `CheckScore()`, or if game was ended
+ * and `false` otherwise.
+ */
+/* SIGNAL */
+public final function GameRules_OnCheckScore_Slot OnCheckScore(
+ AcediaObject receiver)
+{
+ local Signal signal;
+ local UnrealService service;
+ service = UnrealService(class'UnrealService'.static.Require());
+ signal = service.GetSignal(class'GameRules_OnCheckScore_Signal');
+ return GameRules_OnCheckScore_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
@@ -82,16 +149,10 @@ public final function GameRules_OnOverridePickupQuery_Slot
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
@@ -119,11 +180,6 @@ public final function GameRules_OnNetDamage_Slot OnNetDamage(
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));
}
@@ -228,5 +284,4 @@ public final function bool AreAdded(
defaultproperties
{
- errNoService = (l=LOG_Error,m="`UnrealService` could not be reached.")
}
\ No newline at end of file
diff --git a/sources/Unreal/UnrealService.uc b/sources/Unreal/UnrealService.uc
index f57bcb0..10cdc57 100644
--- a/sources/Unreal/UnrealService.uc
+++ b/sources/Unreal/UnrealService.uc
@@ -87,6 +87,9 @@ public event Tick(float delta)
defaultproperties
{
serviceSignals(0) = (signalClass=class'GameRules_OnFindPlayerStart_Signal')
- serviceSignals(1) = (signalClass=class'GameRules_OnOverridePickupQuery_Signal')
- serviceSignals(2) = (signalClass=class'GameRules_OnNetDamage_Signal')
+ serviceSignals(1) = (signalClass=class'GameRules_OnHandleRestartGame_Signal')
+ serviceSignals(2) = (signalClass=class'GameRules_OnCheckEndGame_Signal')
+ serviceSignals(3) = (signalClass=class'GameRules_OnCheckScore_Signal')
+ serviceSignals(4) = (signalClass=class'GameRules_OnOverridePickupQuery_Signal')
+ serviceSignals(5) = (signalClass=class'GameRules_OnNetDamage_Signal')
}
\ No newline at end of file