silbinarywolf / sw-zombie-fortress

A VScript mod that aims to be a faithful reimplementation of the Zombie Fortress mode made originally with SourceMod
Other
0 stars 0 forks source link

add zombie horde buffs (more health regen in horde) #23

Closed silbinarywolf closed 1 year ago

silbinarywolf commented 1 year ago

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.

silbinarywolf commented 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);
}
silbinarywolf commented 1 year ago

Released in https://github.com/silbinarywolf/sw-zombie-fortress/releases/tag/v0.3.0