From 55a1bb91b9b7e137ac7e38e2ada72a1ba2891156 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Fri, 1 Jul 2022 19:23:35 +0700 Subject: [PATCH] Add `EPawn` interface and its implementation --- .../Gameplay/BaseClasses/Frontend/EPawn.uc | 57 +++++++ .../BaseClasses/Frontend/EPlaceable.uc | 31 ++++ .../KF1Frontend/BaseImplementation/EKFPawn.uc | 154 ++++++++++++++++++ sources/Players/EPlayer.uc | 21 +++ 4 files changed, 263 insertions(+) create mode 100644 sources/Gameplay/BaseClasses/Frontend/EPawn.uc create mode 100644 sources/Gameplay/BaseClasses/Frontend/EPlaceable.uc create mode 100644 sources/Gameplay/KF1Frontend/BaseImplementation/EKFPawn.uc diff --git a/sources/Gameplay/BaseClasses/Frontend/EPawn.uc b/sources/Gameplay/BaseClasses/Frontend/EPawn.uc new file mode 100644 index 0000000..cfed609 --- /dev/null +++ b/sources/Gameplay/BaseClasses/Frontend/EPawn.uc @@ -0,0 +1,57 @@ +/** + * Interface for a *Pawn* - base class for any entity that can be + * controlled by player or AI. To avoid purity for the sake of itself, in + * Acedia it will also be bundled with such typical components as health, + * collision, etc. + * Copyright 2022 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 EPawn extends EPlaceable + abstract; + +/** + * Returns current amount of health caller `EPawn`'s referred entity has, + * assuming that entity has a health component. + * + * @return Current amount of health caller `EPawn`'s entity has. + * If entity that caller `EPawn` refers to doesn't have health component - + * returns `0`. + */ +public function int GetHealth() +{ + return 0; +} + +/** + * Returns current maximum amount of health caller `EPawn`'s referred entity can + * have, assuming that entity has a health component. + * + * @return Current maximum amount of health caller `EPawn`'s entity can have. + * If entity that caller `EPawn` refers to doesn't have health component - + * returns `0`. + */ +public function int GetMaxHealth(); + +/** + * Produces a suicide event for caller `EPawn`, making it drain its health and + * change its state into dead, whatever it means for the caller `EPawn`. + */ +public function Suicide(); + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/Gameplay/BaseClasses/Frontend/EPlaceable.uc b/sources/Gameplay/BaseClasses/Frontend/EPlaceable.uc new file mode 100644 index 0000000..3048041 --- /dev/null +++ b/sources/Gameplay/BaseClasses/Frontend/EPlaceable.uc @@ -0,0 +1,31 @@ +/** + * Interface for any entity that can be placed into the game world. + * Copyright 2022 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 EPlaceable extends EInterface; + +/** + * Returns position of the caller `EPlaceable` + * + * @return Vector that describes position of the caller `EPlaceable`. + */ +public function Vector GetLocation(); + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFPawn.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFPawn.uc new file mode 100644 index 0000000..08f5f6c --- /dev/null +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFPawn.uc @@ -0,0 +1,154 @@ +/** + * Implementation of `EPawn` for classic Killing Floor weapons that changes + * as little as possible and only on request from another mod, otherwise not + * altering gameplay at all. + * Copyright 2022 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 EKFPawn extends EPawn; + +var private NativeActorRef pawnReference; + +protected function Finalizer() +{ + _.memory.Free(pawnReference); + pawnReference = none; +} + +/** + * Creates new `EKFPawn` that refers to the `pawnInstance` weapon. + * + * @param pawnInstance Native pawn class that new `EKFPawn` will represent. + * @return New `EKFPawn` that represents given `pawnInstance`. + */ +public final static /*unreal*/ function EKFPawn Wrap(Pawn pawnInstance) +{ + local EKFPawn newReference; + + if (pawnInstance == none) { + return none; + } + newReference = EKFPawn(__().memory.Allocate(class'EKFPawn')); + newReference.pawnReference = __().unreal.ActorRef(pawnInstance); + return newReference; +} + +public function EInterface Copy() +{ + local Pawn pawnInstance; + + pawnInstance = GetNativeInstance(); + return Wrap(pawnInstance); +} + +public function bool Supports(class newInterfaceClass) +{ + if (newInterfaceClass == none) return false; + if (newInterfaceClass == class'EPlaceable') return true; + if (newInterfaceClass == class'EKFPawn') return true; + + return false; +} + +public function EInterface As(class newInterfaceClass) +{ + if (!IsExistent()) { + return none; + } + if ( newInterfaceClass == class'EPlaceable' + || newInterfaceClass == class'EKFPawn') + { + return Copy(); + } + return none; +} + +public function bool IsExistent() +{ + return (GetNativeInstance() != none); +} + +public function bool SameAs(EInterface other) +{ + local EKFPawn otherPawn; + + otherPawn = EKFPawn(other); + if (otherPawn == none) { + return false; + } + return (GetNativeInstance() == otherPawn.GetNativeInstance()); +} + +/** + * Returns `Pawn` instance represented by the caller `EKFPawn`. + * + * @return `Pawn` instance represented by the caller `EKFPawn`. + */ +public final /*unreal*/ function Pawn GetNativeInstance() +{ + if (pawnReference != none) { + return Pawn(pawnReference.Get()); + } + return none; +} + +public function Vector GetLocation() +{ + local Pawn pawnInstance; + + pawnInstance = GetNativeInstance(); + if (pawnInstance != none) { + return pawnInstance.location; + } + return Vect(0.0, 0.0, 0.0); +} + +public function int GetHealth() +{ + local Pawn pawnInstance; + + pawnInstance = GetNativeInstance(); + if (pawnInstance != none) { + return pawnInstance.health; + } + return 0; +} + +public function int GetMaxHealth() +{ + local Pawn pawnInstance; + + pawnInstance = GetNativeInstance(); + if (pawnInstance != none) { + return int(pawnInstance.healthMax); + } + return 0; +} + +public function Suicide() +{ + local Pawn pawnInstance; + + pawnInstance = GetNativeInstance(); + if (pawnInstance != none) { + pawnInstance.Suicide(); + } +} + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/Players/EPlayer.uc b/sources/Players/EPlayer.uc index 29c895d..5aee122 100644 --- a/sources/Players/EPlayer.uc +++ b/sources/Players/EPlayer.uc @@ -180,6 +180,27 @@ public final function Vector GetLocation() return Vect(0.0, 0.0, 0.0); } +/** + * If caller `EPlayer` currently owns a pawn, then this method will return + * `EPawn` interface to it. + * + * @return `EPawn` interface to pawn of the caller `EPlayer`. + * `none` if caller `EPayer` is non-existent or does not have a pawn. + */ +public final function EPawn GetPawn() +{ + local Pawn myPawn; + local PlayerController myController; + + if (controller == none) return none; + myController = PlayerController(controller.Get()); + if (myController == none) return none; + myPawn = myController.pawn; + if (myPawn == none) return none; + + return class'EKFPawn'.static.Wrap(myPawn); +} + // `PlayerReplicationInfo` associated with the caller `EPlayer`. // Can return `none` if: // 1. Caller `EPlayer` has already disconnected;