Skip to content

Commit

Permalink
Improve monster attack behaviour in Monster Defence (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
shrimpza authored Jul 13, 2022
1 parent 9e94ffc commit cb58bfb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 612 to 613
- Spanish localisation updates (thanks Neon_Knight)
- German localisation (thanks eGo)
- Improve monster's ability to find the objective in Monster Defence on smaller maps, maps with movers

## 611 to 612:
- Deaths via traps reduce the life count, rather than increasing it
- Performance optimisations for monster shadows
Expand Down
4 changes: 2 additions & 2 deletions buildscript/buildconfig.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ SCRIPTS_DIR=$(dirname $(realpath $0))

export name="Monster Hunt"
export package=MonsterHunt
export build=612
export version=612
export build=613
export version=613
export packagefull=$package
export packagedist=$package$version
export debug=1
Expand Down
89 changes: 71 additions & 18 deletions src/Classes/MonsterHuntMonsterDefenceExtension.uc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var float spawnChanceBaseScale, spawnChanceScaler;
var int minSpawnDistance;

// monster spawn interval/cycle management
var float spawnInterval, currentSpawnInterval;
var float spawnInterval;

// keeps track of players to avoid regular looping
var Pawn maybeEnemyPlayers[32];
Expand All @@ -30,11 +30,16 @@ var int PlayerCountInterval;

var Texture TeleportEffectTexture;

var float minMonsterScale;
var float miniThreshold;
var localized String miniPrefix;

function PostBeginPlay() {
local FlagBase flag;
local FlagBase bothFlags[2];
local int maxRange, range;
local NavigationPoint nav;
local Mover mover;

foreach AllActors(class'FlagBase', flag) {
if (flag.team == 0) bothFlags[0] = flag;
Expand Down Expand Up @@ -73,6 +78,14 @@ function PostBeginPlay() {

spawnChanceScaler = Max(1000, minSpawnDistance) / spawnChanceBaseScale;

// Update movers so monsters can use them
foreach AllActors(class'Mover', mover) {
if (mover.BumpType == BT_PlayerBump) mover.BumpType = BT_PawnBump;
}

// Set the monster spawn timer going
SetTimer(spawnInterval, True);

Super.PostBeginPlay();
}

Expand Down Expand Up @@ -140,16 +153,11 @@ function CoercePawn(ScriptedPawn pawn) {
}
}

function Tick(float delta) {
event Timer() {
if (game.bGameStarted) {
currentSpawnInterval += delta;
if (currentSpawnInterval >= spawnInterval) {
spawnMonsters();
currentSpawnInterval = 0;
}
spawnMonsters();
Super.Timer();
}

Super.Tick(delta);
}

function NavigationPoint findNearSpawn() {
Expand Down Expand Up @@ -252,31 +260,72 @@ function ScriptedPawn spawnMonsterAt(
// special condition to allow monsters to pass through each other, so they don't block the objective
newMonster.bBlockActors = false;

SetSpawnOrders(newMonster, monsterTarget, tag != '');

newMonster.SetMovementPhysics();
if (newMonster.Physics == PHYS_Walking) newMonster.SetPhysics(PHYS_Falling);

SetSpawnOrders(newMonster, monsterTarget, tag != '');

SpawnEffect(newMonster);
SpawnUnsticker(newMonster);

// set physics after orders, since orders navigation determination factors in physics
if (newMonster.Physics == PHYS_Walking) newMonster.SetPhysics(PHYS_Falling);

return newMonster;
}

function float ResizePawn(ScriptedPawn pawn, float scale) {
pawn.SetCollisionSize(pawn.CollisionRadius * scale, pawn.CollisionHeight * scale);
pawn.DrawScale = pawn.DrawScale * scale;
pawn.Health = pawn.Health * scale;
pawn.GroundSpeed = pawn.GroundSpeed * scale;
pawn.AirSpeed = pawn.AirSpeed * scale;

return pawn.CollisionRadius / pawn.Default.CollisionRadius;
}

function SetSpawnOrders(ScriptedPawn pawn, Actor monsterTarget, bool isRunner) {
local Pawn maybePlayer;
local bool foundPath;
local Float monsterScale;

// make them advance towards the objective
pawn.OrderObject = monsterTarget;
pawn.OrderTag = monsterTarget.Tag;

if (isRunner || FRand() > 0.7) {
pawn.AlarmTag = monsterTarget.Tag;
pawn.Orders = 'TriggerAlarm';
// when an alarm is triggered, TriggerAlarm causes AccessedNone on Enemy, so assign a random enemy
if (playerCount > 0) {
maybePlayer = maybeEnemyPlayers[Rand(playerCount)];
if (maybePlayer != None) pawn.SetEnemy(maybePlayer);
monsterScale = 1.0;

foundPath = pawn.FindBestPathToward(monsterTarget);
// there is no path to the target, try scaling down the monster to see if it can fit through doorways
while (monsterScale >= minMonsterScale && !foundPath) {
pawn.ClearPaths();
monsterScale = ResizePawn(pawn, 0.9);
foundPath = pawn.FindBestPathToward(monsterTarget);
}

if (foundPath) {
// when an alarm is triggered, TriggerAlarm causes AccessedNone on Enemy, so assign a random enemy
if (playerCount > 0) {
maybePlayer = maybeEnemyPlayers[Rand(playerCount)];
if (maybePlayer != None) pawn.SetEnemy(maybePlayer);
}

pawn.AlarmTag = monsterTarget.Tag;
pawn.Orders = 'TriggerAlarm';
} else {
// we didn't find a path to the alarm point, maybe undo the scaling, otherwise keep the mini monster for fun
if (FRand() > 0.5) {
monsterScale = 2 - monsterScale;
ResizePawn(pawn, monsterScale);
}

// at least lets go try to find a player
pawn.Orders = 'Roaming';
}

// set the mini name if the monster is small
if (monsterScale <= miniThreshold) {
pawn.MenuName = miniPrefix @ pawn.MenuName;
}
} else {
pawn.Orders = 'Roaming';
Expand Down Expand Up @@ -309,4 +358,8 @@ defaultproperties {
runnerTag="MHDRunner"

TeleportEffectTexture=Texture'Botpack.Skins.MuzzyPulse'

minMonsterScale=0.5
miniThreshold=0.7
miniPrefix="Mini"
}

0 comments on commit cb58bfb

Please sign in to comment.