Slice 2 (WIP): WarriorCone ability + class tests; Warrior path validated
Authored the WarriorCone AbilityDefinition (archetype Cone, dmg 22, range 2.2, ~130deg arc, 22-tick cd) and added it to the gameplay subscene's AbilityDatabase (re-baked). ClassTraitsTests cover the class->ability mapping + the asymmetric seed folds. 348/348. Play-validated the Warrior end-to-end, server==client: AbilityRef=WarriorCone, 4 seeds, eff MaxHP 130 / MoveSpd 5.1 / cone dmg 22 / coneRad 1.13; conns=1 (re-bake handshake intact); zero runtime errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 84b20ca889a744e888c8c3b3b723ec69, type: 3}
|
||||||
|
m_Name: Ability_WarriorCone
|
||||||
|
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.AbilityDefinition
|
||||||
|
Id: 4
|
||||||
|
Archetype: 2
|
||||||
|
DisplayName: Warrior Cone
|
||||||
|
Damage: 22
|
||||||
|
ProjectileSpeed: 0
|
||||||
|
Range: 2.2
|
||||||
|
AutoTargetRange: 0
|
||||||
|
AutoTargetConeDegrees: 65
|
||||||
|
CooldownTicks: 22
|
||||||
|
ProjectilePrefab: {fileID: 0}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4cf5f3ead961b1242b0e3c79de96fa44
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1006,6 +1006,7 @@ MonoBehaviour:
|
|||||||
- {fileID: 11400000, guid: 013954d16c1ff4c1dad82495e38b4657, type: 2}
|
- {fileID: 11400000, guid: 013954d16c1ff4c1dad82495e38b4657, type: 2}
|
||||||
- {fileID: 11400000, guid: b594c2953f8304189b91ca8c96a9d0c4, type: 2}
|
- {fileID: 11400000, guid: b594c2953f8304189b91ca8c96a9d0c4, type: 2}
|
||||||
- {fileID: 11400000, guid: 601a090742e5341cc9ee1f25d215136b, type: 2}
|
- {fileID: 11400000, guid: 601a090742e5341cc9ee1f25d215136b, type: 2}
|
||||||
|
- {fileID: 11400000, guid: 4cf5f3ead961b1242b0e3c79de96fa44, type: 2}
|
||||||
Characters:
|
Characters:
|
||||||
- {fileID: 11400000, guid: e675b529048144a41a2054c729180bce, type: 2}
|
- {fileID: 11400000, guid: e675b529048144a41a2054c729180bce, type: 2}
|
||||||
--- !u!4 &409538539
|
--- !u!4 &409538539
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using ProjectM.Simulation;
|
||||||
|
using Unity.Collections;
|
||||||
|
using Unity.Entities;
|
||||||
|
|
||||||
|
namespace ProjectM.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Slice 2 — the pure class mapping: which Fire ability each class gets, and that the DRG-asymmetric trait
|
||||||
|
/// seeds fold the right direction (Warrior = melee bruiser / tankier / slower; Ranger = ranged / faster /
|
||||||
|
/// squishier + a wider auto-assist co-op hook), all on the reserved <see cref="Tuning.ClassSourceId"/> range.
|
||||||
|
/// </summary>
|
||||||
|
public class ClassTraitsTests
|
||||||
|
{
|
||||||
|
static DynamicBuffer<StatModifier> SeededBuffer(World world, byte classId)
|
||||||
|
{
|
||||||
|
var em = world.EntityManager;
|
||||||
|
var e = em.CreateEntity();
|
||||||
|
em.AddBuffer<StatModifier>(e);
|
||||||
|
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||||
|
ClassTraits.AppendSeeds(classId, e, ecb);
|
||||||
|
ecb.Playback(em);
|
||||||
|
ecb.Dispose();
|
||||||
|
return em.GetBuffer<StatModifier>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AbilityFor_And_Normalize_DefaultToWarrior()
|
||||||
|
{
|
||||||
|
Assert.AreEqual((byte)AbilityId.WarriorCone, ClassTraits.AbilityFor(ClassTraits.WarriorClass));
|
||||||
|
Assert.AreEqual((byte)AbilityId.Primary, ClassTraits.AbilityFor(ClassTraits.RangerClass));
|
||||||
|
Assert.AreEqual((byte)AbilityId.WarriorCone, ClassTraits.AbilityFor(0), "unknown class -> Warrior cone");
|
||||||
|
Assert.AreEqual(ClassTraits.WarriorClass, ClassTraits.Normalize(0));
|
||||||
|
Assert.AreEqual(ClassTraits.WarriorClass, ClassTraits.Normalize(99));
|
||||||
|
Assert.AreEqual(ClassTraits.RangerClass, ClassTraits.Normalize(ClassTraits.RangerClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Warrior_Seeds_Buff_Melee_And_Tankiness_And_Slow()
|
||||||
|
{
|
||||||
|
using var world = new World("ClassTraitsWarrior");
|
||||||
|
var mods = SeededBuffer(world, ClassTraits.WarriorClass);
|
||||||
|
Assert.AreEqual(4, mods.Length, "Warrior seeds 4 trait modifiers.");
|
||||||
|
Assert.Greater(StatMath.Apply(10f, StatTarget.MeleeDamage, mods), 10f, "Warrior hits harder in melee.");
|
||||||
|
Assert.Greater(StatMath.Apply(2.6f, StatTarget.MeleeRange, mods), 2.6f, "Warrior reaches further in melee.");
|
||||||
|
Assert.Less(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Warrior moves slower.");
|
||||||
|
Assert.Greater(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Warrior is tankier.");
|
||||||
|
for (int i = 0; i < mods.Length; i++)
|
||||||
|
Assert.GreaterOrEqual(mods[i].SourceId, Tuning.ClassSourceId, "class seeds use the reserved SourceId range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Ranger_Seeds_Buff_Range_Speed_Assist_And_Leave_Melee_Weak()
|
||||||
|
{
|
||||||
|
using var world = new World("ClassTraitsRanger");
|
||||||
|
var mods = SeededBuffer(world, ClassTraits.RangerClass);
|
||||||
|
Assert.AreEqual(4, mods.Length, "Ranger seeds 4 trait modifiers.");
|
||||||
|
Assert.Greater(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Ranger moves faster.");
|
||||||
|
Assert.Less(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Ranger is squishier.");
|
||||||
|
Assert.Greater(StatMath.Apply(20f, StatTarget.Range, mods), 20f, "Ranger has longer projectile range.");
|
||||||
|
Assert.Greater(StatMath.Apply(0f, StatTarget.AutoTargetRange, mods), 0f, "Ranger has a wider auto-assist (the co-op hook).");
|
||||||
|
Assert.AreEqual(10f, StatMath.Apply(10f, StatTarget.MeleeDamage, mods), 0.001f, "Ranger melee is unbuffed (weaker than the Warrior).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c97bc5f5f2142144f85272e159e3c7b1
|
||||||
Reference in New Issue
Block a user