Prepare fixtures
This commit is contained in:
parent
797e5ea192
commit
9c94356263
6021 changed files with 722805 additions and 22 deletions
137
kf_sources/TehSpawns/Classes/ReportInteraction.uc
Normal file
137
kf_sources/TehSpawns/Classes/ReportInteraction.uc
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
class ReportInteraction extends Interaction;
|
||||
|
||||
event NotifyLevelChange()
|
||||
{
|
||||
if (master != none) {
|
||||
master.RemoveInteraction(self);
|
||||
}
|
||||
}
|
||||
|
||||
final private function KFPlayerController getController()
|
||||
{
|
||||
return KFPlayerController(viewportOwner.actor);
|
||||
}
|
||||
|
||||
exec function mySp(string s)
|
||||
{
|
||||
local bool b;
|
||||
if (s ~= "1") {
|
||||
b = true;
|
||||
}
|
||||
ShowPathNodes(b);
|
||||
ShowPaths(b);
|
||||
}
|
||||
|
||||
simulated function ShowPathNodes(bool b)
|
||||
{
|
||||
local NavigationPoint np;
|
||||
local int i, j;
|
||||
if (b)
|
||||
{
|
||||
foreach GetController().AllActors(class'NavigationPoint', np)
|
||||
{
|
||||
if (np == none)
|
||||
continue;
|
||||
np.bHidden = false;
|
||||
np.resetStaticFilterState();
|
||||
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach GetController().AllActors(class'NavigationPoint', np)
|
||||
{
|
||||
if (np == none)
|
||||
continue;
|
||||
np.bHidden = true;
|
||||
np.resetStaticFilterState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// show zed paths:
|
||||
// Orange - Flying path, narrow.
|
||||
// Light Orange - Flying path, wide.
|
||||
// Light Purple - requires high jump (higher than normal jump capability).
|
||||
// Blue - narrow path.
|
||||
// Green - normal width.
|
||||
// White - wide path.
|
||||
// Pink - very wide path.
|
||||
// Yellow - forced path.
|
||||
// Purple - "advanced" path (requires "intelligence" to be used).
|
||||
// Red - "one-way" path (i.e. path going from node A->B, but B->A is proscribed).
|
||||
final function ShowPaths(bool b)
|
||||
{
|
||||
local KFPlayerController pc;
|
||||
local NavigationPoint np;
|
||||
local array<NavigationPoint> np_array;
|
||||
local ReachSpec Spec;
|
||||
local vector SpecColor;
|
||||
local int i, j;
|
||||
local int debugLinesDrawn;
|
||||
|
||||
pc = getController();
|
||||
|
||||
if (!b)
|
||||
{
|
||||
pc.ClearStayingDebugLines();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach GetController().AllActors(class'NavigationPoint', np)
|
||||
{
|
||||
if (np == none)
|
||||
continue;
|
||||
|
||||
np_array.length = i + 1;
|
||||
np_array[i] = np;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
for (i = np_array.length - 1; i >= 0; i--)
|
||||
{
|
||||
for (j = 0; j < np_array[i].PathList.Length; j++)
|
||||
{
|
||||
Spec = np_array[i].PathList[j];
|
||||
SpecColor = vect(0, 255, 0);
|
||||
// 260 = MAXVEHICLERADIUS 80 = MINCOMMONHEIGHT
|
||||
if (( Spec.CollisionRadius >= 260 ) && (Spec.CollisionHeight >= 80))
|
||||
{
|
||||
SpecColor = vect( 255,255,255 );
|
||||
}
|
||||
// Jump spec
|
||||
else if( ( Spec.reachFlags & 8 ) == Spec.reachFlags )
|
||||
{
|
||||
SpecColor = vect( 191, 165, 99 );
|
||||
}
|
||||
// Proscribed
|
||||
else if( ( Spec.reachFlags & 128 ) == Spec.reachFlags )
|
||||
{
|
||||
SpecColor = vect( 255, 0, 0 );
|
||||
}
|
||||
// Forced
|
||||
else if( ( Spec.reachFlags & 256 ) == Spec.reachFlags )
|
||||
{
|
||||
SpecColor = vect( 255, 255, 0 );
|
||||
}
|
||||
// Blue (narrow)
|
||||
else if( ( Spec.CollisionRadius < 72 || Spec.CollisionHeight < 80 ) )
|
||||
{
|
||||
SpecColor = vect( 0, 0, 255 );
|
||||
}
|
||||
|
||||
pc.DrawStayingDebugLine(np_array[i].PathList[j].Start.Location, np_array[i].PathList[j].End.Location, SpecColor.X, SpecColor.Y, SpecColor.Z);
|
||||
debugLinesDrawn += 1;
|
||||
}
|
||||
}
|
||||
GetController().ClientMessage("Path segments amount is:" @ debugLinesDrawn);
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bVisible = true
|
||||
}
|
||||
559
kf_sources/TehSpawns/Classes/SpawnManager.uc
Normal file
559
kf_sources/TehSpawns/Classes/SpawnManager.uc
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
class SpawnManager extends Actor;
|
||||
|
||||
var private const int canBuildNodesAtOnce;
|
||||
var private const int canBuildSpawnersAtOnce;
|
||||
var public int nodesBuilt;//for building nodes only
|
||||
var public int spawnersBuilt;//for building nodes only
|
||||
|
||||
var private bool isInitializing;
|
||||
var private int initializationStage;
|
||||
var public array<ZombieVolume> cachedZombieVolumes;
|
||||
var public array<KFUseTrigger> cachedTriggers;
|
||||
var public array<KFHumanPawn> cachedPawns;
|
||||
var public array<Vector> cachedEyes;
|
||||
struct Node
|
||||
{
|
||||
var public NavigationPoint point;
|
||||
var public array<int> adjacentNodesIndicies;
|
||||
var public array<float> adjacentNodesDistances;
|
||||
var public array<int> connectedVolumesIndicies;
|
||||
var public array<KFDoorMover> connectedDoors;
|
||||
var public bool populated;
|
||||
};
|
||||
var public array<Node> allNodes;
|
||||
var public int depopulationIndex;
|
||||
var public int populatedSigIndex;
|
||||
|
||||
struct Spawner
|
||||
{
|
||||
var public ZombieVolume volume;
|
||||
var public int connectedNodeIndex;
|
||||
var public bool active;
|
||||
var public array<Vector> checkPositions;
|
||||
};
|
||||
var public array<Spawner> allSpawners;
|
||||
var public int counter;
|
||||
public function Initialize()
|
||||
{
|
||||
isInitializing = true;
|
||||
initializationStage = 0;
|
||||
Log("PHASE #1");
|
||||
StopWatch(false);
|
||||
CacheNodes();
|
||||
CacheZombieVolumes();
|
||||
CacheUseTriggers();
|
||||
StopWatch(true);
|
||||
KFGameType(level.game).bDisableZedSpawning = true;
|
||||
}
|
||||
|
||||
public function /*function*/ ReportConnectedSpawners()
|
||||
{
|
||||
local int i;
|
||||
for (i = 0; i < allNodes.length; i += 1)
|
||||
{
|
||||
Log("Node #" $ i $ " has " $ allNodes[i].connectedVolumesIndicies.length $ " conencted ZVs!");
|
||||
}
|
||||
}
|
||||
|
||||
public function Tick(float delta)
|
||||
{
|
||||
local int i;
|
||||
if (isInitializing)
|
||||
{
|
||||
HandleInitialization();
|
||||
return;
|
||||
}
|
||||
CacheKFPawns();
|
||||
//StopWatch(false);
|
||||
for (i = 0; i < cachedPawns.length; i += 1) {
|
||||
DisableVisibleZombieVolumes(cachedPawns[i]);
|
||||
}
|
||||
CacheEyes();
|
||||
DepopulateNodes();
|
||||
EnableHiddenZombieVolumes();
|
||||
//StopWatch(true);
|
||||
/*counter += 1;
|
||||
if (counter % 60 == 0) {
|
||||
LogActiveZV();
|
||||
}*/
|
||||
}
|
||||
|
||||
private function LogActiveZV()
|
||||
{
|
||||
local int i, j;
|
||||
local int scount;
|
||||
local string s;
|
||||
for (i = 0; i < allSpawners.length; i += 1)
|
||||
{
|
||||
if (allSpawners[i].active) {
|
||||
scount += 1;
|
||||
}
|
||||
else {
|
||||
Log("Disabled spawner has populated point tho:" @ allNodes[allSpawners[i].connectedNodeIndex].populated);
|
||||
Log("Also" @ allSpawners[i].volume.disabledWaveNums.length);
|
||||
Log("But" @ allSpawners[i].volume.bVolumeIsEnabled);
|
||||
}
|
||||
}
|
||||
Log("Active spawners right now:" @ scount);
|
||||
scount = 0;
|
||||
for (i = 0; i < allNodes.length; i += 1)
|
||||
{
|
||||
if (allNodes[i].populated)
|
||||
{
|
||||
scount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = "Node" @ i @ "is not populated, but:";
|
||||
for (j = 0; j < allNodes[i].adjacentNodesIndicies.length; j += 1)
|
||||
{
|
||||
s = s @ allNodes[i].adjacentNodesIndicies[j] $ ", ";
|
||||
}
|
||||
Log(s);
|
||||
}
|
||||
}
|
||||
Log("Populated nodes right now:" @ scount);
|
||||
}
|
||||
|
||||
private function DepopulateNodes()
|
||||
{
|
||||
local int i, j;
|
||||
local int nodesPerUpdate;
|
||||
local Vector testPosition;
|
||||
nodesPerUpdate = allNodes.length / 30;
|
||||
while (i < nodesPerUpdate)
|
||||
{
|
||||
testPosition = allNodes[depopulationIndex].point.location;
|
||||
for (j = 0; j < cachedEyes.length; j += 1)
|
||||
{
|
||||
if ( allNodes[depopulationIndex].populated
|
||||
&& FastTrace(testPosition, cachedEyes[j]))
|
||||
{
|
||||
allNodes[depopulationIndex].populated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
depopulationIndex += 1;
|
||||
if (depopulationIndex >= allNodes.length) {
|
||||
depopulationIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function PopulateActiveSpawnerNodes()
|
||||
{
|
||||
local int i;
|
||||
for (i = 0; i < allSpawners.length; i += 1)
|
||||
{
|
||||
if (allSpawners[i].active) {
|
||||
allSpawners[i].volume.bVolumeIsEnabled = true;
|
||||
allNodes[allSpawners[i].connectedNodeIndex].populated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function CacheEyes()
|
||||
{
|
||||
local int i;
|
||||
cachedEyes.length = 0;
|
||||
for (i = 0; i < cachedPawns.length; i += 1) {
|
||||
cachedEyes[i] = cachedPawns[i].location + cachedPawns[i].EyePosition();
|
||||
}
|
||||
}
|
||||
|
||||
private function EnableHiddenZombieVolumes()
|
||||
{
|
||||
local int i;
|
||||
local int nodesPerUpdate;
|
||||
nodesPerUpdate = allNodes.length / 29;
|
||||
while (i < nodesPerUpdate)
|
||||
{
|
||||
PropagateEnableSignal(populatedSigIndex);
|
||||
i += 1;
|
||||
populatedSigIndex += 1;
|
||||
if (populatedSigIndex >= allNodes.length)
|
||||
{
|
||||
populatedSigIndex = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (populatedSigIndex == 0 ) {
|
||||
PopulateActiveSpawnerNodes();
|
||||
}
|
||||
}
|
||||
|
||||
private function PropagateEnableSignal(int nodeIndex)
|
||||
{
|
||||
local bool canPropogate;
|
||||
local bool allDoorsLocked;
|
||||
local array<KFDoorMover> doors;
|
||||
local int i, j, otherIndex, spawnerIndex;
|
||||
local Vector testPosition;
|
||||
local array<int> adjacentIdx, spawnerIdx;
|
||||
if (!allNodes[nodeIndex].populated) {
|
||||
return;
|
||||
}
|
||||
doors = allNodes[nodeIndex].connectedDoors;
|
||||
if (doors.length > 0) {
|
||||
allDoorsLocked = true;
|
||||
}
|
||||
// TODO: might need to open doors if such spawner is used...
|
||||
for (i = 0; i < doors.length; i += 1)
|
||||
{
|
||||
if (doors[i].bDoorIsDead || !doors[i].bSealed)
|
||||
{
|
||||
allDoorsLocked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allDoorsLocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
testPosition = allNodes[nodeIndex].point.location;
|
||||
for (j = 0; j < cachedEyes.length; j += 1)
|
||||
{
|
||||
if (FastTrace(testPosition, cachedEyes[j]))
|
||||
{
|
||||
allNodes[nodeIndex].populated = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
adjacentIdx = allNodes[nodeIndex].adjacentNodesIndicies;
|
||||
for (i = 0; i < adjacentIdx.length; i += 1)
|
||||
{
|
||||
canPropogate = true;
|
||||
otherIndex = adjacentIdx[i];
|
||||
testPosition = allNodes[otherIndex].point.location;
|
||||
for (j = 0; j < cachedEyes.length; j += 1)
|
||||
{
|
||||
if (FastTrace(testPosition, cachedEyes[j]))
|
||||
{
|
||||
canPropogate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
testPosition =
|
||||
(testPosition + allNodes[nodeIndex].point.location) * 0.5;
|
||||
for (j = 0; j < cachedEyes.length; j += 1)
|
||||
{
|
||||
if (FastTrace(testPosition, cachedEyes[j]))
|
||||
{
|
||||
canPropogate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
allNodes[otherIndex].populated = true;
|
||||
spawnerIdx = allNodes[otherIndex].connectedVolumesIndicies;
|
||||
for (j = 0; j < spawnerIdx.length; j += 1)
|
||||
{
|
||||
spawnerIndex = spawnerIdx[j];
|
||||
allSpawners[spawnerIndex].active = true;
|
||||
allSpawners[spawnerIndex].volume.bVolumeIsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function DisableVisibleZombieVolumes(KFHumanPawn pawn)
|
||||
{
|
||||
local int i, j;
|
||||
local bool doDisable;
|
||||
local bool testFog;
|
||||
local float spawnZedHeight;
|
||||
local float distance, fogDistance;
|
||||
local int spawnersAmount, spawnPointsAmount;
|
||||
local Vector testPosition, pawnEyePosition;
|
||||
local array<Vector> spawnPositions;
|
||||
if (pawn == none) {
|
||||
return;
|
||||
}
|
||||
spawnZedHeight = class'ZombieFleshPoundBase'.default.collisionRadius * 1.25;
|
||||
pawnEyePosition = pawn.location + pawn.EyePosition();
|
||||
testFog = pawn.region.zone.bDistanceFog;
|
||||
fogDistance = FMax(0.0, pawn.region.zone.distanceFogEnd);
|
||||
spawnersAmount = allSpawners.length;
|
||||
for (i = 0; i < spawnersAmount; i += 1)
|
||||
{
|
||||
doDisable = false;
|
||||
spawnPositions = allSpawners[i].checkPositions;
|
||||
spawnPointsAmount = spawnPositions.length;
|
||||
for (j = 0; j < spawnPositions.length; j += 1)
|
||||
{
|
||||
testPosition = spawnPositions[j];
|
||||
if (testFog) {
|
||||
distance = VSize(testPosition - pawn.location);
|
||||
}
|
||||
if (testFog && distance >= fogDistance) continue;
|
||||
if (!FastTrace(testPosition, pawnEyePosition)) continue;
|
||||
testPosition.z += spawnZedHeight;
|
||||
if (!FastTrace(testPosition, pawnEyePosition)) continue;
|
||||
doDisable = true;
|
||||
break;
|
||||
}
|
||||
if (doDisable) {
|
||||
allSpawners[i].active = false;
|
||||
}
|
||||
allSpawners[i].volume.bVolumeIsEnabled = allSpawners[i].active;
|
||||
}
|
||||
}
|
||||
|
||||
private function HandleInitialization()
|
||||
{
|
||||
if (initializationStage == 0)
|
||||
{
|
||||
Log("PHASE #2");
|
||||
StopWatch(false);
|
||||
if (BuildNodes()) {
|
||||
initializationStage += 1;
|
||||
}
|
||||
StopWatch(true);
|
||||
}
|
||||
else if (initializationStage == 1)
|
||||
{
|
||||
Log("PHASE #3");
|
||||
StopWatch(false);
|
||||
if (BuildSpawners()) {
|
||||
initializationStage += 1;
|
||||
}
|
||||
StopWatch(true);
|
||||
}
|
||||
else if (initializationStage == 2)
|
||||
{
|
||||
Log("PHASE #4");
|
||||
StopWatch(false);
|
||||
ConnectDoors();
|
||||
StopWatch(true);
|
||||
initializationStage += 1;
|
||||
}
|
||||
else if (initializationStage == 3)
|
||||
{
|
||||
isInitializing = false;
|
||||
Log("RESULT");
|
||||
ReportConnectedSpawners();
|
||||
}
|
||||
}
|
||||
|
||||
private function CacheNodes()
|
||||
{
|
||||
local Node nextNode;
|
||||
local NavigationPoint nextPoint;
|
||||
foreach AllActors(class'NavigationPoint', nextPoint)
|
||||
{
|
||||
nextNode.point = nextPoint;
|
||||
nextNode.populated = true;
|
||||
allNodes[allNodes.length] = nextNode;
|
||||
}
|
||||
}
|
||||
|
||||
private function CacheZombieVolumes()
|
||||
{
|
||||
local ZombieVolume nextVolume;
|
||||
foreach AllActors(class'ZombieVolume', nextVolume)
|
||||
{
|
||||
if (!nextVolume.bVolumeIsEnabled) continue;
|
||||
cachedZombieVolumes[cachedZombieVolumes.length] = nextVolume;
|
||||
}
|
||||
}
|
||||
|
||||
private function CacheUseTriggers()
|
||||
{
|
||||
local KFUseTrigger nextTrigger;
|
||||
foreach AllActors(class'KFUseTrigger', nextTrigger) {
|
||||
cachedTriggers[cachedTriggers.length] = nextTrigger;
|
||||
}
|
||||
}
|
||||
|
||||
private function CacheKFPawns()
|
||||
{
|
||||
local KFHumanPawn nextPawn;
|
||||
local Controller nextController;
|
||||
nextController = level.controllerList;
|
||||
cachedPawns.length = 0;
|
||||
while (nextController != none)
|
||||
{
|
||||
nextPawn = KFHumanPawn(nextController.pawn);
|
||||
if ( nextPawn != none && nextPawn.health > 0
|
||||
&& nextController.bIsPlayer)
|
||||
{
|
||||
cachedPawns[cachedPawns.length] = nextPawn;
|
||||
}
|
||||
nextController = nextController.nextController;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private function ConnectDoors()
|
||||
{
|
||||
local int i, j, k;
|
||||
local KFUseTrigger nextTrigger;
|
||||
local int nodesAmount, triggersAmount;
|
||||
local array<KFDoorMover> nextDoors;
|
||||
nodesAmount = allNodes.length;
|
||||
nextDoors[0] = none;
|
||||
Log("CHECKING DOORS:" @ cachedTriggers.length);
|
||||
for (i = 0; i < nodesAmount; i += 1)
|
||||
{
|
||||
nextDoors.length = 0;
|
||||
triggersAmount = cachedTriggers.length;
|
||||
for (j = 0; j < triggersAmount; j += 1)
|
||||
{
|
||||
nextTrigger = cachedTriggers[j];
|
||||
for (k = 0; k < nextTrigger.doorOwners.length; k += 1)
|
||||
{
|
||||
if (allNodes[i].point == nextTrigger.doorOwners[k].doorPathNode)
|
||||
{
|
||||
nextDoors[nextDoors.length] = nextTrigger.doorOwners[k];
|
||||
Log("!FOUND AND ADDED!");
|
||||
}
|
||||
}
|
||||
}
|
||||
allNodes[i].connectedDoors = nextDoors;
|
||||
Log("Node" @ i @ "has" @ allNodes[i].connectedDoors.length @ "doors!");
|
||||
}
|
||||
}
|
||||
|
||||
private function bool BuildNodes()
|
||||
{
|
||||
local int nodesDoneThisCall;
|
||||
local int i, j;
|
||||
local int nodesAmount, specsAmount;
|
||||
local NavigationPoint nextPoint;
|
||||
local array<ReachSpec> nextSpecs;
|
||||
local array<int> nextIndicies;
|
||||
local array<float> nextDistances;
|
||||
nodesAmount = allNodes.length;
|
||||
// To avoid possible crash on `.length = 0` in the loop
|
||||
nextIndicies[0] = -1;
|
||||
nextDistances[0] = 0;
|
||||
for (i = nodesBuilt; i < nodesAmount; i += 1)
|
||||
{
|
||||
nextIndicies.length = 0;
|
||||
nextDistances.length = 0;
|
||||
nextPoint = allNodes[i].point;
|
||||
nextSpecs = nextPoint.pathList;
|
||||
specsAmount = nextSpecs.length;
|
||||
for (j = 0; j < specsAmount; j += 1)
|
||||
{
|
||||
if (nextPoint == nextSpecs[j].start){
|
||||
nextIndicies[j] = FindNodeIndex(nextSpecs[j].end);
|
||||
}
|
||||
else {
|
||||
nextIndicies[j] = FindNodeIndex(nextSpecs[j].start);
|
||||
}
|
||||
nextDistances[j] =
|
||||
VSize(nextSpecs[j].start.location - nextSpecs[j].end.location);
|
||||
}
|
||||
allNodes[i].adjacentNodesIndicies = nextIndicies;
|
||||
allNodes[i].adjacentNodesDistances = nextDistances;
|
||||
// Done too much, bail
|
||||
nodesDoneThisCall += 1;
|
||||
if (nodesDoneThisCall >= canBuildNodesAtOnce)
|
||||
{
|
||||
nodesBuilt = i + 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function int FindNodeIndex(NavigationPoint point)
|
||||
{
|
||||
local int i;
|
||||
local int nodesAmount;
|
||||
nodesAmount = allNodes.length;
|
||||
for (i = 0; i < nodesAmount; i += 1)
|
||||
{
|
||||
if (allNodes[i].point == point) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private function bool BuildSpawners()
|
||||
{
|
||||
local int i, j;
|
||||
local int spawnersDoneThisCall;
|
||||
local int volumesAmount, pointsAmount;
|
||||
local int selectedNodeIndex;
|
||||
local float boxMinX, boxMaxX, boxMinY, boxMaxY, boxZ;
|
||||
local float nextDistance, minDistance;
|
||||
local Spawner nextSpawner;
|
||||
local ZombieVolume nextVolume;
|
||||
local NavigationPoint nextPoint;
|
||||
local array<Vector> spawnPositions, checkPositions;
|
||||
local array<int> volumesCopy;
|
||||
volumesAmount = cachedZombieVolumes.length;
|
||||
pointsAmount = allNodes.length;
|
||||
for (i = 0; spawnersBuilt < volumesAmount; spawnersBuilt += 1)
|
||||
{
|
||||
nextVolume = cachedZombieVolumes[spawnersBuilt];
|
||||
selectedNodeIndex = -1;
|
||||
for (j = 0; j < pointsAmount; j += 1)
|
||||
{
|
||||
nextPoint = allNodes[j].point;
|
||||
if (!FastTrace(nextPoint.location, nextVolume.location)) {
|
||||
continue;
|
||||
}
|
||||
nextDistance = VSize(nextVolume.location - nextPoint.location);
|
||||
if (selectedNodeIndex < 0 || nextDistance < minDistance)
|
||||
{
|
||||
minDistance = nextDistance;
|
||||
selectedNodeIndex = j;
|
||||
}
|
||||
}
|
||||
if (selectedNodeIndex >= 0)
|
||||
{
|
||||
nextSpawner.volume = nextVolume;
|
||||
nextSpawner.connectedNodeIndex = selectedNodeIndex;
|
||||
nextSpawner.active = true;
|
||||
volumesCopy = allNodes[selectedNodeIndex].connectedVolumesIndicies;
|
||||
volumesCopy[volumesCopy.length] = allSpawners.length;
|
||||
allNodes[selectedNodeIndex].connectedVolumesIndicies = volumesCopy;
|
||||
spawnPositions = nextVolume.spawnPos;
|
||||
boxMinX = spawnPositions[0].x;
|
||||
boxMaxX = spawnPositions[0].x;
|
||||
boxMinY = spawnPositions[0].y;
|
||||
boxMaxY = spawnPositions[0].y;
|
||||
boxZ = spawnPositions[0].z;
|
||||
for (i = 1; i < spawnPositions.length; i += 1)
|
||||
{
|
||||
boxMinX = FMin(boxMinX, spawnPositions[i].x);
|
||||
boxMaxX = FMax(boxMaxX, spawnPositions[i].x);
|
||||
boxMinY = FMin(boxMinY, spawnPositions[i].y);
|
||||
boxMaxY = FMax(boxMaxY, spawnPositions[i].y);
|
||||
}
|
||||
checkPositions[0] = GetVect(boxMinX, boxMinY, boxZ);
|
||||
checkPositions[1] = GetVect(boxMinX, boxMaxY, boxZ);
|
||||
checkPositions[2] = GetVect(boxMaxX, boxMinY, boxZ);
|
||||
checkPositions[3] = GetVect(boxMaxX, boxMaxY, boxZ);
|
||||
checkPositions[4] = nextVolume.location;
|
||||
nextSpawner.checkPositions = checkPositions;
|
||||
allSpawners[allSpawners.length] = nextSpawner;
|
||||
}
|
||||
spawnersDoneThisCall += 1;
|
||||
if (spawnersDoneThisCall >= canBuildSpawnersAtOnce) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function Vector GetVect(float x, float y, float z)
|
||||
{
|
||||
local Vector result;
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
result.z = z;
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: what is ZVs are so huge 5 points is not enough?
|
||||
defaultproperties
|
||||
{
|
||||
canBuildNodesAtOnce = 100
|
||||
canBuildSpawnersAtOnce = 100
|
||||
}
|
||||
135
kf_sources/TehSpawns/Classes/TehSpawnsMut.uc
Normal file
135
kf_sources/TehSpawns/Classes/TehSpawnsMut.uc
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
class TehSpawnsMut extends Mutator;
|
||||
|
||||
var bool interactionAdded;
|
||||
|
||||
function Mutate(string mutateString, PlayerController player)
|
||||
{
|
||||
local SpawnManager manager;
|
||||
if (mutateString ~= "pathinfo") {
|
||||
ShowMeInfo(player);
|
||||
}
|
||||
if (mutateString ~= "doit")
|
||||
{
|
||||
manager = Spawn(class'SpawnManager');
|
||||
manager.Initialize();
|
||||
}
|
||||
if (mutateString ~= "predoit") {
|
||||
DoIt(player, false);
|
||||
}
|
||||
if (mutateString ~= "predoit2") {
|
||||
DoIt(player, true);
|
||||
}
|
||||
if (mutateString ~= "check") {
|
||||
CheckSin(player);
|
||||
}
|
||||
if (nextMutator != none) {
|
||||
nextMutator.Mutate(mutateString, player);
|
||||
}
|
||||
}
|
||||
|
||||
function ShowMeInfo(PlayerController player)
|
||||
{
|
||||
local int nodeCount, volumeCount;
|
||||
local ZombieVolume nextVolume;
|
||||
local NavigationPoint nextNode;
|
||||
StopWatch(false);
|
||||
foreach AllActors(class'NavigationPoint', nextNode) {
|
||||
nodeCount += 1;
|
||||
}
|
||||
StopWatch(true);
|
||||
StopWatch(false);
|
||||
foreach AllActors(class'ZombieVolume', nextVolume) {
|
||||
volumeCount += 1;
|
||||
}
|
||||
StopWatch(true);
|
||||
player.ClientMessage("Path nodes count:" @ nodeCount);
|
||||
player.ClientMessage("`ZomvieVolume`s count:" @ volumeCount);
|
||||
}
|
||||
|
||||
function CheckSin(PlayerController player)
|
||||
{
|
||||
local int i;
|
||||
StopWatch(false);
|
||||
for (i = 0; i < 1000; i += 1) {
|
||||
sin(float(i));
|
||||
}
|
||||
StopWatch(true);
|
||||
}
|
||||
|
||||
function doit(PlayerController player, bool nav)
|
||||
{
|
||||
local int iter;
|
||||
local int totalZV, fullZV;
|
||||
local float perc;
|
||||
local float distance, maxDistance;
|
||||
local NavigationPoint nextPoint, furthestPoint, selectedPoint;
|
||||
local ZombieVolume nextVolume, isolatedVolume;
|
||||
maxDistance = -1;
|
||||
StopWatch(false);
|
||||
foreach AllActors(class'ZombieVolume', nextVolume)
|
||||
{
|
||||
distance = 1000000;
|
||||
selectedPoint = none;
|
||||
foreach AllActors(class'NavigationPoint', nextPoint)
|
||||
{
|
||||
iter += 1;
|
||||
if (VSize(nextPoint.location - nextVolume.location) < distance)
|
||||
{
|
||||
if (!FastTrace(nextPoint.location, nextVolume.location)) {
|
||||
continue;
|
||||
}
|
||||
distance = VSize(nextPoint.location - nextVolume.location);
|
||||
selectedPoint = nextPoint;
|
||||
}
|
||||
}
|
||||
totalZV += 1;
|
||||
if (selectedPoint != none && nextVolume.Encompasses(selectedPoint)) {
|
||||
fullZV += 1;
|
||||
}
|
||||
//Log("Min distance:" @ distance);
|
||||
if (maxDistance < distance && selectedPoint != none)
|
||||
{
|
||||
maxDistance = distance;
|
||||
isolatedVolume = nextVolume;
|
||||
furthestPoint = selectedPoint;
|
||||
}
|
||||
}
|
||||
StopWatch(true);
|
||||
perc = (float(fullZV) / float(totalZV)) * 100;
|
||||
player.ClientMessage("Max ditance is:" @ maxDistance);
|
||||
player.ClientMessage("Iterations done:" @ iter);
|
||||
player.ClientMessage("Full volume percentage:" @ perc);
|
||||
if (nav) {
|
||||
player.SetLocation(furthestPoint.location);
|
||||
}
|
||||
else {
|
||||
player.SetLocation(isolatedVolume.location);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Tick(float delta)
|
||||
{
|
||||
local ReportInteraction myInteraction;
|
||||
local Player localPlayer;
|
||||
if (role == Role_AUTHORITY) return;
|
||||
if (interactionAdded) return;
|
||||
localPlayer = level.GetLocalPlayerController().player;
|
||||
if (localPlayer == none) return;
|
||||
|
||||
myInteraction = ReportInteraction(localPlayer.interactionMaster
|
||||
.AddInteraction("TehSpawns.ReportInteraction", localPlayer));
|
||||
if (myInteraction != none) {
|
||||
interactionAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// Mutator description
|
||||
GroupName = "Test mutators"
|
||||
FriendlyName = "Zed spawner mutator"
|
||||
Description = "Mutator that provides clients with information about how many zeds (and their spawn rate) are present on the map."
|
||||
bAddToServerPackages = true
|
||||
bAlwaysRelevant = true
|
||||
RemoteRole = ROLE_SimulatedProxy
|
||||
}
|
||||
9
kf_sources/TehSpawns/Classes/index.html
Normal file
9
kf_sources/TehSpawns/Classes/index.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head><title>Index of /kf_sources/TehSpawns/Classes/</title></head>
|
||||
<body>
|
||||
<h1>Index of /kf_sources/TehSpawns/Classes/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="ReportInteraction.uc">ReportInteraction.uc</a> 18-Jan-2022 20:46 3201
|
||||
<a href="SpawnManager.uc">SpawnManager.uc</a> 20-Jan-2022 20:48 17485
|
||||
<a href="TehSpawnsMut.uc">TehSpawnsMut.uc</a> 19-Jan-2022 19:01 4143
|
||||
</pre><hr></body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue