...
 
Commits (7)
# always normalise line endings
* text=auto
# user-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# build results
[Dd]ebug/
[Rr]elease/
[Bb]in/
[Oo]bj/
# Visual Studio cache/options
.vs/
# ReSharper
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# NuGet packages
*.nupkg
**/packages/*
*.nuget.props
*.nuget.targets
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/StaticQualifier/STATIC_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
</wpf:ResourceDictionary>
\ No newline at end of file
namespace SMAPIHealthBarMod
{
/// <summary>The mod configuration model.</summary>
public class HealthBarConfig
{
/*********
** Accessors
*********/
/// <summary>The color scheme to apply.</summary>
public int ColourScheme { get; set; }
}
}
/*
Copyright 2016 Maurício Gomes (Speeder)
Storm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Speeder's SDV Mods are distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Speeder's SDV Mods. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewValley;
using StardewValley.Monsters;
namespace SMAPIHealthBarMod
{
/// <summary>The mod entry point.</summary>
public class HealthBarMod : Mod
{
/*********
** Properties
*********/
/// <summary>A blank pixel for drawing.</summary>
private Texture2D Pixel;
/// <summary>The mod settings.</summary>
private HealthBarConfig Config;
/// <summary>The available color schemes.</summary>
private readonly Color[][] ColorSchemes =
{
new[] { Color.LawnGreen, Color.YellowGreen, Color.Gold, Color.DarkOrange, Color.Crimson },
new[] { Color.Crimson, Color.DarkOrange, Color.Gold, Color.YellowGreen, Color.LawnGreen },
};
/*********
** Public methods
*********/
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
this.Config = helper.ReadConfig<HealthBarConfig>();
if (this.Config.ColourScheme < 0)
this.Config.ColourScheme = 0;
if (this.Config.ColourScheme >= this.ColorSchemes.Length)
this.Config.ColourScheme = this.ColorSchemes.Length - 1;
GraphicsEvents.OnPostRenderEvent += this.GraphicsEvents_DrawTick;
}
/*********
** Private methods
*********/
/// <summary>The method invoked when the game is drawing to the screen.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>
private void GraphicsEvents_DrawTick(object sender, EventArgs e)
{
if (!Game1.hasLoadedGame || Game1.currentMinigame != null || Game1.activeClickableMenu != null)
return;
if (this.Pixel == null)
this.Pixel = this.GetPixel();
foreach (Monster monster in Game1.currentLocation.characters.OfType<Monster>())
{
// skip if not visible
if (monster.isInvisible || !Utility.isOnScreen(monster.position, 3 * Game1.tileSize))
continue;
// get monster data
int health = monster.health;
int maxHealth = Math.Max(monster.maxHealth, monster.health);
int numberKilled = Game1.stats.specificMonstersKilled.ContainsKey(monster.name)
? Game1.stats.specificMonstersKilled[monster.name]
: 0;
string label = "???";
// get bar data
Color barColor;
float barLengthPercent;
if (numberKilled + Game1.player.combatLevel > 15)
{
float monsterHealthPercent = health / (float)maxHealth;
barLengthPercent = 1f;
if (monsterHealthPercent > 0.9f)
barColor = this.ColorSchemes[this.Config.ColourScheme][0];
else if (monsterHealthPercent > 0.65f)
barColor = this.ColorSchemes[this.Config.ColourScheme][1];
else if (monsterHealthPercent > 0.35f)
barColor = this.ColorSchemes[this.Config.ColourScheme][2];
else if (monsterHealthPercent > 0.15f)
barColor = this.ColorSchemes[this.Config.ColourScheme][3];
else
barColor = this.ColorSchemes[this.Config.ColourScheme][4];
if (numberKilled + Game1.player.combatLevel * 4 > 45)
{
barLengthPercent = monsterHealthPercent;
label = monster.health > 999
? "!!!"
: $"{monster.health:000}";
}
}
else
{
barLengthPercent = 1f;
barColor = Color.DarkSlateGray;
}
// get monster position
Vector2 monsterLocalPosition = monster.getLocalPosition(Game1.viewport);
Rectangle monsterBox = new Rectangle((int)monsterLocalPosition.X, (int)monsterLocalPosition.Y - monster.sprite.spriteHeight / 2 * Game1.pixelZoom, monster.sprite.spriteWidth * Game1.pixelZoom, 12);
if (monster is GreenSlime slime)
{
if (slime.hasSpecialItem)
{
monsterBox.X -= 5;
monsterBox.Width += 10;
}
else if (slime.cute)
{
monsterBox.X -= 2;
monsterBox.Width += 4;
}
else
monsterBox.Y += 5 * Game1.pixelZoom;
}
else if (monster is RockCrab || monster is LavaCrab)
{
if (monster.sprite.CurrentFrame % 4 == 0)
continue;
}
else if (monster is RockGolem)
{
if (monster.health == monster.maxHealth)
continue;
monsterBox.Y = (int)monsterLocalPosition.Y - monster.sprite.spriteHeight * Game1.pixelZoom * 3 / 4;
}
else if (monster is Bug bug)
{
if (bug.isArmoredBug)
continue;
monsterBox.Y -= 15 * Game1.pixelZoom;
}
else if (monster is Grub)
{
if (monster.sprite.CurrentFrame == 19)
continue;
monsterBox.Y = (int)monsterLocalPosition.Y - monster.sprite.spriteHeight * Game1.pixelZoom * 4 / 7;
}
else if (monster is Fly)
monsterBox.Y = (int)monsterLocalPosition.Y - monster.sprite.spriteHeight * Game1.pixelZoom * 5 / 7;
else if (monster is DustSpirit)
{
monsterBox.X += 3;
monsterBox.Width -= 6;
monsterBox.Y += 5 * Game1.pixelZoom;
}
else if (monster is Bat)
{
if (monster.sprite.CurrentFrame == 4)
continue;
monsterBox.X -= 1;
monsterBox.Width -= 2;
monsterBox.Y += 1 * Game1.pixelZoom;
}
else if (monster is MetalHead || monster is Mummy)
monsterBox.Y -= 2 * Game1.pixelZoom;
else if (monster is Skeleton || monster is ShadowBrute || monster is ShadowShaman || monster is SquidKid)
{
if (monster.health == monster.maxHealth)
continue;
monsterBox.Y -= 7 * Game1.pixelZoom;
}
// get health bar position
Rectangle healthBox = monsterBox;
++healthBox.X;
++healthBox.Y;
healthBox.Height = monsterBox.Height - 2;
healthBox.Width = monsterBox.Width - 2;
// draw health bar
Game1.spriteBatch.Draw(this.Pixel, monsterBox, Color.BurlyWood);
Game1.spriteBatch.Draw(this.Pixel, healthBox, Color.SaddleBrown);
healthBox.Width = (int)(healthBox.Width * barLengthPercent);
Game1.spriteBatch.Draw(this.Pixel, healthBox, barColor);
// draw label
Color textColor = barColor == Color.DarkSlateGray || barLengthPercent < 0.35f ? Color.AntiqueWhite : Color.DarkSlateGray;
Utility.drawTextWithShadow(Game1.spriteBatch, label, Game1.smallFont, new Vector2(monsterBox.X + (float)monsterBox.Width / 2 - 9 * Game1.options.zoomLevel, monsterBox.Y + 2), textColor, Game1.options.zoomLevel * 0.4f, -1, 0, 0, 0, 0);
}
}
/// <summary>Get a blank pixel.</summary>
private Texture2D GetPixel()
{
Texture2D pixel = new Texture2D(Game1.graphics.GraphicsDevice, 1, 1);
pixel.SetData(new[] { Color.White });
return pixel;
}
}
}
......@@ -30,71 +30,38 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Windows\Microsoft.NET\assembly\GAC_32\Microsoft.Xna.Framework\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Windows\Microsoft.NET\assembly\GAC_32\Microsoft.Xna.Framework.Game\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Windows\Microsoft.NET\assembly\GAC_32\Microsoft.Xna.Framework.Graphics\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.Graphics.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Windows\Microsoft.NET\assembly\GAC_32\Microsoft.Xna.Framework.Xact\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.Xact.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Stardew Valley">
<HintPath>D:\gog games\Stardew Valley\Stardew Valley.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="StardewModdingAPI">
<HintPath>D:\gog games\Stardew Valley\StardewModdingAPI.exe</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xTile">
<HintPath>D:\gog games\Stardew Valley\xTile.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="SMAPIHealthBarModMainClass.cs" />
<Compile Include="HealthBarConfig.cs" />
<Compile Include="HealthBarMod.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>SET STARDEWMODDIR="D:\\gog games\\Stardew Valley\\Mods\\$(ProjectName)"
erase *.pdb
copy ..\..\..\..\README.md README.md
copy ..\..\..\..\screenshot.png screenshot.png
copy ..\..\..\..\patreon_logo_shine100.png patreon_logo_shine100.png
cd..
xcopy $(ProjectName) %25STARDEWMODDIR%25 /S /I /Y</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
<Import Project="..\packages\Pathoschild.Stardew.ModBuildConfig.1.5.0\build\Pathoschild.Stardew.ModBuildConfig.targets" Condition="Exists('..\packages\Pathoschild.Stardew.ModBuildConfig.1.5.0\build\Pathoschild.Stardew.ModBuildConfig.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Pathoschild.Stardew.ModBuildConfig.1.5.0\build\Pathoschild.Stardew.ModBuildConfig.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Pathoschild.Stardew.ModBuildConfig.1.5.0\build\Pathoschild.Stardew.ModBuildConfig.targets'))" />
</Target>
<Target Name="AfterBuild">
<PropertyGroup>
<ModPath>$(GamePath)\Mods\$(TargetName)</ModPath>
</PropertyGroup>
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll" DestinationFolder="$(ModPath)" />
<Copy SourceFiles="$(TargetDir)\$(TargetName).pdb" DestinationFolder="$(ModPath)" Condition="Exists('$(TargetDir)\$(TargetName).pdb')" />
<Copy SourceFiles="$(TargetDir)\$(TargetName).dll.mdb" DestinationFolder="$(ModPath)" Condition="Exists('$(TargetDir)\$(TargetName).dll.mdb')" />
<Copy SourceFiles="$(ProjectDir)manifest.json" DestinationFolder="$(ModPath)" />
<Copy SourceFiles="$(SolutionDir)README.md" DestinationFolder="$(ModPath)" />
<Copy SourceFiles="$(SolutionDir)screenshot.png" DestinationFolder="$(ModPath)" />
<Copy SourceFiles="$(SolutionDir)patreon_logo_shine100.png" DestinationFolder="$(ModPath)" />
</Target>
-->
</Project>
\ No newline at end of file
This diff is collapsed.
{
"Name": "Health Bars Mod",
"Authour": "Maurício Gomes (Speeder)",
"Version":
{
"MajorVersion": 1,
"MinorVersion": 7,
"PatchVersion": 0,
"Build": ""
},
"UniqueID": "SPDHealthBar",
"PerSaveConfigs": false,
"Name": "Health Bars",
"Author": "Maurício Gomes (Speeder)",
"Version": {
"MajorVersion": 1,
"MinorVersion": 8,
"PatchVersion": 0,
"Build": null
},
"MinimumApiVersion": "1.9",
"UniqueID": "Speeder.HealthBars",
"Description": "Add health bars to monsters.",
"EntryDll": "SMAPIHealthBarMod.dll"
}
\ No newline at end of file
"EntryDll": "SMAPIHealthBarMod.dll"
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Pathoschild.Stardew.ModBuildConfig" version="1.5.0" targetFramework="net452" />
</packages>
\ No newline at end of file