diff --git a/CHANGELOG.md b/CHANGELOG.md
index b85338e..0b4a560 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,12 @@
-# Changelog
+# Changelog
+
+## 607 to 608:
+- Re-worked and improved MH-NaliVillage]\[ map, included as MH-NaliVillage][-SE
+- Include monster difficulty in scoreboard footer message
+- Show objectives on scoreboard
+- Reduce volume of objective activated/completed sounds
+- Only include unfriendly creatures in monsters remaining count
+- Tweak levers/waypoints in MH-NaliVillage]\[ map to prevent double-triggering by AI
## 606 to 607:
- Introduction of support for optional objectives in maps, which can show up on the HUD, and tell players what they need to be doing
diff --git a/buildscript/buildconfig.sh b/buildscript/buildconfig.sh
index 059034f..e131fa5 100644
--- a/buildscript/buildconfig.sh
+++ b/buildscript/buildconfig.sh
@@ -7,8 +7,8 @@ SCRIPTS_DIR=$(dirname $(realpath $0))
export name="Monster Hunt"
export package=MonsterHunt
-export build=607
-export version=607
+export build=608
+export version=608
export packagefull=$package
export packagedist=$package$version
export debug=1
diff --git a/resources/Help/MonsterHunt/ReadMe.html b/resources/Help/MonsterHunt/ReadMe.html
index 722049a..dbabe1a 100644
--- a/resources/Help/MonsterHunt/ReadMe.html
+++ b/resources/Help/MonsterHunt/ReadMe.html
@@ -306,6 +306,16 @@
Credits
Release History
+ Release 14 (608)
+
+ - Re-worked and improved MH-NaliVillage]\[ map, included as MH-NaliVillage][-SE
+
- Include monster difficulty in scoreboard footer message
+
- Show objectives on scoreboard
+
- Reduce volume of objective activated/completed sounds
+
- Only include unfriendly creatures in monsters remaining count
+
- Tweak levers/waypoints in MH-NaliVillage]\[ map to prevent double-triggering by AI
+
+
Release 13 (607)
- Introduction of support for optional objectives in maps, which can show up on the HUD, and tell players what they need to be doing
diff --git a/resources/Maps/MH-NaliVillage][-SE.unr b/resources/Maps/MH-NaliVillage][-SE.unr
new file mode 100644
index 0000000..f7a2da6
Binary files /dev/null and b/resources/Maps/MH-NaliVillage][-SE.unr differ
diff --git a/resources/Maps/MH-NaliVillage][.unr b/resources/Maps/MH-NaliVillage][.unr
index 2ddd30d..f4d649c 100644
Binary files a/resources/Maps/MH-NaliVillage][.unr and b/resources/Maps/MH-NaliVillage][.unr differ
diff --git a/src/Classes/MonsterBoard.uc b/src/Classes/MonsterBoard.uc
index 27e391f..637cf6b 100644
--- a/src/Classes/MonsterBoard.uc
+++ b/src/Classes/MonsterBoard.uc
@@ -10,6 +10,7 @@
class MonsterBoard extends TournamentScoreBoard;
var color LightGreenColor, DarkGreenColor;
+var localized String MonsterDifficultyJoinString, ObjectivesString;
function DrawHeader(canvas Canvas) {
local GameReplicationInfo GRI;
@@ -57,39 +58,50 @@ function DrawTrailer(canvas Canvas) {
local int Hours, Minutes, Seconds;
local float XL, YL;
local PlayerPawn PlayerOwner;
- local string TitleQuote;
+ local GameReplicationInfo GRI;
+ local string TitleQuote, DifficultyQuote;
Canvas.bCenter = true;
Canvas.StrLen("Test", XL, YL);
Canvas.DrawColor = LightGreenColor;
- PlayerOwner = PlayerPawn(Owner);
Canvas.SetPos(0, Canvas.ClipY - 2 * YL);
- if ((Level.NetMode == NM_Standalone) && Level.Game.IsA('DeathMatchPlus')) {
- TitleQuote = PlayerOwner.GameReplicationInfo.GameName @ MapTitle @ MapTitleQuote $ Level.Title $ MapTitleQuote;
- if (DeathMatchPlus(Level.Game).bRatedGame) {
- Canvas.DrawText(DeathMatchPlus(Level.Game).RatedGameLadderObj.SkillText @ TitleQuote, true);
- } else if (DeathMatchPlus(Level.Game).bNoviceMode) {
- Canvas.DrawText(class'ChallengeBotInfo'.default.Skills[Level.Game.Difficulty] @ TitleQuote, true);
+ PlayerOwner = PlayerPawn(Owner);
+ GRI = PlayerPawn(Owner).GameReplicationInfo;
+
+ if (Level.Game.IsA('MonsterHunt') && GRI.IsA('MonsterReplicationInfo')) {
+ DifficultyQuote = class'MonsterHuntRules'.default.Skills[
+ class'MonsterHuntRules'.static.TranslateMonsterSkillIndex(MonsterReplicationInfo(GRI).MonsterSkill)
+ ] @ MonsterDifficultyJoinString;
+ } else {
+ DifficultyQuote = "";
+ }
+
+ if ((Level.NetMode == NM_Standalone) && Level.Game.IsA('MonsterHunt')) {
+ TitleQuote = GRI.GameName @ MapTitle @ MapTitleQuote $ Level.Title $ MapTitleQuote;
+ if (DeathMatchPlus(Level.Game).bNoviceMode) {
+ TitleQuote = class'ChallengeBotInfo'.default.Skills[Level.Game.Difficulty] @ TitleQuote;
} else {
- Canvas.DrawText(class'ChallengeBotInfo'.default.Skills[Level.Game.Difficulty + 4] @ TitleQuote, true);
+ TitleQuote = class'ChallengeBotInfo'.default.Skills[Level.Game.Difficulty + 4] @ TitleQuote;
}
} else {
- Canvas.DrawText(PlayerOwner.GameReplicationInfo.GameName @ MapTitle @ Level.Title, true);
+ TitleQuote = GRI.GameName @ MapTitle @ Level.Title;
}
+ Canvas.DrawText(DifficultyQuote @ TitleQuote, true);
+
Canvas.SetPos(0, Canvas.ClipY - YL);
- if (bTimeDown || (PlayerOwner.GameReplicationInfo.RemainingTime > 0)) {
+ if (bTimeDown || (GRI.RemainingTime > 0)) {
bTimeDown = true;
- if (PlayerOwner.GameReplicationInfo.RemainingTime <= 0) {
+ if (GRI.RemainingTime <= 0) {
Canvas.DrawText(RemainingTime @ "00:00", true);
} else {
- Minutes = PlayerOwner.GameReplicationInfo.RemainingTime / 60;
- Seconds = PlayerOwner.GameReplicationInfo.RemainingTime % 60;
+ Minutes = GRI.RemainingTime / 60;
+ Seconds = GRI.RemainingTime % 60;
Canvas.DrawText(RemainingTime @ TwoDigitString(Minutes) $ ":" $ TwoDigitString(Seconds), true);
}
} else {
- Seconds = PlayerOwner.GameReplicationInfo.ElapsedTime;
+ Seconds = GRI.ElapsedTime;
Minutes = Seconds / 60;
Hours = Minutes / 60;
Seconds = Seconds - (Minutes * 60);
@@ -97,7 +109,7 @@ function DrawTrailer(canvas Canvas) {
Canvas.DrawText(ElapsedTime @ TwoDigitString(Hours) $ ":" $ TwoDigitString(Minutes) $ ":" $ TwoDigitString(Seconds), true);
}
- if (PlayerOwner.GameReplicationInfo.GameEndedComments != "") {
+ if (GRI.GameEndedComments != "") {
Canvas.bCenter = true;
Canvas.StrLen("Test", XL, YL);
Canvas.SetPos(0, Canvas.ClipY - Min(YL * 6, Canvas.ClipY * 0.1));
@@ -112,6 +124,8 @@ function DrawTrailer(canvas Canvas) {
Canvas.DrawText(Restart, true);
}
Canvas.bCenter = false;
+
+ DrawObjectivesList(Canvas);
}
function DrawCategoryHeaders(Canvas Canvas) {
@@ -196,96 +210,65 @@ function DrawNameAndPing(Canvas Canvas, PlayerReplicationInfo PRI, float XOffset
}
}
-function SortScores(int N) {
- local int I, J, Max;
- local PlayerReplicationInfo TempPRI;
-
- for (I = 0; I < N - 1; I++) {
- Max = I;
- for (J = I + 1; J < N; J++) {
- if (Ordered[J].Score > Ordered[Max].Score) {
- Max = J;
- } else if ((Ordered[J].Score == Ordered[Max].Score) && (Ordered[J].Deaths < Ordered[Max].Deaths)) {
- Max = J;
- } else if ((Ordered[J].Score == Ordered[Max].Score) && (Ordered[J].Deaths == Ordered[Max].Deaths)
- && (Ordered[J].PlayerID < Ordered[Max].Score)) {
- Max = J;
- }
- }
+function DrawObjectivesList(Canvas Canvas) {
+ local float XL, YL, YOffset, XOffset;
+ local int i;
+ local MonsterReplicationInfo mri;
+ local MonsterHuntObjective obj;
+ local bool wasObjectives;
- TempPRI = Ordered[Max];
- Ordered[Max] = Ordered[I];
- Ordered[I] = TempPRI;
- }
-}
+ if (PlayerPawn(Owner) == None) return;
-function ShowScores(canvas Canvas) {
- local PlayerReplicationInfo PRI;
- local int PlayerCount, i;
- local float XL, YL;
- local float YOffset, YStart;
- local font CanvasFont;
+ mri = MonsterReplicationInfo(PlayerPawn(Owner).GameReplicationInfo);
- Canvas.Style = ERenderStyle.STY_Normal;
+ if (mri == None) return;
- // Header
- Canvas.SetPos(0, 0);
- DrawHeader(Canvas);
+ Canvas.Font = MyFonts.GetBigFont(Canvas.ClipX);
+ Canvas.StrLen("Test", XL, YL);
- // Wipe everything.
- for (i = 0; i < ArrayCount(Ordered); i++) Ordered[i] = None;
- for (i = 0; i < 32; i++) {
- if (PlayerPawn(Owner).GameReplicationInfo.PRIArray[i] != None) {
- PRI = PlayerPawn(Owner).GameReplicationInfo.PRIArray[i];
- if (!PRI.bIsSpectator || PRI.bWaitingPlayer) {
- Ordered[PlayerCount] = PRI;
- PlayerCount++;
+ YOffset = Canvas.ClipY - (YL * 6);
+ XOffset = Canvas.ClipX * 0.1875; // in line with names list
- if (PlayerCount == ArrayCount(Ordered)) break;
- }
+ for (i = 15; i >= 0; i--) { // rendering bottom-up
+ obj = mri.objectives[i];
+ if (obj == None) continue;
+ if (!obj.bActive && !obj.bAlwaysShown) {
+ if (!obj.bCompleted || (obj.bCompleted && !obj.bShowWhenComplete)) continue;
}
- }
- SortScores(PlayerCount);
-
- CanvasFont = Canvas.Font;
- Canvas.Font = MyFonts.GetBigFont(Canvas.ClipX);
+ if (!obj.bActive) {
+ Canvas.Style = ERenderStyle.STY_Translucent;
+ Canvas.DrawColor = WhiteColor * 0.5;
+ } else {
+ Canvas.DrawColor = GoldColor;
+ }
- Canvas.SetPos(0, 160.0 / 768.0 * Canvas.ClipY);
- DrawCategoryHeaders(Canvas);
+ Canvas.SetPos(XOffset + YL, YOffset);
+ Canvas.DrawText(obj.message, False);
- Canvas.StrLen("TEST", XL, YL);
- YStart = Canvas.CurY;
- YOffset = YStart;
- if (PlayerCount > 15) PlayerCount = FMin(PlayerCount, (Canvas.ClipY - YStart) / YL - 1);
+ Canvas.Style = ERenderStyle.STY_Translucent;
+ Canvas.SetPos(XOffset + 4, YOffset + 4);
+ if (obj.bCompleted) {
+ Canvas.DrawTile(Texture'{{package}}.Hud.ObjComplete', (YL - 8), (YL - 8), 0, 0, 32, 32);
+ } else {
+ Canvas.DrawTile(Texture'{{package}}.Hud.ObjIncomplete', (YL - 8), (YL - 8), 0, 0, 32, 32);
+ }
+
+ Canvas.Style = Style;
- Canvas.SetPos(0, 0);
- for (I = 0; I < PlayerCount; I++) {
- YOffset = YStart + I * YL;
- DrawNameAndPing(Canvas, Ordered[I], 0, YOffset, false);
+ YOffset -= YL;
+
+ wasObjectives = true;
}
- Canvas.DrawColor = LightGreenColor;
- Canvas.Font = CanvasFont;
- // Trailer
- if (!Level.bLowRes) {
- Canvas.Font = MyFonts.GetSmallFont(Canvas.ClipX);
- DrawTrailer(Canvas);
+ if (wasObjectives) {
+ Canvas.SetPos(XOffset, YOffset);
+ Canvas.DrawColor = GreenColor;
+ Canvas.DrawText(ObjectivesString, False);
}
- Canvas.DrawColor = WhiteColor;
- Canvas.Font = CanvasFont;
}
-defaultproperties {
- GreenColor=(G=255)
- WhiteColor=(R=255, G=255, B=255)
- GoldColor=(R=255, G=255)
- BlueColor=(B=255)
- LightCyanColor=(R=128, G=255, B=255)
- SilverColor=(R=138, G=164, B=166)
- BronzeColor=(R=203, G=147, B=52)
- CyanColor=(G=128, B=255)
- RedColor=(R=255)
+defaultproperties
LightGreenColor=(G=136)
DarkGreenColor=(G=255, B=128)
Restart="You have been killed. Hit [Fire] to continue the hunt!"
@@ -294,4 +277,6 @@ defaultproperties {
PlayerString="Hunter"
FragsString="Score"
DeathsString="Lives"
+ MonsterDifficultyJoinString="Monsters /"
+ ObjectivesString="Objectives"
}
diff --git a/src/Classes/MonsterHUD.uc b/src/Classes/MonsterHUD.uc
index b59502e..2d2b8dc 100644
--- a/src/Classes/MonsterHUD.uc
+++ b/src/Classes/MonsterHUD.uc
@@ -99,7 +99,7 @@ simulated function DrawGameSynopsis(Canvas Canvas) {
obj = mri.objectives[i];
if (obj != None) {
if (!obj.bActive && !obj.bAlwaysShown) {
- if (!obj.bCompleted || (obj.bCompleted && !obj.bShowWhenComplete)) continue;
+ if (!obj.bCompleted || (obj.bCompleted && !obj.bShowWhenComplete)) continue;
}
if (!obj.bActive) {
Canvas.Style = ERenderStyle.STY_Translucent;
@@ -114,9 +114,9 @@ simulated function DrawGameSynopsis(Canvas Canvas) {
Canvas.Style = ERenderStyle.STY_Translucent;
Canvas.SetPos(XOffset + 4, YOffset + 4);
if (obj.bCompleted) {
- Canvas.DrawTile(Texture'{{package}}.Hud.ObjComplete', (YL - 8) * Scale, (YL - 8) * Scale, 0, 0, 32, 32);
+ Canvas.DrawTile(Texture'{{package}}.Hud.ObjComplete', (YL - 8), (YL - 8), 0, 0, 32, 32);
} else {
- Canvas.DrawTile(Texture'{{package}}.Hud.ObjIncomplete', (YL - 8) * Scale, (YL - 8) * Scale, 0, 0, 32, 32);
+ Canvas.DrawTile(Texture'{{package}}.Hud.ObjIncomplete', (YL - 8), (YL - 8), 0, 0, 32, 32);
}
Canvas.Style = Style;
diff --git a/src/Classes/MonsterHunt.uc b/src/Classes/MonsterHunt.uc
index dc7342e..7fb3feb 100644
--- a/src/Classes/MonsterHunt.uc
+++ b/src/Classes/MonsterHunt.uc
@@ -56,6 +56,7 @@ function InitGameReplicationInfo() {
mri.Lives = Lives;
mri.bUseTeamSkins = bUseTeamSkins;
mri.bUseLives = Lives > 0;
+ mri.MonsterSkill = MonsterSkill;
}
}
@@ -665,7 +666,12 @@ function CountMonsters() {
local int monsterCount;
monsterCount = 0;
- foreach AllActors(class'ScriptedPawn', S) if (S.Health >= 1) monsterCount ++;
+ foreach AllActors(class'ScriptedPawn', S) {
+ if (S.Health >= 1) {
+ if ((S.IsA('Nali') || S.IsA('Cow')) && !MaybeEvilFriendlyPawn(S)) continue;
+ monsterCount ++;
+ }
+ }
MonsterReplicationInfo(GameReplicationInfo).Monsters = monsterCount;
}
@@ -869,16 +875,18 @@ function byte AssessBotAttitude(Bot aBot, Pawn Other) {
return super(DeathMatchPlus).AssessBotAttitude(aBot, Other);
}
-function bool MaybeEvilFriendlyPawn(ScriptedPawn Pawn, Pawn Other) {
+function bool MaybeEvilFriendlyPawn(ScriptedPawn Pawn, optional Pawn Other) {
switch (Pawn.Default.AttitudeToPlayer) {
case ATTITUDE_Hate:
case ATTITUDE_Frenzy:
return true;
default:
- switch (Pawn.AttitudeToCreature(Other)) {
- case ATTITUDE_Hate:
- case ATTITUDE_Frenzy:
- return true;
+ if (Other != None) {
+ switch (Pawn.AttitudeToCreature(Other)) {
+ case ATTITUDE_Hate:
+ case ATTITUDE_Frenzy:
+ return true;
+ }
}
}
return false;
diff --git a/src/Classes/MonsterHuntObjective.uc b/src/Classes/MonsterHuntObjective.uc
index f2b163d..0f581a5 100644
--- a/src/Classes/MonsterHuntObjective.uc
+++ b/src/Classes/MonsterHuntObjective.uc
@@ -71,13 +71,13 @@ function Trigger(Actor Other, Pawn EventInstigator) {
if (!bInitiallyActive && !bActive && SoundActivated != None) {
for (P = Level.PawnList; P != None; P = P.nextPawn) {
- if (P.bIsPlayer) P.PlaySound(SoundActivated, SLOT_Interface, 2.0);
+ if (P.bIsPlayer) P.PlaySound(SoundActivated, SLOT_Interface, 1.5);
}
}
if (bCompleted && SoundCompleted != None) {
for (P = Level.PawnList; P != None; P = P.nextPawn) {
- if (P.bIsPlayer) P.PlaySound(SoundCompleted, SLOT_Interface, 2.0);
+ if (P.bIsPlayer) P.PlaySound(SoundCompleted, SLOT_Interface, 1.5);
}
}
diff --git a/src/Classes/MonsterHuntRules.uc b/src/Classes/MonsterHuntRules.uc
index b4dd3b9..3fd473c 100644
--- a/src/Classes/MonsterHuntRules.uc
+++ b/src/Classes/MonsterHuntRules.uc
@@ -91,7 +91,7 @@ function Notify(UWindowDialogControl C, byte E) {
}
function LoadCurrentValues() {
- local int skill, difficulty;
+ local int difficulty;
Super.LoadCurrentValues();
TimeEdit.SetValue(string(Class(BotmatchParent.GameClass).Default.TimeLimit));
@@ -113,18 +113,21 @@ function LoadCurrentValues() {
FragEdit.SetValue(string(Class(BotmatchParent.GameClass).Default.Lives));
TourneyCheck.bChecked = Class(BotmatchParent.GameClass).Default.bUseTeamSkins;
- // translate difficulty on scale of 8 (based on bot skill) to 4 (based on Unreal skills)
- skill = class(BotmatchParent.GameClass).Default.MonsterSkill;
- if (skill <= 1) difficulty = 0;
- else if (skill <= 3) difficulty = 1;
- else if (skill <= 5) difficulty = 2;
- else if (skill <= 7) difficulty = 3;
- else difficulty = 2;
+ difficulty = TranslateMonsterSkillIndex(class(BotmatchParent.GameClass).Default.MonsterSkill);
DifficultyCombo.SetSelectedIndex(Min(difficulty, 7));
TauntLabel.SetText(SkillTaunts[DifficultyCombo.GetSelectedIndex()]);
}
+// translate difficulty on scale of 8 (based on bot skill) to 4 (based on Unreal skills)
+static function int TranslateMonsterSkillIndex(int skill) {
+ if (skill <= 1) return 0;
+ else if (skill <= 3) return 1;
+ else if (skill <= 5) return 2;
+ else if (skill <= 7) return 3;
+ else return 2;
+}
+
function Paint(Canvas C, float X, float Y) {
Super.Paint(C, X, Y);
diff --git a/src/Classes/MonsterReplicationInfo.uc b/src/Classes/MonsterReplicationInfo.uc
index b9b4229..8600511 100644
--- a/src/Classes/MonsterReplicationInfo.uc
+++ b/src/Classes/MonsterReplicationInfo.uc
@@ -14,6 +14,7 @@ var bool bUseTeamSkins;
var int Lives;
var int Monsters;
var int Hunters;
+var int MonsterSkill;
// objectives
var MonsterHuntObjective objectives[16];
@@ -24,7 +25,7 @@ var int Escapees;
replication {
reliable if (Role == ROLE_Authority)
- Lives, Monsters, bUseLives, bUseTeamSkins, Hunters, Escapees, objectives;
+ Lives, Monsters, bUseLives, bUseTeamSkins, Hunters, Escapees, objectives, MonsterSkill;
}
function RegisterObjective(MonsterHuntObjective objective) {