Anton Tarasenko
2 years ago
9 changed files with 861 additions and 524 deletions
@ -1,202 +0,0 @@
|
||||
/** |
||||
* Implementation of `EPlaceable` 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 <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EKFPlaceable extends EPlaceable |
||||
abstract; |
||||
|
||||
var private NativeActorRef actorReference; |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
_.memory.Free(actorReference); |
||||
actorReference = none; |
||||
} |
||||
|
||||
/** |
||||
* Creates new `EKFPlaceable` that refers to the `actorInstance` pawn. |
||||
* |
||||
* @param actorInstance Native actor class that new `EKFPlaceable` will |
||||
* represent. |
||||
* @return New `EKFPlaceable` that represents given `actorInstance`. |
||||
*/ |
||||
public final static /*unreal*/ function EKFPlaceable Wrap(Actor actorInstance) |
||||
{ |
||||
local EKFPlaceable newReference; |
||||
|
||||
if (actorInstance == none) { |
||||
return none; |
||||
} |
||||
newReference = EKFPlaceable(__().memory.Allocate(class'EKFPlaceable')); |
||||
newReference.actorReference = __server().unreal.ActorRef(actorInstance); |
||||
return newReference; |
||||
} |
||||
|
||||
public function EInterface Copy() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
return Wrap(actorInstance); |
||||
} |
||||
|
||||
public function bool Supports(class<EInterface> newInterfaceClass) |
||||
{ |
||||
if (newInterfaceClass == none) return false; |
||||
if (newInterfaceClass == class'EPlaceable') return true; |
||||
if (newInterfaceClass == class'EKFPlaceable') return true; |
||||
|
||||
if (newInterfaceClass == class'EKFPawn') { |
||||
return (Pawn(GetNativeInstance()) != none); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function EInterface As(class<EInterface> newInterfaceClass) |
||||
{ |
||||
local Pawn pawnInstance; |
||||
|
||||
if (!IsExistent()) { |
||||
return none; |
||||
} |
||||
if ( newInterfaceClass == class'EPlaceable' |
||||
|| newInterfaceClass == class'EKFPlaceable') |
||||
{ |
||||
return Copy(); |
||||
} |
||||
if ( newInterfaceClass == class'EPawn' |
||||
|| newInterfaceClass == class'EKFPawn') |
||||
{ |
||||
pawnInstance = Pawn(GetNativeInstance()); |
||||
if (pawnInstance != none) { |
||||
return class'EKFPawn'.static.Wrap(pawnInstance); |
||||
} |
||||
} |
||||
return none; |
||||
} |
||||
|
||||
public function bool IsExistent() |
||||
{ |
||||
return (GetNativeInstance() != none); |
||||
} |
||||
|
||||
public function bool SameAs(EInterface other) |
||||
{ |
||||
local EKFPlaceable otherPlaceable; |
||||
|
||||
otherPlaceable = EKFPlaceable(other); |
||||
if (otherPlaceable == none) { |
||||
return false; |
||||
} |
||||
return (GetNativeInstance() == otherPlaceable.GetNativeInstance()); |
||||
} |
||||
|
||||
/** |
||||
* Returns `Pawn` instance represented by the caller `EKFPlaceable`. |
||||
* |
||||
* @return `Pawn` instance represented by the caller `EKFPlaceable`. |
||||
*/ |
||||
public final /*unreal*/ function Actor GetNativeInstance() |
||||
{ |
||||
if (actorReference != none) { |
||||
return actorReference.Get(); |
||||
} |
||||
return none; |
||||
} |
||||
|
||||
public function Vector GetLocation() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return actorInstance.location; |
||||
} |
||||
return Vect(0.0, 0.0, 0.0); |
||||
} |
||||
|
||||
public function Rotator GetRotation() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return actorInstance.rotation; |
||||
} |
||||
return Rot(0.0, 0.0, 0.0); |
||||
} |
||||
|
||||
public function bool IsStatic() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return actorInstance.bStatic; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function bool IsColliding() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return actorInstance.bCollideActors; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function bool IsBlocking() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return actorInstance.bBlockActors; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function SetBlocking(bool newBlocking) |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
actorInstance.bBlockActors = newBlocking; |
||||
} |
||||
} |
||||
|
||||
public function bool IsVisible() |
||||
{ |
||||
local Actor actorInstance; |
||||
|
||||
actorInstance = GetNativeInstance(); |
||||
if (actorInstance != none) { |
||||
return (!actorInstance.bHidden && actorInstance.drawType != DT_None); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -1,184 +0,0 @@
|
||||
/** |
||||
* `EntityIterator` implementation for `KF1_Frontend`. |
||||
* 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 <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class KF1_EntityIterator extends EntityIterator; |
||||
|
||||
var private bool initialized; |
||||
|
||||
var private int currentIndex; |
||||
// Simply store all traced `Actor`s here at the moment of user first |
||||
// interacting with iterator's items: when either `Next()` or one of |
||||
// the `Get...()` methods were called. |
||||
var private array<EPlaceable> foundActors; |
||||
// Did we already perform iteration through actors? |
||||
var private bool iterated; |
||||
|
||||
// Iterator filters |
||||
var private bool onlyPawns; |
||||
var private bool onlyPlaceables; |
||||
var private bool onlyVisible; |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
_.memory.FreeMany(foundActors); |
||||
foundActors.length = 0; |
||||
initialized = false; |
||||
} |
||||
|
||||
/** |
||||
* Initializes `TracingIterator` that traces entities between `start` and |
||||
* `end` positions, in order starting from the `start` |
||||
*/ |
||||
public final function Initialize() |
||||
{ |
||||
initialized = true; |
||||
} |
||||
|
||||
private final function bool IsActorVisible(Actor actorToCheck) |
||||
{ |
||||
if (actorToCheck == none) return false; |
||||
if (actorToCheck.bHidden && !actorToCheck.bWorldGeometry) return false; |
||||
if (actorToCheck.drawType == DT_None) return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
// Does actual tracing, but only once per iterator's lifecycle. |
||||
// Assumes `initialized` is `true`. |
||||
private final function TryIterating() |
||||
{ |
||||
local Pawn nextPawn; |
||||
local Actor nextActor; |
||||
local class<Actor> targetClass; |
||||
local ServerLevelCore core; |
||||
|
||||
// Checking `initialized` flag is already done by every method that |
||||
// calls `TryTracing()` |
||||
if (iterated) { |
||||
return; |
||||
} |
||||
currentIndex = 0; |
||||
if (onlyPawns) { |
||||
targetClass = class'Pawn'; |
||||
} |
||||
else { |
||||
targetClass = class'Actor'; |
||||
} |
||||
core = ServerLevelCore(class'ServerLevelCore'.static.GetInstance()); |
||||
// TODO: We should not always use slow `AllActors()` method |
||||
foreach core.AllActors(targetClass, nextActor) |
||||
{ |
||||
if (onlyVisible && !IsActorVisible(nextActor)) { |
||||
continue; |
||||
} |
||||
nextPawn = Pawn(nextActor); |
||||
if (nextPawn != none) |
||||
{ |
||||
foundActors[foundActors.length] = |
||||
class'EKFPawn'.static.Wrap(nextPawn); |
||||
} |
||||
else { |
||||
foundActors[foundActors.length] = |
||||
class'EKFUnknownPlaceable'.static.Wrap(nextActor); |
||||
} |
||||
} |
||||
iterated = true; |
||||
} |
||||
|
||||
public function Iter Next() |
||||
{ |
||||
if (!initialized) { |
||||
return self; |
||||
} |
||||
TryIterating(); |
||||
currentIndex += 1; |
||||
return self; |
||||
} |
||||
|
||||
public function AcediaObject Get() |
||||
{ |
||||
if (!initialized) { |
||||
return none; |
||||
} |
||||
TryIterating(); |
||||
if (HasFinished()) { |
||||
return none; |
||||
} |
||||
return foundActors[currentIndex].NewRef(); |
||||
} |
||||
|
||||
public function EPlaceable GetPlaceable() |
||||
{ |
||||
// We only create `EPlaceable` child classes in this class |
||||
return EPlaceable(Get()); |
||||
} |
||||
|
||||
public function EPawn GetPawn() |
||||
{ |
||||
local AcediaObject result; |
||||
local EPawn pawnResult; |
||||
|
||||
if (!initialized) { |
||||
return none; |
||||
} |
||||
result = Get(); |
||||
pawnResult = EPawn(result); |
||||
if (pawnResult == none) { |
||||
_.memory.Free(result); |
||||
} |
||||
return pawnResult; |
||||
} |
||||
|
||||
public function bool HasFinished() |
||||
{ |
||||
TryIterating(); |
||||
return (currentIndex >= foundActors.length); |
||||
} |
||||
|
||||
public function Iter LeaveOnlyNotNone() |
||||
{ |
||||
// We cannot tracer `none` actors, so no need to do anything |
||||
return self; |
||||
} |
||||
|
||||
public function EntityIterator LeaveOnlyPawns() |
||||
{ |
||||
if (initialized && !iterated) { |
||||
onlyPawns = true; |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
public function EntityIterator LeaveOnlyPlaceables() { |
||||
// Doesn't do anything for now |
||||
// TODO: make it actually do something |
||||
return self; |
||||
} |
||||
|
||||
public function EntityIterator LeaveOnlyVisible() |
||||
{ |
||||
if (initialized && !iterated) { |
||||
onlyVisible = true; |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
Loading…
Reference in new issue