Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
jhett12321 committed Apr 6, 2023
2 parents 1f2ccd6 + 81d285d commit 54aa4e5
Show file tree
Hide file tree
Showing 31 changed files with 328 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
NWN_VERSION=8193.34
NWNX_VERSION=2692ecb
NWNX_VERSION=d44d373
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## 8193.34.26
https://github.com/nwn-dotnet/Anvil/compare/v8193.34.25...v8193.34.26

### Added
- NwGameTables: Added `EffectIconTable`.
- CreatureClassInfo: Added `School`, `KnownSpells` properties.
- CreatureLevelInfo: Added `AddedKnownSpells`, `RemovedKnownSpells` properties.

### Package Updates
- NWNX: 2692ecb -> d44d373
- NWN.Core: 8193.34.12 -> 8193.34.15
- NWN.Native: 8193.34.5 -> 8193.34.7
- Newtonsoft.Json: 13.0.2 -> 13.0.3
- NLog: 5.1.2 -> 5.1.3
- Paket.Core: 7.2.0 -> 7.2.1

### Changed
- CollectionExtensions: `InsertOrdered` now returns the index in which the item was inserted.
- Anvil will now log a managed stack trace during an assertion failure. We're hoping this will help track down issues where the nwscript VM reports an invalid stack state.

### Deprecated
- `CreatureClassInfo.AddKnownSpell` - use `CreatureClassInfo.KnownSpells[].Add` instead.
- `CreatureClassInfo.RemoveKnownSpell` - use `CreatureClassInfo.KnownSpells[].Remove` instead.
- `CreatureClassInfo.GetKnownSpellCountByLevel` - use `CreatureClassInfo.KnownSpells[].Count` instead.
- `CreatureClassInfo.GetKnownSpells` - use `CreatureClassInfo.KnownSpells` instead.

### Fixed
- Fixed null/empty script names not clearing object event scripts.
- Fixed an issue where an invalid script name could be assigned to an object event.
- Fixed a NRE in the `ModuleEvents.OnAcquireItem` event caused by characters failing ELC.
- Fixed a cast exception in the `PlaceableEvents.OnDisturbed` event when the last inventory event was not caused by a creature.
- NwStore: Fixed `WillNotBuyItems`, `WillOnlyBuyItems` lists not removing items, and LINQ functions (ToList/ToArray) not working.
- CreatureLevelInfo: `ClassInfo` now returns the correct creature class.
- ItemPropertyItemMapTable: Fixed some item property values returning valid when they shouldn't be.

## 8193.34.25
https://github.com/nwn-dotnet/Anvil/compare/v8193.34.24...v8193.34.25

Expand Down
4 changes: 2 additions & 2 deletions NWN.Anvil.TestRunner/NWN.Anvil.TestRunner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NWN.Core" Version="8193.34.12" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.5" PrivateAssets="compile" />
<PackageReference Include="NWN.Core" Version="8193.34.15" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.7" PrivateAssets="compile" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions NWN.Anvil.Tests/NWN.Anvil.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NWN.Core" Version="8193.34.12" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.5" PrivateAssets="compile" />
<PackageReference Include="NWN.Core" Version="8193.34.15" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.7" PrivateAssets="compile" />
</ItemGroup>

<ItemGroup>
Expand Down
64 changes: 64 additions & 0 deletions NWN.Anvil.Tests/src/main/API/Objects/NwObjectTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Anvil.API;
Expand Down Expand Up @@ -51,6 +52,69 @@ public async Task QueueCreatureActionIsQueued()
Assert.That(actionExecuted, Is.EqualTo(true));
}

[Test(Description = "Tests if assigning a valid event script correctly updates the event script.")]
[TestCase("my_event")]
[TestCase("")]
[TestCase(null)]
public void SetValidEventScriptCorrectlyUpdatesEventScript(string? script)
{
NwCreature creature = NwCreature.Create(StandardResRef.Creature.nw_bandit001, NwModule.Instance.StartingLocation)!;
Assert.That(creature, Is.Not.Null);

createdTestObjects.Add(creature);

creature.SetEventScript(EventScriptType.CreatureOnSpawnIn, script);

Assert.That(creature.GetEventScript(EventScriptType.CreatureOnSpawnIn), script == null ? Is.EqualTo(string.Empty) : Is.EqualTo(script));
}

[Test(Description = "Tests if assigning an invalid event script correctly throws an exception")]
[TestCase("reallylongscriptname")]
[TestCase("@&^/*7")]
[TestCase(ScriptConstants.GameEventScriptName)]
[TestCase(ScriptConstants.NWNXEventScriptName)]
public void SetInvalidEventScriptCorrectlyThrowsException(string? script)
{
NwCreature creature = NwCreature.Create(StandardResRef.Creature.nw_bandit001, NwModule.Instance.StartingLocation)!;
Assert.That(creature, Is.Not.Null);

createdTestObjects.Add(creature);

Assert.Throws<ArgumentOutOfRangeException>(() =>
{
creature.SetEventScript(EventScriptType.CreatureOnSpawnIn, script);
});
}

