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