diff --git a/Daybreak/Daybreak.csproj b/Daybreak/Daybreak.csproj
index 0cf9331b..cd8d425f 100644
--- a/Daybreak/Daybreak.csproj
+++ b/Daybreak/Daybreak.csproj
@@ -13,7 +13,7 @@
preview
Daybreak.ico
true
- 0.9.8.9
+ 0.9.8.10
true
cfb2a489-db80-448d-a969-80270f314c46
diff --git a/Daybreak/Models/Guildwars/GameData.cs b/Daybreak/Models/Guildwars/GameData.cs
index d92c4225..d751a2dd 100644
--- a/Daybreak/Models/Guildwars/GameData.cs
+++ b/Daybreak/Models/Guildwars/GameData.cs
@@ -5,6 +5,7 @@ namespace Daybreak.Models;
public sealed class GameData
{
+ public bool Valid { get; init; }
public MainPlayerInformation? MainPlayer { get; init; }
public List? Party { get; init; }
public UserInformation? User { get; init; }
diff --git a/Daybreak/Models/Guildwars/PlayerInformation.cs b/Daybreak/Models/Guildwars/PlayerInformation.cs
index e6599afb..efead409 100644
--- a/Daybreak/Models/Guildwars/PlayerInformation.cs
+++ b/Daybreak/Models/Guildwars/PlayerInformation.cs
@@ -7,6 +7,7 @@ public class PlayerInformation
public Profession? PrimaryProfession { get; init; }
public Profession? SecondaryProfession { get; init; }
public List? UnlockedProfession { get; init; }
+ public Build? CurrentBuild { get; init; }
public float CurrentHealth { get; init; }
public float MaxHealth { get; init; }
public float CurrentEnergy { get; init; }
diff --git a/Daybreak/Models/Guildwars/SkillMetadata.cs b/Daybreak/Models/Guildwars/SkillMetadata.cs
new file mode 100644
index 00000000..a896efa3
--- /dev/null
+++ b/Daybreak/Models/Guildwars/SkillMetadata.cs
@@ -0,0 +1,11 @@
+namespace Daybreak.Models.Guildwars;
+
+public sealed class SkillMetadata
+{
+ public Skill? Skill { get; init; }
+ public uint Adrenaline1 { get; init; }
+ public uint Adrenaline2 { get; init; }
+ public uint Recharge { get; init; }
+ public uint Id { get; init; }
+ public uint Event { get; init; }
+}
diff --git a/Daybreak/Models/Guildwars/WorldPlayerInformation.cs b/Daybreak/Models/Guildwars/WorldPlayerInformation.cs
index 4cf6c1e0..7834429c 100644
--- a/Daybreak/Models/Guildwars/WorldPlayerInformation.cs
+++ b/Daybreak/Models/Guildwars/WorldPlayerInformation.cs
@@ -1,4 +1,6 @@
-namespace Daybreak.Models.Guildwars;
+using System.Collections.Generic;
+
+namespace Daybreak.Models.Guildwars;
public class WorldPlayerInformation : PlayerInformation
{
diff --git a/Daybreak/Models/Interop/AttributeContext.cs b/Daybreak/Models/Interop/AttributeContext.cs
new file mode 100644
index 00000000..1ce10650
--- /dev/null
+++ b/Daybreak/Models/Interop/AttributeContext.cs
@@ -0,0 +1,10 @@
+namespace Daybreak.Models.Interop;
+
+public readonly struct AttributeContext
+{
+ public readonly uint Id;
+ public readonly uint BaseLevel;
+ public readonly uint ActualLevel;
+ public readonly uint DecrementPoints;
+ public readonly uint IncrementPoints;
+}
diff --git a/Daybreak/Models/Interop/GameContext.cs b/Daybreak/Models/Interop/GameContext.cs
index d9a8599b..c3103bc9 100644
--- a/Daybreak/Models/Interop/GameContext.cs
+++ b/Daybreak/Models/Interop/GameContext.cs
@@ -12,6 +12,9 @@ public readonly struct GameContext
///Array of type .
public readonly GuildwarsArray MapEntities;
+ [FieldOffset(0x0030)]
+ public readonly GuildwarsArray PartyAttributes;
+
[FieldOffset(0x04AC)]
public readonly uint QuestId;
@@ -21,10 +24,13 @@ public readonly struct GameContext
[FieldOffset(0x0608)]
public readonly uint HardModeUnlocked;
- [FieldOffset(0x640)]
+ [FieldOffset(0x0640)]
///Array of type
public readonly GuildwarsArray Professions;
+ [FieldOffset(0x0674)]
+ public readonly GuildwarsArray Skillbars;
+
[FieldOffset(0x06C4)]
public readonly uint Experience;
diff --git a/Daybreak/Models/Interop/PartyAttributesContext.cs b/Daybreak/Models/Interop/PartyAttributesContext.cs
new file mode 100644
index 00000000..a0d15be1
--- /dev/null
+++ b/Daybreak/Models/Interop/PartyAttributesContext.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace Daybreak.Models.Interop;
+
+public readonly struct PartyAttributesContext
+{
+ public readonly uint AgentId;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x36)]
+ public readonly AttributeContext[] Attributes;
+}
diff --git a/Daybreak/Models/Interop/SkillContext.cs b/Daybreak/Models/Interop/SkillContext.cs
new file mode 100644
index 00000000..9afd55d4
--- /dev/null
+++ b/Daybreak/Models/Interop/SkillContext.cs
@@ -0,0 +1,17 @@
+using System.Runtime.InteropServices;
+
+namespace Daybreak.Models.Interop;
+
+[StructLayout(LayoutKind.Sequential)]
+public readonly struct SkillContext
+{
+ public readonly uint Adrenaline1;
+
+ public readonly uint Adrenaline2;
+
+ public readonly uint Recharge;
+
+ public readonly uint Id;
+
+ public readonly uint Event;
+}
diff --git a/Daybreak/Models/Interop/SkillbarContext.cs b/Daybreak/Models/Interop/SkillbarContext.cs
new file mode 100644
index 00000000..7de49246
--- /dev/null
+++ b/Daybreak/Models/Interop/SkillbarContext.cs
@@ -0,0 +1,23 @@
+using System.Runtime.InteropServices;
+
+namespace Daybreak.Models.Interop;
+
+[StructLayout(LayoutKind.Explicit)]
+public readonly struct SkillbarContext
+{
+ [FieldOffset(0x0000)]
+ public readonly uint AgentId;
+
+ [FieldOffset(0x0004)]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x08)]
+ public readonly SkillContext[] Skills;
+
+ [FieldOffset(0x00A4)]
+ public readonly uint Disabled;
+
+ [FieldOffset(0x00B0)]
+ public readonly uint Casting;
+
+ [FieldOffset(0x00B8)]
+ public readonly uint H00B8;
+}
diff --git a/Daybreak/Services/Scanner/GuildwarsMemoryReader.cs b/Daybreak/Services/Scanner/GuildwarsMemoryReader.cs
index d2810520..0480bda0 100644
--- a/Daybreak/Services/Scanner/GuildwarsMemoryReader.cs
+++ b/Daybreak/Services/Scanner/GuildwarsMemoryReader.cs
@@ -1,17 +1,19 @@
using Daybreak.Models;
+using Daybreak.Models.Builds;
using Daybreak.Models.Guildwars;
using Daybreak.Models.Interop;
using Microsoft.Extensions.Logging;
using System;
+using System.Collections.Generic;
using System.Core.Extensions;
using System.Diagnostics;
using System.Extensions;
using System.Linq;
using System.Logging;
-using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows.Documents;
namespace Daybreak.Services.Scanner;
@@ -26,6 +28,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
private IntPtr entityArrayPointer;
private volatile CancellationTokenSource? cancellationTokenSource;
+ public bool Faulty { get; private set; }
+
public bool Running => this.cancellationTokenSource is not null && this.cancellationTokenSource.IsCancellationRequested is false;
public GameData? GameData { get; private set; }
@@ -121,9 +125,12 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
try
{
this.ReadGameMemory(cancellationToken);
+ this.Faulty = false;
}
catch(Exception e)
{
+ this.GameData = null;
+ this.Faulty = true;
this.logger.LogError(e, "Exception encountered when reading game memory");
}
}
@@ -157,13 +164,16 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
var professions = this.memoryScanner.ReadArray(gameContext.Professions);
var players = this.memoryScanner.ReadArray(gameContext.Players);
var quests = this.memoryScanner.ReadArray(gameContext.QuestLog);
+ var skills = this.memoryScanner.ReadArray(gameContext.Skillbars);
+ var partyAttributes = this.memoryScanner.ReadArray(gameContext.PartyAttributes);
var playerEntityId = this.memoryScanner.ReadPtrChain(this.GetPlayerIdPointer(), 0x0, 0x0);
+
// The following lines would retrieve all entities, including item entities.
//var entityArray = this.memoryScanner.ReadPtrChain(this.GetEntityArrayPointer(), 0x0, 0x0);
//var entities = this.memoryScanner.ReadArray(entityArray);
- this.GameData = this.AggregateGameData(gameContext, instanceContext, mapEntities, players, professions, quests, userContext, playerEntityId);
+ this.GameData = this.AggregateGameData(gameContext, instanceContext, mapEntities, players, professions, quests, userContext, skills, partyAttributes, playerEntityId);
}
private IntPtr GetPlayerIdPointer()
@@ -185,7 +195,7 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
return this.entityArrayPointer;
}
-
+
private GameData AggregateGameData(
GameContext gameContext,
InstanceContext instanceContext,
@@ -194,6 +204,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
ProfessionsContext[] professions,
QuestContext[] quests,
UserContext userContext,
+ SkillbarContext[] skills,
+ PartyAttributesContext[] partyAttributes,
int mainPlayerEntityId)
{
var email = ParseAndCleanWCharArray(userContext.PlayerEmailBytes);
@@ -201,14 +213,14 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
_ = Map.TryParse((int)userContext.MapId, out var currentMap);
var partyMembers = professions
.Where(p => p.AgentId != mainPlayerEntityId)
- .Select(p => GetPlayerInformation((int)p.AgentId, instanceContext, entities, professions))
+ .Select(p => GetPlayerInformation((int)p.AgentId, instanceContext, entities, professions, skills, partyAttributes))
.ToList();
- var mainPlayer = GetMainPlayerInformation(mainPlayerEntityId, name, gameContext, instanceContext, entities, professions, quests);
+ var mainPlayer = GetMainPlayerInformation(mainPlayerEntityId, name, gameContext, instanceContext, entities, professions, quests, skills, partyAttributes);
var worldPlayers = players
.Where(p => p.AgentId != mainPlayerEntityId)
- .Select(p => GetWorldPlayerInformation(p, this.memoryScanner.ReadWString(p.NamePointer, 0x40), instanceContext, entities, professions))
+ .Select(p => GetWorldPlayerInformation(p, this.memoryScanner.ReadWString(p.NamePointer, 0x40), instanceContext, entities, professions, skills, partyAttributes))
.ToList();
@@ -245,7 +257,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
MainPlayer = mainPlayer,
Session = sessionInformation,
User = userInformation,
- WorldPlayers = worldPlayers
+ WorldPlayers = worldPlayers,
+ Valid = entities.Length > 0 || players.Length > 0 || professions.Length > 0 || quests.Length > 0 || skills.Length > 0 || partyAttributes.Length > 0
};
}
@@ -256,9 +269,11 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
InstanceContext instanceContext,
MapEntityContext[] entities,
ProfessionsContext[] professions,
- QuestContext[] quests)
+ QuestContext[] quests,
+ SkillbarContext[] skillbars,
+ PartyAttributesContext[] partyAttributes)
{
- var playerInformation = GetPlayerInformation(mainPlayerId, instanceContext, entities, professions);
+ var playerInformation = GetPlayerInformation(mainPlayerId, instanceContext, entities, professions, skillbars, partyAttributes);
_ = Quest.TryParse((int)gameContext.QuestId, out var quest);
var questLog = quests
.Select(q =>
@@ -288,7 +303,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
Name = name,
Experience = gameContext.Experience,
Level = gameContext.Level,
- Morale = gameContext.Morale
+ Morale = gameContext.Morale,
+ CurrentBuild = playerInformation.CurrentBuild
};
}
@@ -297,9 +313,11 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
string name,
InstanceContext instanceContext,
MapEntityContext[] entities,
- ProfessionsContext[] professions)
+ ProfessionsContext[] professions,
+ SkillbarContext[] skillbars,
+ PartyAttributesContext[] partyAttributes)
{
- var playerInformation = GetPlayerInformation(playerContext.AgentId, instanceContext, entities, professions);
+ var playerInformation = GetPlayerInformation(playerContext.AgentId, instanceContext, entities, professions, skillbars, partyAttributes);
return new WorldPlayerInformation
{
PrimaryProfession = playerInformation.PrimaryProfession,
@@ -312,6 +330,7 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
EnergyRegen = playerInformation.EnergyRegen,
HealthRegen = playerInformation.HealthRegen,
Name = name,
+ CurrentBuild = playerInformation.CurrentBuild
};
}
@@ -319,7 +338,9 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
int playerId,
InstanceContext instanceContext,
MapEntityContext[] entities,
- ProfessionsContext[] professions)
+ ProfessionsContext[] professions,
+ SkillbarContext[] skillbars,
+ PartyAttributesContext[] partyAttributes)
{
var entityContext = entities.Skip(playerId).FirstOrDefault();
var professionContext = professions.Where(p => p.AgentId == playerId).FirstOrDefault();
@@ -331,6 +352,44 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
.Where(p => p is not null && p != Profession.None)
.OrderBy(p => p.Id)
.ToList();
+ var maybeSkillbarContext = skillbars.Select(s => (SkillbarContext?) s).FirstOrDefault(s => s?.AgentId == playerId);
+ var maybePartyAttributesContext = partyAttributes.Select(p => (PartyAttributesContext?) p).FirstOrDefault(p => p?.AgentId == playerId);
+ Build? build = null;
+ if (maybeSkillbarContext is SkillbarContext skillbarContext &&
+ maybePartyAttributesContext is PartyAttributesContext attributesContext &&
+ primaryProfession is not null &&
+ secondaryProfession is not null)
+ {
+ var attributes = new List { primaryProfession.PrimaryAttribute! }
+ .Concat(primaryProfession.Attributes)
+ .Concat(secondaryProfession.Attributes)
+ .Select(a => new AttributeEntry { Attribute = a })
+ .ToList();
+ foreach(var attribute in attributesContext.Attributes)
+ {
+ if (attribute.Id < 0 || attribute.Id > 44)
+ {
+ continue;
+ }
+
+ var maybeAttributeEntry = attributes.FirstOrDefault(a => a.Attribute!.Id == attribute.Id);
+ if (maybeAttributeEntry is not AttributeEntry attributeEntry)
+ {
+ continue;
+ }
+
+ attributeEntry.Points = (int)attribute.BaseLevel;
+ }
+
+ build = new Build
+ {
+ Primary = primaryProfession,
+ Secondary = secondaryProfession,
+ Attributes = attributes,
+ Skills = skillbarContext.Skills.Select(s => Skill.Parse((int)s.Id)).ToList()
+ };
+ }
+
(var currentHp, var currentEnergy) = ApplyEnergyAndHealthRegen(instanceContext, entityContext);
return new PlayerInformation
{
@@ -342,7 +401,8 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
MaxHealth = entityContext.MaxHealth,
MaxEnergy = entityContext.MaxEnergy,
HealthRegen = entityContext.HealthRegen,
- EnergyRegen = entityContext.EnergyRegen
+ EnergyRegen = entityContext.EnergyRegen,
+ CurrentBuild = build
};
}
@@ -377,5 +437,6 @@ public sealed class GuildwarsMemoryReader : IGuildwarsMemoryReader, IDisposable
this.cancellationTokenSource?.Cancel();
this.cancellationTokenSource?.Dispose();
this.cancellationTokenSource = null;
+ this.Faulty = false;
}
}
diff --git a/Daybreak/Services/Scanner/IGuildwarsMemoryReader.cs b/Daybreak/Services/Scanner/IGuildwarsMemoryReader.cs
index aef28838..08f962da 100644
--- a/Daybreak/Services/Scanner/IGuildwarsMemoryReader.cs
+++ b/Daybreak/Services/Scanner/IGuildwarsMemoryReader.cs
@@ -5,6 +5,7 @@ namespace Daybreak.Services.Scanner;
public interface IGuildwarsMemoryReader
{
+ bool Faulty { get; }
bool Running { get; }
GameData? GameData { get; }
Process? TargetProcess { get; }
diff --git a/Daybreak/Views/FocusView.xaml b/Daybreak/Views/FocusView.xaml
index 3a378edb..581a998e 100644
--- a/Daybreak/Views/FocusView.xaml
+++ b/Daybreak/Views/FocusView.xaml
@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Views"
xmlns:controls="clr-namespace:Daybreak.Controls"
+ xmlns:converters="clr-namespace:Daybreak.Converters"
xmlns:templates="clr-namespace:Daybreak.Controls.Templates"
mc:Ignorable="d"
Foreground="White"
@@ -14,6 +15,7 @@
d:DesignHeight="450" d:DesignWidth="800">
+
@@ -32,7 +34,8 @@
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="2"
- Grid.RowSpan="2">
+ Grid.RowSpan="2"
+ Visibility="{Binding ElementName=_this, Path=GameData.Valid, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
@@ -238,19 +241,90 @@
+ Grid.Column="1"
+ Visibility="{Binding ElementName=_this, Path=GameData.Valid, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Daybreak/Views/FocusView.xaml.cs b/Daybreak/Views/FocusView.xaml.cs
index c8f68c36..b49070ab 100644
--- a/Daybreak/Views/FocusView.xaml.cs
+++ b/Daybreak/Views/FocusView.xaml.cs
@@ -1,7 +1,9 @@
using Daybreak.Configuration;
using Daybreak.Models;
+using Daybreak.Models.Builds;
using Daybreak.Models.Guildwars;
using Daybreak.Services.ApplicationLauncher;
+using Daybreak.Services.BuildTemplates;
using Daybreak.Services.Experience;
using Daybreak.Services.Navigation;
using Daybreak.Services.Scanner;
@@ -15,6 +17,7 @@ using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
+using System.Windows.Media.Animation;
namespace Daybreak.Views;
@@ -23,8 +26,12 @@ namespace Daybreak.Views;
///
public partial class FocusView : UserControl
{
+ private const string InfoNamePlaceholder = "[NAME]";
+ private const string WikiBaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
+ private const string BuildsAddress = $"https://gwpvx.fandom.com/wiki/Category:Builds_by_category";
private const double BarsTotalSize = 116; // Size of the bars on one side of the screen.
+ private readonly IBuildTemplateManager buildTemplateManager;
private readonly IApplicationLauncher applicationLauncher;
private readonly IGuildwarsMemoryReader guildwarsMemoryReader;
private readonly IExperienceCalculator experienceCalculator;
@@ -74,6 +81,7 @@ public partial class FocusView : UserControl
private bool browserMaximized = false;
public FocusView(
+ IBuildTemplateManager buildTemplateManager,
IApplicationLauncher applicationLauncher,
IGuildwarsMemoryReader guildwarsMemoryReader,
IExperienceCalculator experienceCalculator,
@@ -81,6 +89,7 @@ public partial class FocusView : UserControl
ILiveUpdateableOptions liveUpdateableOptions,
ILogger logger)
{
+ this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
this.applicationLauncher = applicationLauncher.ThrowIfNull();
this.guildwarsMemoryReader = guildwarsMemoryReader.ThrowIfNull();
this.experienceCalculator = experienceCalculator.ThrowIfNull();
@@ -126,7 +135,8 @@ public partial class FocusView : UserControl
this.viewManager.ShowView();
}
- if (this.guildwarsMemoryReader.Running is false)
+ if (this.guildwarsMemoryReader.Running is false ||
+ this.guildwarsMemoryReader.Faulty)
{
this.guildwarsMemoryReader.Initialize(this.applicationLauncher.RunningGuildwarsProcess!);
}
@@ -134,6 +144,7 @@ public partial class FocusView : UserControl
this.Dispatcher.Invoke(() =>
{
this.GameData = this.guildwarsMemoryReader.GameData;
+ this.Browser.Visibility = this.GameData?.Valid is true ? Visibility.Visible : Visibility.Collapsed;
if (this.GameData?.MainPlayer is null ||
this.GameData?.User is null ||
this.GameData?.Session is null)
@@ -491,6 +502,37 @@ public partial class FocusView : UserControl
}
}
+ private void MetaBuilds_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ this.BrowserAddress = BuildsAddress;
+ }
+
+ private void PrimaryProfession_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ if (this.GameData.MainPlayer?.PrimaryProfession?.Name is string professionName)
+ {
+ this.BrowserAddress = WikiBaseAddress.Replace(InfoNamePlaceholder, professionName);
+ }
+ }
+
+ private void SecondaryProfession_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ if (this.GameData.MainPlayer?.SecondaryProfession?.Name is string professionName)
+ {
+ this.BrowserAddress = WikiBaseAddress.Replace(InfoNamePlaceholder, professionName);
+ }
+ }
+
+ private void EditBuild_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ if (this.GameData.MainPlayer?.CurrentBuild is Build build)
+ {
+ var buildEntry = this.buildTemplateManager.CreateBuild();
+ buildEntry.Build = build;
+ this.viewManager.ShowView(buildEntry);
+ }
+ }
+
private void Browser_MaximizeClicked(object sender, EventArgs e)
{
this.browserMaximized = !this.browserMaximized;
diff --git a/Scripts/CompareVersions.ps1 b/Scripts/CompareVersions.ps1
index f03b5115..dddbfe78 100644
--- a/Scripts/CompareVersions.ps1
+++ b/Scripts/CompareVersions.ps1
@@ -13,10 +13,36 @@ if ($lastVersion.StartsWith("v")){
$lastVersion = $lastVersion.Substring(1)
}
-$isNewer = $currentVersion.CompareTo($lastVersion) -eq 1
-if ($isNewer -eq $false){
- throw "Version is not incremented. Current version " + $currentVersion + ". Last version " + $lastVersion
+$currentVersionTokens = $currentVersion.Split('.')
+$lastVersionTokens = $lastVersion.Split('.')
+if ($currentVersionTokens.Length -eq $lastVersionTokens.Length)
+{
+ for($i = 0 ; $i -lt $currentVersionTokens.Length; $i++)
+ {
+ $currentVersionToken = [int]$currentVersionTokens[$i]
+ $lastVersionToken = [int]$lastVersionTokens[$i]
+ if ($currentVersionToken -lt $lastVersionToken){
+ throw "Version is not incremented. Current version " + $currentVersion + ". Last version " + $lastVersion
+ }
+ }
+
+ if ($currentVersionToken -le $lastVersionToken){
+ throw "Version is not incremented. Current version " + $currentVersion + ". Last version " + $lastVersion
+ }
+
+ Write-Host "Version has been incremented"
}
-else{
+elseif ($currentVersionTokens.Length -gt $lastVersionTokens.Length){
+ if ($currentVersionTokens[$lastVersionTokens.Length - 1] -lt $lastVersionTokens[$lastVersionTokens.Length - 1]){
+ throw "Version is not incremented. Current version " + $currentVersion + ". Last version " + $lastVersion
+ }
+
+ Write-Host "Version has been incremented"
+}
+elseif ($currentVersionTokens.Length -lt $lastVersionTokens.Length){
+ if ($currentVersionTokens[$currentVersionTokens.Length - 1] -le $lastVersionTokens[$currentVersionTokens.Length - 1]){
+ throw "Version is not incremented. Current version " + $currentVersion + ". Last version " + $lastVersion
+ }
+
Write-Host "Version has been incremented"
}
\ No newline at end of file