Closed silbinarywolf closed 1 year ago
This will land in v0.3.0.
Solution is as follows and translated pretty much as-is from Zombie Fortress
::HandleZombieHordeBonusOnTick <- function(zombieList) {
if (zombieList.len() == 0) {
return;
}
local hordeStack = [];
local playerHordeIndex = {};
local hordeSizeList = [];
for (local i = 0; i < zombieList.len(); i++) {
// 2a. Create new horde group.
// If player is not in horde, create one and add them to it
{
local player = zombieList[i];
if (!(player in playerHordeIndex)) {
hordeSizeList.push(1);
playerHordeIndex[player] <- hordeSizeList.len()-1;
hordeStack.push(player);
}
}
// 2b. Build current horde created in step 2a.
// Use a depth-first adjacency search.
while (hordeStack.len() > 0) {
local player = hordeStack.pop();
for(local j = i+1; j < zombieList.len(); j++) {
local otherPlayer = zombieList[j];
if (otherPlayer in playerHordeIndex) {
// If player is already assigned to a hoard, do nothing
continue;
}
local deltaVector = player.GetOrigin() - otherPlayer.GetOrigin(); // GetOrigin == GetAbsOrigin
local distance = deltaVector.Norm();
// printl("Distance - " + distance);
if (distance <= 1000) {
// Add match to our horde
local currHordeIndex = hordeSizeList.len()-1;
playerHordeIndex[otherPlayer] <- currHordeIndex;
hordeSizeList[currHordeIndex] += 1;
// Next, let's see who *they* match with on the same horde
hordeStack.push(otherPlayer);
}
}
}
}
// DEBUG: Check if hording works as expected
//for (local i = 0; i < hordeSizeList.len(); i++) {
// printl("Horde["+i+"]:" + hordeSizeList[i]);
//}
// 3. Set horde bonuses.
for (local i = 0; i < zombieList.len(); i++) {
local player = zombieList[i];
if (player in playerHordeIndex) {
// If part of horde, apply bonus
local hordeIndex = playerHordeIndex[player];
local zombieCountInHorde = hordeSizeList[hordeIndex];
zf_hordeBonus[player] <- zombieCountInHorde - 1;
} else {
// If not part of horde, remove bonus
zf_hordeBonus[player] <- 0;
}
}
}
// runs on team_round_timer entity
//
// equivalent to timer_main from zombiefortress_vanilla
::TickEverySecond <- function() {
local zombieList = [];
for (local i = 1; i <= Constants.Server.MAX_PLAYERS; i++) {
local player = PlayerInstanceFromIndex(i)
if (player == null || !player.IsValid()) {
continue;
}
local team = player.GetTeam();
switch (team) {
case zombieTeamNumber:
zombieList.push(player);
break;
}
}
// Handle zombie horde bonuses
HandleZombieHordeBonusOnTick(zombieList);
}
In the original mod, if Zombies stuck close together they got health buffs and crit buffs. As part of this issue, we'll just handle health as crits are tougher to work out.