[Test(Description = "Tests if attempting to set an event script after subscribing correctly throws an exception.")]
public void SetEventScriptAfterSubscribeCorrectlyThrowsException()
{
NwCreature creature = NwCreature.Create(StandardResRef.Creature.nw_bandit001, NwModule.Instance.StartingLocation)!;
Assert.That(creature, Is.Not.Null);

createdTestObjects.Add(creature);
creature.OnSpawn += _ => {};

Assert.Throws<InvalidOperationException>(() =>
{
creature.SetEventScript(EventScriptType.CreatureOnSpawnIn, null);
});
}

[Test(Description = "Tests if attempting to set an invalid event type correctly throws an exception.")]
public void SetInvalidEventScriptCorrectlyThrowsException()
{
NwCreature creature = NwCreature.Create(StandardResRef.Creature.nw_bandit001, NwModule.Instance.StartingLocation)!;
Assert.That(creature, Is.Not.Null);

createdTestObjects.Add(creature);

Assert.Throws<InvalidOperationException>(() =>
{
creature.SetEventScript(EventScriptType.ModuleOnClientEnter, null);
});
}

[TearDown]
public void CleanupTestObjects()
{
Expand Down
10 changes: 5 additions & 5 deletions NWN.Anvil/NWN.Anvil.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@

<ItemGroup>
<PackageReference Include="LightInject" Version="6.6.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog" Version="5.1.2" />
<PackageReference Include="Paket.Core" Version="7.2.0" PrivateAssets="all" />
<PackageReference Include="NWN.Core" Version="8193.34.12" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.5" PrivateAssets="compile" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.1.3" />
<PackageReference Include="Paket.Core" Version="7.2.1" PrivateAssets="all" />
<PackageReference Include="NWN.Core" Version="8193.34.15" PrivateAssets="compile" />
<PackageReference Include="NWN.Native" Version="8193.34.7" PrivateAssets="compile" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil/src/main/API/Async/NwTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Anvil.API
{
//! ## Examples
//! @import NwTaskExamples.cs
//! @include NwTaskExamples.cs

/// <summary>
/// Asynchronous tasks and helpers for running NWN APIs in an async context.
Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil/src/main/API/EngineStructures/Cassowary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Anvil.API
{
//! ## Examples
//! @import CassowaryExamples.cs
//! @include CassowaryExamples.cs

/// <summary>
/// Represents a Cassowary engine structure.<br/>
Expand Down
10 changes: 8 additions & 2 deletions NWN.Anvil/src/main/API/EngineStructures/Effect.Create.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,19 @@ public static Effect HitPointChangeWhenDying(float hpChangePerRound)
return NWScript.EffectHitPointChangeWhenDying(hpChangePerRound)!;
}

[Obsolete("Use the EffectIconTableEntry overload instead.")]
public static Effect Icon(EffectIcon icon)
{
return NWScript.EffectIcon((int)icon)!;
}

/// <summary>
/// Creates an icon effect. Icons appear in the top right and in the character sheet and examine panels.
/// </summary>
/// <param name="icon">The icon to display.</param>
public static Effect Icon(EffectIcon icon)
public static Effect Icon(EffectIconTableEntry icon)
{
return NWScript.EffectIcon((int)icon)!;
return NWScript.EffectIcon(icon.RowIndex)!;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil/src/main/API/EngineStructures/Effect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Anvil.API
{
//! ## Examples
//! @import EffectExamples.cs
//! @include EffectExamples.cs

/// <summary>
/// Represents an effect engine structure.
Expand Down
2 changes: 1 addition & 1 deletion NWN.Anvil/src/main/API/EngineStructures/ItemProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Anvil.API
{
//! ## Examples
//! @import ItemPropertyExamples.cs
//! @include ItemPropertyExamples.cs

/// <summary>
/// Represents an item property effect engine structure.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ public static partial class ModuleEvents
/// <summary>
/// Triggered whenever an <see cref="NwItem"/> is added to <see cref="NwGameObject"/> inventory.
/// </summary>
/// <remarks>
/// This event fires for all items when a player connects to the server, in addition to item/inventory interactions while playing.<br/>
/// It will also fire for characters failing ELC. In this case, it is recommended to do an early return in your event handler by checking if <see cref="Item"/> is null.
/// </remarks>
[GameEvent(EventScriptType.ModuleOnAcquireItem)]
public sealed class OnAcquireItem : IEvent
{
public OnAcquireItem()
{
// Patch player reference due to a reference bug during client enter context
// See https://github.com/Beamdog/nwn-issues/issues/367
if (AcquiredBy is null && Item.Possessor is NwCreature creature)
if (AcquiredBy is null && Item?.Possessor is NwCreature creature)
{
AcquiredBy = creature;
}
Expand All @@ -43,7 +47,10 @@ public OnAcquireItem()
/// <summary>
/// Gets the <see cref="NwItem"/> that triggered the event.
/// </summary>
public NwItem Item { get; } = NWScript.GetModuleItemAcquired().ToNwObject<NwItem>()!;
/// <remarks>
/// This property will return null when a character fails ELC. It is recommended to do an early exit if this is null.
/// </remarks>
public NwItem? Item { get; } = NWScript.GetModuleItemAcquired().ToNwObject<NwItem>();

NwObject? IEvent.Context => AcquiredBy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public sealed class OnPlayerDeath : IEvent
{
public OnPlayerDeath()
{
Killer = NWScript.GetLastHostileActor(DeadPlayer.ControlledCreature).ToNwObject<NwGameObject>()
?? NWScript.GetLastDamager(DeadPlayer.ControlledCreature).ToNwObject<NwGameObject>();
Killer = NWScript.GetLastHostileActor(DeadPlayer.ControlledCreature).ToNwObject()
?? NWScript.GetLastDamager(DeadPlayer.ControlledCreature).ToNwObject();
}

/// <summary>
Expand All @@ -29,7 +29,7 @@ public OnPlayerDeath()
/// <summary>
/// Gets the <see cref="NwGameObject"/> that caused <see cref="NwPlayer"/> to trigger the event.
/// </summary>
public NwGameObject? Killer { get; }
public NwObject? Killer { get; }

NwObject? IEvent.Context => DeadPlayer.ControlledCreature;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public sealed class OnPlayerGuiEvent : IEvent
/// <summary>
/// Gets the effect icon that was selected. Only valid in <see cref="GuiEventType.EffectIconClick"/> events.
/// </summary>
public EffectIcon EffectIcon => (EffectIcon)integerEventData;
public EffectIconTableEntry EffectIcon => NwGameTables.EffectIconTable[integerEventData];

/// <summary>
/// Gets the object data associated with this GUI event.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public sealed class OnDisturbed : IEvent
public NwItem? DisturbedItem { get; } = NWScript.GetInventoryDisturbItem().ToNwObject<NwItem>();

/// <summary>
/// Gets the <see cref="NwCreature"/> that disturbed <see cref="NwPlaceable"/>.
/// Gets the object that disturbed <see cref="NwPlaceable"/>.
/// </summary>
public NwCreature? Disturber { get; } = NWScript.GetLastDisturbed().ToNwObject<NwCreature>();
public NwGameObject? Disturber { get; } = NWScript.GetLastDisturbed().ToNwObject<NwGameObject>();

/// <summary>
/// Gets the <see cref="InventoryDisturbType"/>.
Expand Down
4 changes: 3 additions & 1 deletion NWN.Anvil/src/main/API/Extensions/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,13 @@ public static void DisposeAll(this IEnumerable<IDisposable?>? disposables)
/// <param name="item">The item to insert.</param>
/// <param name="comparer">A custom comparer to use when comparing the item against elements in the collection.</param>
/// <typeparam name="T">The type of item to insert.</typeparam>
public static void InsertOrdered<T>(this List<T> sortedList, T item, IComparer<T>? comparer = null)
public static int InsertOrdered<T>(this List<T> sortedList, T item, IComparer<T>? comparer = null)
{
int binaryIndex = sortedList.BinarySearch(item, comparer);
int index = binaryIndex < 0 ? ~binaryIndex : binaryIndex;
sortedList.Insert(index, item);

return index;
}

/// <summary>
Expand Down
18 changes: 15 additions & 3 deletions NWN.Anvil/src/main/API/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,27 @@ public static bool IsReservedScriptName(this string scriptName)
return lowerName is ScriptConstants.GameEventScriptName or ScriptConstants.NWNXEventScriptName;
}

public static bool IsValidScriptName(this string scriptName)
public static bool IsValidScriptName(this string? scriptName, bool allowEmpty)
{
if (string.IsNullOrEmpty(scriptName))
{
return allowEmpty;
}

if (scriptName.Length > 16)
{
return false;
}

string lowerName = scriptName.ToLower();
return lowerName != ScriptConstants.GameEventScriptName && lowerName != ScriptConstants.NWNXEventScriptName;
foreach (char c in scriptName)
{
if (!char.IsLetterOrDigit(c) && c != '_' && c != '-')
{
return false;
}
}

return !scriptName.Equals(ScriptConstants.GameEventScriptName, StringComparison.OrdinalIgnoreCase) && !scriptName.Equals(ScriptConstants.NWNXEventScriptName, StringComparison.OrdinalIgnoreCase);
}

/// <inheritdoc cref="ParseFloat(string,float)"/>
Expand Down
Loading

0 comments on commit 54aa4e5

Please sign in to comment.