LANTERN kit into the shipping scene + frame rename (audit H2/M4)

H2 was the audit's sharpest finding: in Game.unity every player spawned
with four ability sockets pointing at SparkIds the baked AbilityDatabase
did not contain, so all four resolved to Damage=0 Range=0 Cooldown=0.
Melee and dash were the only working combat verbs in the built game.
Cause: the 5 LANTERN Sparks were added to GymSub.unity and never to
Gameplay.unity.

- Gameplay.unity's AbilityDatabaseAuthoring now carries all 9 defs (the
  4 legacy ids keep their numbers; Sparks are 5-9) with their effect
  prefabs. Live-verified in Play: sockets now read
  Vortex 8dmg/6range/420cd, Blink 20range/1cd, Hook & Pull
  15dmg/25range/120cd, Light Zone 6dmg/5range/480cd.
- Removed 6 orphaned authoring GameObjects the purge left behind in the
  subscene (StorageSpawner, StructureCatalog, ItemDatabase,
  SpitterProjectileConfig, BoonCatalog, MetaCatalog) and the RoomDressing
  object in Game.unity — the latter is what scattered 47 Synty desert
  props into the seabed murk.
- Deleted 4 now-unreferenced prefabs: EnemySpit, Pylon, Storage, Wall.
- Frame rename (M4): FrameKind.Warrior/Ranger -> Bathynaut/Harpooner,
  93 identifier sites. Byte values pinned (2/3), so no ghost-hash or save
  impact. The menu said "Warrior"/"Ranger" to players three weeks after
  the frames were renamed in design.
- Menu now reads LANTERN / "Light is territory — co-op descent" instead
  of "PROJECT M" / "Frontier colony — co-op" (the Awakening-Engine
  tagline, two directions stale).
- Removed the "Replay Tutorial" button and the Settings ONBOARDING
  section: both drove coach-marks DR-051 deleted. The settings fields
  still round-trip so existing settings files load unchanged.

All four project scenes + all prefabs verified free of missing scripts.
Server measured at 59.6 ticks/s against a 60 Hz target. 295/295 green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-07 13:11:58 -07:00
parent 62e48a3b0b
commit 9f61f7c6fe
28 changed files with 88 additions and 1465 deletions
-100
View File
@@ -1123,105 +1123,6 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1333170161
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1333170163}
- component: {fileID: 1333170162}
m_Layer: 0
m_Name: RoomDressing
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1333170162
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1333170161}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4ef612b567d6f6746bc03f764274740e, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Client::ProjectM.Client.RoomDressingConfig
Enabled: 1
CountPerRoom: 26
ScaleMin: 0.85
ScaleMax: 1.35
Meadow:
- {fileID: 3757109599224033816, guid: 60467653c9024a94cbe4863e1b401660, type: 3}
- {fileID: 1557974530457926728, guid: d74b9ad70f26c1c41805b672a71665b0, type: 3}
- {fileID: 5214937767286086917, guid: f4c1ab01cce3344498755643a1be1e5a, type: 3}
- {fileID: 2186473713617367126, guid: d6538b1be0012ec49affc54b4b0b8f19, type: 3}
- {fileID: 1074864049481174882, guid: 8e2a923736393f34d9d8dc6a0d5baf44, type: 3}
- {fileID: 1511162409591480987, guid: 207b689f475fbcc48bf39ca3fecca461, type: 3}
- {fileID: 7158316201231779819, guid: 5a94592405aec68418c8c69881c5a3b0, type: 3}
- {fileID: 5376390175986146221, guid: a6953db8e1209e74b8141f1e9847b94b, type: 3}
- {fileID: 1118155114131449006, guid: e1b4f5f50eebd6441919aab5ea3b042f, type: 3}
- {fileID: 8596010870747751422, guid: f3f0fef6f816f4641856a0db4dfbb905, type: 3}
- {fileID: 1346982405202136, guid: 09a3b44b8937d6245b39d930062109c6, type: 3}
- {fileID: 1325243728563266, guid: 720c6591b996f3b45b844519425924b9, type: 3}
Arid:
- {fileID: 2343585175475211231, guid: 82b24fde941b791499b3e3df77f33994, type: 3}
- {fileID: 5355830441712902000, guid: f7e55accb0f3ef74ebf6f2b0423ca2b7, type: 3}
- {fileID: 6243260667707658037, guid: c6b3f3875f0986d49a0c47cbd022b0bf, type: 3}
- {fileID: 1897731639152372492, guid: 72469d6301a36f541917475d91c3d003, type: 3}
- {fileID: 7399423978015975178, guid: 2b71e23fcf27f6147b0e6b05477f129e, type: 3}
- {fileID: 8429375587787154361, guid: 1701b13a21c3cee4abfdc7cf68253a01, type: 3}
- {fileID: 8812702112283937109, guid: 99d003c03fa874f4dafda35e5d1ecde5, type: 3}
- {fileID: 530501058922827164, guid: 595d7bac85c68234abd41625ae3db0cd, type: 3}
- {fileID: 6850435770556105135, guid: 66d4f7c006b77084da3929add6d06f24, type: 3}
- {fileID: 8217716403657413284, guid: 9df62898e2ddbbd4b9df38751d895ba0, type: 3}
- {fileID: 9189062589720884796, guid: 2f1d23f56aee799459168baa6c36053c, type: 3}
- {fileID: 7897640328251657048, guid: 041cd6c93207bec4b9bef2390aa9047f, type: 3}
- {fileID: 4168235972698704609, guid: a29bb4ac881c18d4dbfda67c2ff21091, type: 3}
- {fileID: 2660068605479700378, guid: 5609edadd6d8f3744b3f17d21a3a507f, type: 3}
Cavern:
- {fileID: 5376390175986146221, guid: a6953db8e1209e74b8141f1e9847b94b, type: 3}
- {fileID: 1118155114131449006, guid: e1b4f5f50eebd6441919aab5ea3b042f, type: 3}
- {fileID: 1548467455464118, guid: a66fcd4b0c95c3c4f8a2e3ec71b821fd, type: 3}
- {fileID: 1219693987300432, guid: 2802a8bdb7ea3354a8b0be8bfb9e7ac9, type: 3}
- {fileID: 1956064514463986, guid: b200516e65de5a142a3bbadb73cd77e4, type: 3}
- {fileID: 1976401696516608, guid: 7aec7d7b6b4e5f24f832c33028ee90d9, type: 3}
- {fileID: 1218948445974146, guid: 7f4082e70edb70e4b83b1d67eb74deb5, type: 3}
- {fileID: 1296379715616498, guid: 23aa7813617e5be4983e5df6b139f5ea, type: 3}
- {fileID: 1475996404134592, guid: c4be778793f575b42b8d942b78462284, type: 3}
- {fileID: 1159367070492942, guid: ac42f59b9c44c274b9612f7df5333cf3, type: 3}
- {fileID: 1804667845376260, guid: 4005b9a03d8625b4990b7a567bf6faa1, type: 3}
Blight:
- {fileID: 1804667845376260, guid: 4005b9a03d8625b4990b7a567bf6faa1, type: 3}
- {fileID: 1361614101361290, guid: d3b497db883149045a9c1218adca475a, type: 3}
- {fileID: 1364780636854694, guid: d6f6b930859540e44aa1b08dc38756a3, type: 3}
- {fileID: 1272498397077028, guid: 66e7fae4a94b7534da72db0198a0f740, type: 3}
- {fileID: 1490281888066316, guid: df92770844ac44c4ab92f00167bffc4c, type: 3}
- {fileID: 1154308530469040, guid: 2c1b8ba858adad2478af52d208187ae6, type: 3}
- {fileID: 1436310706135902, guid: d490d5805a8f22c449470acc5c2bbf6f, type: 3}
- {fileID: 1552408322253738, guid: c104bd949dbb87644ab3fe86ab934293, type: 3}
- {fileID: 6243260667707658037, guid: c6b3f3875f0986d49a0c47cbd022b0bf, type: 3}
- {fileID: 4168235972698704609, guid: a29bb4ac881c18d4dbfda67c2ff21091, type: 3}
--- !u!4 &1333170163
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1333170161}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1501947282 --- !u!1 &1501947282
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1696,5 +1597,4 @@ SceneRoots:
- {fileID: 70737666} - {fileID: 70737666}
- {fileID: 1276835916} - {fileID: 1276835916}
- {fileID: 1007206783} - {fileID: 1007206783}
- {fileID: 1333170163}
- {fileID: 1643709738} - {fileID: 1643709738}
-180
View File
@@ -1,180 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &803404312977859260
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 544753127400808733}
- component: {fileID: 8071270979468917903}
- component: {fileID: 4362678855125273864}
m_Layer: 0
m_Name: Model
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &544753127400808733
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803404312977859260}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.4, z: 0}
m_LocalScale: {x: 1.3, y: 1.3, z: 1.3}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3572766465862231365}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8071270979468917903
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803404312977859260}
m_Mesh: {fileID: 4300000, guid: a52e2d101bf32694d9012060774e97fd, type: 3}
--- !u!23 &4362678855125273864
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803404312977859260}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 71e41e43b459a244abaf5acca76b89ee, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &3885353946372160549
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3572766465862231365}
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 6800460489587750746}
m_Layer: 0
m_Name: EnemySpit
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3572766465862231365
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 544753127400808733}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9053853372340598254
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
--- !u!114 &6834786618115927220
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
UseSingleBaseline: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
DefaultGhostMode: 0
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 1
MaxSendRate: 0
prefabId:
--- !u!114 &6800460489587750746
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff79c8fbcacb8c34faad37d59836b5ac, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.EnemyProjectileAuthoring
Speed: 11
Damage: 8
Range: 16
@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 8a13ef653e5266741b0896084f74038f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
-201
View File
@@ -1,201 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &366348267144353778
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5779750859554542924}
- component: {fileID: 7170592853470682160}
- component: {fileID: 738253848842457672}
m_Layer: 0
m_Name: Model
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5779750859554542924
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 366348267144353778}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.4, y: 3, z: 1.4}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3572766465862231365}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &7170592853470682160
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 366348267144353778}
m_Mesh: {fileID: 4300000, guid: a52e2d101bf32694d9012060774e97fd, type: 3}
--- !u!23 &738253848842457672
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 366348267144353778}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 53c360a5b4f92c04caad3273e9bb5bef, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &3885353946372160549
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3572766465862231365}
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 7685488391646220227}
- component: {fileID: 1225369404710843925}
m_Layer: 9
m_Name: Pylon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3572766465862231365
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5779750859554542924}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9053853372340598254
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
--- !u!114 &6834786618115927220
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
UseSingleBaseline: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
DefaultGhostMode: 0
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 1
MaxSendRate: 0
prefabId:
--- !u!114 &7685488391646220227
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3f03349205fb1fe43bf6aaff14fce0b7, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.StructureAuthoring
Kind: 6
MaxHp: 150
--- !u!65 &1225369404710843925
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1.6, y: 2, z: 1.6}
m_Center: {x: 0, y: 1, z: 0}
@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 7d0637ef90f120a4c9e2ba637dfc00af
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
-360
View File
@@ -1,360 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3885353946372160549
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3572766465862231365}
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 1499754650316338861}
m_Layer: 0
m_Name: Storage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3572766465862231365
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7754515490259982108}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9053853372340598254
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
--- !u!114 &6834786618115927220
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
UseSingleBaseline: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
DefaultGhostMode: 0
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 1
MaxSendRate: 0
prefabId:
--- !u!114 &1499754650316338861
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8cc6285a9b8958a47a61a07550b7f792, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.SharedStorageContainerAuthoring
InteractRadius: 2
--- !u!1 &4342778333059441971
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8611665802642757146}
- component: {fileID: 6598987389968571053}
- component: {fileID: 1872235609085155134}
m_Layer: 0
m_Name: SM_Prop_Chest_01_Latch
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8611665802642757146
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4342778333059441971}
serializedVersion: 2
m_LocalRotation: {x: -0.027002363, y: 0, z: -0, w: 0.9996354}
m_LocalPosition: {x: -4.3326118e-10, y: 0.055391826, z: 0.53040093}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6847878535001934851}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6598987389968571053
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4342778333059441971}
m_Mesh: {fileID: 4300004, guid: 2b3d40ab397966c46866a5ae4769602b, type: 3}
--- !u!23 &1872235609085155134
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4342778333059441971}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 71e41e43b459a244abaf5acca76b89ee, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &4346114154671337569
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6847878535001934851}
- component: {fileID: 5242650844534680107}
- component: {fileID: 1017291060828274944}
m_Layer: 0
m_Name: SM_Prop_Chest_01_Lid
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6847878535001934851
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4346114154671337569}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 4.3326118e-10, y: 0.32239768, z: -0.25041196}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8611665802642757146}
m_Father: {fileID: 7754515490259982108}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &5242650844534680107
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4346114154671337569}
m_Mesh: {fileID: 4300002, guid: 2b3d40ab397966c46866a5ae4769602b, type: 3}
--- !u!23 &1017291060828274944
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4346114154671337569}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 71e41e43b459a244abaf5acca76b89ee, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &4577827258028593592
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7754515490259982108}
- component: {fileID: 5772852026247014718}
- component: {fileID: 8850822068282186422}
m_Layer: 0
m_Name: Model
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7754515490259982108
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4577827258028593592}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.5, y: 1.5, z: 1.5}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6847878535001934851}
m_Father: {fileID: 3572766465862231365}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &5772852026247014718
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4577827258028593592}
m_Mesh: {fileID: 4300000, guid: 2b3d40ab397966c46866a5ae4769602b, type: 3}
--- !u!23 &8850822068282186422
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4577827258028593592}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 71e41e43b459a244abaf5acca76b89ee, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 6636e906a2ac46345889f5517658be67
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
-202
View File
@@ -1,202 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &551144932704427983
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7825746404949508119}
- component: {fileID: 4477892480858664848}
- component: {fileID: 4489297219945009455}
m_Layer: 0
m_Name: Model
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7825746404949508119
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 551144932704427983}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3572766465862231365}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &4477892480858664848
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 551144932704427983}
m_Mesh: {fileID: 4754861833707048916, guid: d5f5c8f8a3300c249a861a444f85e05d, type: 3}
--- !u!23 &4489297219945009455
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 551144932704427983}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 2a95f9ff80948c643a57b9e94a98eb3f, type: 2}
- {fileID: 2100000, guid: 53c360a5b4f92c04caad3273e9bb5bef, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &3885353946372160549
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3572766465862231365}
- component: {fileID: 9053853372340598254}
- component: {fileID: 6834786618115927220}
- component: {fileID: 8793146551006314905}
- component: {fileID: 7779358222264100756}
m_Layer: 9
m_Name: Wall
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3572766465862231365
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7825746404949508119}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9053853372340598254
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Entities.Hybrid::Unity.Entities.Hybrid.Baking.LinkedEntityGroupAuthoring
--- !u!114 &6834786618115927220
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.NetCode.Authoring.Hybrid::Unity.NetCode.GhostAuthoringComponent
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
UseSingleBaseline: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
DefaultGhostMode: 0
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 1
MaxSendRate: 0
prefabId:
--- !u!114 &8793146551006314905
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3f03349205fb1fe43bf6aaff14fce0b7, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.StructureAuthoring
Kind: 5
MaxHp: 150
--- !u!65 &7779358222264100756
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3885353946372160549}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 0.58636487, y: 0.600076, z: 0.9781774}
m_Center: {x: 0, y: 0, z: 0.083845735}
-7
View File
@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 1e321aea244cc484f99c1cdd68cb01c4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -6,8 +6,8 @@ using UnityEngine.InputSystem;
namespace ProjectM.Client namespace ProjectM.Client
{ {
/// <summary> /// <summary>
/// EDITOR-ONLY dev hotkey to switch the local player's class while playtesting: <b>F1 = Warrior</b>, /// EDITOR-ONLY dev hotkey to switch the local player's class while playtesting: <b>F1 = Bathynaut</b>,
/// <b>F2 = Ranger</b>. The <see cref="DebugOverlay"/>'s Class buttons only live in the DevSandbox scene, so this /// <b>F2 = Harpooner</b>. The <see cref="DebugOverlay"/>'s Class buttons only live in the DevSandbox scene, so this
/// keybind makes the swap reachable in the real menu -> Game flow too (no scene wiring needed). It enqueues the /// keybind makes the swap reachable in the real menu -> Game flow too (no scene wiring needed). It enqueues the
/// SAME authoritative <see cref="ProjectM.Simulation.DebugCommandRequest"/> (DebugOp.SetClass) the overlay buttons /// SAME authoritative <see cref="ProjectM.Simulation.DebugCommandRequest"/> (DebugOp.SetClass) the overlay buttons
/// do, via <see cref="DebugCommandSendSystem"/> — the server strips/re-seeds the class traits, swaps the Fire /// do, via <see cref="DebugCommandSendSystem"/> — the server strips/re-seeds the class traits, swaps the Fire
@@ -24,9 +24,9 @@ namespace ProjectM.Client
return; return;
if (kb.f1Key.wasPressedThisFrame) if (kb.f1Key.wasPressedThisFrame)
DebugCommandSendSystem.SetWarrior(); DebugCommandSendSystem.SetBathynaut();
else if (kb.f2Key.wasPressedThisFrame) else if (kb.f2Key.wasPressedThisFrame)
DebugCommandSendSystem.SetRanger(); DebugCommandSendSystem.SetHarpooner();
} }
} }
} }
@@ -39,8 +39,8 @@ namespace ProjectM.Client
public static void SetTuning(byte knob, float value) => Send(DebugOp.SetTuning, knob, Mathf.RoundToInt(value * 1000f)); public static void SetTuning(byte knob, float value) => Send(DebugOp.SetTuning, knob, Mathf.RoundToInt(value * 1000f));
/// <summary>Swap the sender's class to <paramref name="classId"/> (a <see cref="ProjectM.Simulation.FrameKind"/> byte); server-authoritative (class-switch dev tool).</summary> /// <summary>Swap the sender's class to <paramref name="classId"/> (a <see cref="ProjectM.Simulation.FrameKind"/> byte); server-authoritative (class-switch dev tool).</summary>
public static void SetClass(byte classId) => Send(DebugOp.SetClass, classId); public static void SetClass(byte classId) => Send(DebugOp.SetClass, classId);
public static void SetWarrior() => SetClass(ClassTraits.WarriorClass); public static void SetBathynaut() => SetClass(ClassTraits.BathynautFrame);
public static void SetRanger() => SetClass(ClassTraits.RangerClass); public static void SetHarpooner() => SetClass(ClassTraits.HarpoonerFrame);
/// <summary>GYM: spawn enemy KIND (a <see cref="ProjectM.Simulation.GymEnemyKind"/> byte) near the sender, count times.</summary> /// <summary>GYM: spawn enemy KIND (a <see cref="ProjectM.Simulation.GymEnemyKind"/> byte) near the sender, count times.</summary>
public static void SpawnEnemy(byte kind, int count = 1) => Send(DebugOp.SpawnEnemy, kind, count); public static void SpawnEnemy(byte kind, int count = 1) => Send(DebugOp.SpawnEnemy, kind, count);
@@ -69,8 +69,8 @@ namespace ProjectM.Client
GUILayout.Space(6); GUILayout.Space(6);
GUILayout.Label("- Class (F1/F2) -"); GUILayout.Label("- Class (F1/F2) -");
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
if (GUILayout.Button("Warrior")) DebugCommandSendSystem.SetWarrior(); if (GUILayout.Button("Bathynaut")) DebugCommandSendSystem.SetBathynaut();
if (GUILayout.Button("Ranger")) DebugCommandSendSystem.SetRanger(); if (GUILayout.Button("Harpooner")) DebugCommandSendSystem.SetHarpooner();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.Space(6); GUILayout.Space(6);
@@ -68,8 +68,8 @@ namespace ProjectM.Client
switch (idx) switch (idx)
{ {
case 0: // Controls (chosen class) case 0: // Controls (chosen class)
bool ranger = WorldLauncher.SelectedClass == (byte)FrameKind.Ranger; bool ranger = WorldLauncher.SelectedClass == (byte)FrameKind.Harpooner;
Head(c, ranger ? "CLASS: Ranger (ranged anchor)" : "CLASS: Warrior (melee anchor)"); Head(c, ranger ? "CLASS: Harpooner (ranged anchor)" : "CLASS: Bathynaut (melee anchor)");
Body(c, "Move — WASD / Left Stick"); Body(c, "Move — WASD / Left Stick");
Body(c, "Aim — Mouse cursor / Right Stick"); Body(c, "Aim — Mouse cursor / Right Stick");
Body(c, "Attack — LMB / X (3-hit melee combo — the finisher hits hard)"); Body(c, "Attack — LMB / X (3-hit melee combo — the finisher hits hard)");
@@ -78,8 +78,8 @@ namespace ProjectM.Client
void BuildMain(VisualElement root) void BuildMain(VisualElement root)
{ {
_mainPanel = MenuUi.FullScreenRoot(true); _mainPanel = MenuUi.FullScreenRoot(true);
var card = MenuUi.Card("PROJECT M"); var card = MenuUi.Card("LANTERN");
card.Add(MenuUi.Caption("Frontier colony — co-op")); card.Add(MenuUi.Caption("Light is territory — co-op descent"));
// Why the last session ended (connection watchdog / bad join address) — shown once, then cleared. // Why the last session ended (connection watchdog / bad join address) — shown once, then cleared.
if (!string.IsNullOrEmpty(SessionEnd.Reason)) if (!string.IsNullOrEmpty(SessionEnd.Reason))
{ {
@@ -91,7 +91,7 @@ namespace ProjectM.Client
card.Add(reason); card.Add(reason);
} }
// Slice 2: class picker -> sets WorldLauncher.SelectedClass for the next session (Warrior melee / Ranger ranged). // Slice 2: class picker -> sets WorldLauncher.SelectedClass for the next session (Bathynaut melee / Harpooner ranged).
_classLabel = new Label(ClassName(WorldLauncher.SelectedClass)); _classLabel = new Label(ClassName(WorldLauncher.SelectedClass));
_classLabel.style.unityTextAlign = TextAnchor.MiddleCenter; _classLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
_classLabel.style.marginTop = 6; _classLabel.style.marginBottom = 2; _classLabel.style.marginTop = 6; _classLabel.style.marginBottom = 2;
@@ -99,8 +99,8 @@ namespace ProjectM.Client
var classRow = new VisualElement(); var classRow = new VisualElement();
classRow.style.flexDirection = FlexDirection.Row; classRow.style.flexDirection = FlexDirection.Row;
classRow.style.justifyContent = Justify.Center; classRow.style.justifyContent = Justify.Center;
classRow.Add(MenuUi.Button("Warrior", () => SelectClass((byte)FrameKind.Warrior))); classRow.Add(MenuUi.Button("Bathynaut", () => SelectClass((byte)FrameKind.Bathynaut)));
classRow.Add(MenuUi.Button("Ranger", () => SelectClass((byte)FrameKind.Ranger))); classRow.Add(MenuUi.Button("Harpooner", () => SelectClass((byte)FrameKind.Harpooner)));
card.Add(classRow); card.Add(classRow);
card.Add(MenuUi.Button("Single Player", () => Launch(SessionMode.Single, false))); card.Add(MenuUi.Button("Single Player", () => Launch(SessionMode.Single, false)));
@@ -118,18 +118,9 @@ namespace ProjectM.Client
card.Add(MenuUi.Button("Settings", ShowSettings)); card.Add(MenuUi.Button("Settings", ShowSettings));
card.Add(MenuUi.Button("How to Play", ShowHowToPlay)); card.Add(MenuUi.Button("How to Play", ShowHowToPlay));
// Re-arm the first-run coach-marks (clears the client-local completed-step mask). The next session // 2026-08-07 audit purge: the "Replay Tutorial" button re-armed first-run coach-marks whose system
// replays them; the How-to-Play card stays available regardless. // DR-051 deleted — it wrote OnboardingMask/TutorialHints that nothing reads. Removed rather than left
Button replayBtn = null; // as a button that visibly does nothing. The How-to-Play card above is the real reference.
replayBtn = MenuUi.Button("Replay Tutorial", () =>
{
var s = SettingsService.Current;
s.OnboardingMask = 0;
s.TutorialHints = 1;
SettingsService.Save(s);
if (replayBtn != null) replayBtn.text = "Tutorial armed ✓";
});
card.Add(replayBtn);
card.Add(MenuUi.Button("Quit", Quit)); card.Add(MenuUi.Button("Quit", Quit));
@@ -149,7 +140,7 @@ namespace ProjectM.Client
if (_classLabel != null) _classLabel.text = ClassName(classId); if (_classLabel != null) _classLabel.text = ClassName(classId);
} }
static string ClassName(byte classId) => classId == (byte)FrameKind.Ranger ? "CLASS: Ranger (ranged)" : "CLASS: Warrior (melee)"; static string ClassName(byte classId) => classId == (byte)FrameKind.Harpooner ? "CLASS: Harpooner (ranged)" : "CLASS: Bathynaut (melee)";
void ShowSettings() void ShowSettings()
{ {
@@ -59,22 +59,9 @@ namespace ProjectM.Client
card.Add(VolumeRow("Music", working.Music, v => { working.Music = v; GameVolume.Music = v; })); card.Add(VolumeRow("Music", working.Music, v => { working.Music = v; GameVolume.Music = v; }));
card.Add(VolumeRow("SFX", working.Sfx, v => { working.Sfx = v; GameVolume.Sfx = v; })); card.Add(VolumeRow("SFX", working.Sfx, v => { working.Sfx = v; GameVolume.Sfx = v; }));
// ---------------- Onboarding ---------------- // 2026-08-07 audit purge: the ONBOARDING section (Tutorial Hints + the dev Force-Each-Launch toggle)
card.Add(MenuUi.Caption("— ONBOARDING —")); // drove coach-marks DR-051 deleted. The settings still round-trip the fields so an existing settings
string[] onoff = { "Off", "On" }; // file loads unchanged — they just no longer pretend to be a control.
card.Add(CycleRow("Tutorial Hints",
() => onoff[Mathf.Clamp(working.TutorialHints, 0, 1)],
dir => working.TutorialHints = Wrap(working.TutorialHints + dir, 2)));
// DEV: forces the first-run coach-marks to replay fresh on every launch (wipes the completed-step mask at
// each boot — see SettingsService.Boot). Off = normal once-only first-run behaviour.
#if UNITY_EDITOR // D7: dev-only onboarding replay toggle — hidden from the public demo Settings so a player can't lock themselves into permanent tutorial
card.Add(CycleRow("Force Each Launch (Dev)",
() => onoff[Mathf.Clamp(working.ForceOnboardingEachLaunch, 0, 1)],
dir => working.ForceOnboardingEachLaunch = Wrap(working.ForceOnboardingEachLaunch + dir, 2)));
#endif
// ---------------- Buttons ---------------- // ---------------- Buttons ----------------
var apply = MenuUi.Button("Apply", () => SettingsService.SaveAndApply(working)); var apply = MenuUi.Button("Apply", () => SettingsService.SaveAndApply(working));
@@ -29,7 +29,7 @@ namespace ProjectM.Client
public static bool Busy { get; private set; } public static bool Busy { get; private set; }
/// <summary>Slice 2: the frame chosen in the menu (a FrameKind byte), seeded into the client world at session start.</summary> /// <summary>Slice 2: the frame chosen in the menu (a FrameKind byte), seeded into the client world at session start.</summary>
public static byte SelectedClass = (byte)FrameKind.Warrior; public static byte SelectedClass = (byte)FrameKind.Bathynaut;
/// <summary>The mode of the most recently started session — the HUD's outcome banner branches on it /// <summary>The mode of the most recently started session — the HUD's outcome banner branches on it
/// (single: PLAY AGAIN restarts; co-op: the honest exit is a clean teardown for everyone).</summary> /// (single: PLAY AGAIN restarts; co-op: the honest exit is a clean teardown for everyone).</summary>
@@ -72,7 +72,7 @@ namespace ProjectM.Server
// Slice 2 -> LANTERN: seed the chosen frame on the just-instantiated player. The 4-socket Spark // Slice 2 -> LANTERN: seed the chosen frame on the just-instantiated player. The 4-socket Spark
// loadout IS the ability model (the legacy single-AbilityRef path is deleted); the DRG-asymmetry // loadout IS the ability model (the legacy single-AbilityRef path is deleted); the DRG-asymmetry
// traits ride permanent StatModifiers (CharacterStatsRef stays Default -> deltas replicate via the // traits ride permanent StatModifiers (CharacterStatsRef stays Default -> deltas replicate via the
// OwnerSendType.All buffer). 0 -> Warrior/Bathynaut. // OwnerSendType.All buffer). 0 -> Bathynaut/Bathynaut.
byte classId = ClassTraits.Normalize(goReq.ValueRO.ClassId); byte classId = ClassTraits.Normalize(goReq.ValueRO.ClassId);
ClassTraits.AppendSeeds(classId, player, ecb); ClassTraits.AppendSeeds(classId, player, ecb);
// Expedition redesign: the server-only class anchor the meta systems key on (born-correct meta // Expedition redesign: the server-only class anchor the meta systems key on (born-correct meta
@@ -10,7 +10,7 @@ namespace ProjectM.Simulation
/// </summary> /// </summary>
public struct ClassSelectRequest : IRpcCommand public struct ClassSelectRequest : IRpcCommand
{ {
/// <summary>Requested class id (0/unknown → Warrior via ClassTraits.Normalize).</summary> /// <summary>Requested class id (0/unknown → Bathynaut via ClassTraits.Normalize).</summary>
public byte ClassId; public byte ClassId;
} }
} }
@@ -7,7 +7,7 @@ namespace ProjectM.Simulation
/// singleton by the menu / WorldLauncher before going in-game. <see cref="GoInGameRequest"/> picks it up /// singleton by the menu / WorldLauncher before going in-game. <see cref="GoInGameRequest"/> picks it up
/// (GoInGameClientSystem) so the server seeds the right class at spawn. NOT replicated — it is client-local /// (GoInGameClientSystem) so the server seeds the right class at spawn. NOT replicated — it is client-local
/// intent; the class travels to the server via the RPC, then back to all clients via the seeded StatModifiers + /// intent; the class travels to the server via the RPC, then back to all clients via the seeded StatModifiers +
/// the replicated AbilityRef. 0 = unset (the server defaults to Warrior). /// the replicated AbilityRef. 0 = unset (the server defaults to Bathynaut).
/// </summary> /// </summary>
public struct ClassSelection : IComponentData public struct ClassSelection : IComponentData
{ {
@@ -26,7 +26,7 @@ namespace ProjectM.Simulation
/// <summary>Heal/down-clamp a LIVING player's Current to the new class's full max (blob base folded with the /// <summary>Heal/down-clamp a LIVING player's Current to the new class's full max (blob base folded with the
/// just-reseeded <paramref name="mods"/>, like StatRecomputeSystem). Doubles as the down-clamp when the new /// just-reseeded <paramref name="mods"/>, like StatRecomputeSystem). Doubles as the down-clamp when the new
/// class's max is lower (Warrior +30 HP vs Ranger -15%). No-op on a corpse (Current&lt;=0) — respawn refills.</summary> /// class's max is lower (Bathynaut +30 HP vs Harpooner -15%). No-op on a corpse (Current&lt;=0) — respawn refills.</summary>
public static void HealClamp(ref Health health, float baseMaxHealth, DynamicBuffer<StatModifier> mods) public static void HealClamp(ref Health health, float baseMaxHealth, DynamicBuffer<StatModifier> mods)
{ {
if (health.Current > 0f) if (health.Current > 0f)
@@ -11,11 +11,11 @@ namespace ProjectM.Simulation
/// <para> /// <para>
/// Trait deltas seed onto the <see cref=\"FrameKind.Default\"/> character (no per-class blob row needed — the /// Trait deltas seed onto the <see cref=\"FrameKind.Default\"/> character (no per-class blob row needed — the
/// deltas ride the replicated StatModifier buffer, OwnerSendType.All, so the owning client folds the correct /// deltas ride the replicated StatModifier buffer, OwnerSendType.All, so the owning client folds the correct
/// EffectiveCharacterStats). The DRG-asymmetry (operator-locked): <b>Warrior</b> = melee bruiser (tankier, /// EffectiveCharacterStats). The DRG-asymmetry (operator-locked): <b>Bathynaut</b> = melee bruiser (tankier,
/// slower, harder + longer-reach melee via MeleeDamage/MeleeRange); <b>Ranger</b> = ranged anchor (faster, /// slower, harder + longer-reach melee via MeleeDamage/MeleeRange); <b>Harpooner</b> = ranged anchor (faster,
/// squishier, longer projectile range + a wider auto-target assist — the co-op synergy hook the Warrior's /// squishier, longer projectile range + a wider auto-target assist — the co-op synergy hook the Bathynaut's
/// knockback feeds). The Warrior's Fire = the aim-directed cone (<see cref="AbilityId.WarriorCone"/>); the /// knockback feeds). The Bathynaut's Fire = the aim-directed cone (<see cref="AbilityId.WarriorCone"/>); the
/// Ranger's Fire = the default projectile (<see cref="AbilityId.Primary"/>). /// Harpooner's Fire = the default projectile (<see cref="AbilityId.Primary"/>).
/// </para> /// </para>
/// <para> /// <para>
/// <see cref="Reapply"/> swaps an already-spawned player's class IN PLACE (strip the old class seeds, re-seed /// <see cref="Reapply"/> swaps an already-spawned player's class IN PLACE (strip the old class seeds, re-seed
@@ -26,28 +26,28 @@ namespace ProjectM.Simulation
/// </summary> /// </summary>
public static class ClassTraits public static class ClassTraits
{ {
public const byte WarriorClass = (byte)FrameKind.Warrior; public const byte BathynautFrame = (byte)FrameKind.Bathynaut;
public const byte RangerClass = (byte)FrameKind.Ranger; public const byte HarpoonerFrame = (byte)FrameKind.Harpooner;
/// <summary>How many trait modifiers a class seeds (each on a distinct SourceId at ClassSourceId + i).</summary> /// <summary>How many trait modifiers a class seeds (each on a distinct SourceId at ClassSourceId + i).</summary>
public const int ClassSeedCount = 4; public const int ClassSeedCount = 4;
/// <summary>Normalize a wire ClassId to a known class (0 / unknown -> Warrior).</summary> /// <summary>Normalize a wire ClassId to a known class (0 / unknown -> Bathynaut).</summary>
public static byte Normalize(byte classId) => classId == RangerClass ? RangerClass : WarriorClass; public static byte Normalize(byte classId) => classId == HarpoonerFrame ? HarpoonerFrame : BathynautFrame;
/// <summary>The Fire-slot ability id for a class (Warrior = cone, Ranger = the default projectile).</summary> /// <summary>The Fire-slot ability id for a class (Bathynaut = cone, Harpooner = the default projectile).</summary>
/// <summary>The class a Fire-slot ability id implies — the exact inverse of <see cref="AbilityFor"/> (Ranger /// <summary>The class a Fire-slot ability id implies — the exact inverse of <see cref="AbilityFor"/> (Harpooner
/// iff Primary). Lets the CLIENT derive the local class from the replicated <see cref="AbilityRef"/> (tracks /// iff Primary). Lets the CLIENT derive the local class from the replicated <see cref="AbilityRef"/> (tracks
/// the dev class-switch, unlike the menu's ClassSelection static; PlayerClass itself is server-only).</summary> /// the dev class-switch, unlike the menu's ClassSelection static; PlayerClass itself is server-only).</summary>
/// <summary>Default 4-socket Spark loadout per frame (Harpooner = the Ranger slot, line-and-iron; Bathynaut = /// <summary>Default 4-socket Spark loadout per frame (Harpooner = the Harpooner slot, line-and-iron; Bathynaut =
/// the Warrior slot, anchor-and-crash). Tunable; drives the gym's per-frame default sockets (Build Spec step 5).</summary> /// the Bathynaut slot, anchor-and-crash). Tunable; drives the gym's per-frame default sockets (Build Spec step 5).</summary>
public static void FrameLoadout(byte classId, out byte s0, out byte s1, out byte s2, out byte s3) public static void FrameLoadout(byte classId, out byte s0, out byte s1, out byte s2, out byte s3)
{ {
if (classId == RangerClass) // Harpooner: reel primary + mobility + skillshots if (classId == HarpoonerFrame) // Harpooner: reel primary + mobility + skillshots
{ {
s0 = (byte)AbilityId.HookPull; s1 = (byte)AbilityId.Blink; s2 = (byte)AbilityId.DecoyWisp; s3 = (byte)AbilityId.LightZone; s0 = (byte)AbilityId.HookPull; s1 = (byte)AbilityId.Blink; s2 = (byte)AbilityId.DecoyWisp; s3 = (byte)AbilityId.LightZone;
} }
@@ -70,7 +70,7 @@ namespace ProjectM.Simulation
static void Seeds(byte classId, Span<StatModifier> seeds) static void Seeds(byte classId, Span<StatModifier> seeds)
{ {
uint src = Tuning.ClassSourceId; uint src = Tuning.ClassSourceId;
if (classId == RangerClass) if (classId == HarpoonerFrame)
{ {
seeds[0] = new StatModifier { Target = (byte)StatTarget.MoveSpeed, Op = (byte)ModOp.PercentMult, Value = 0.15f, SourceId = src }; seeds[0] = new StatModifier { Target = (byte)StatTarget.MoveSpeed, Op = (byte)ModOp.PercentMult, Value = 0.15f, SourceId = src };
seeds[1] = new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.PercentMult, Value = -0.15f, SourceId = src + 1u }; seeds[1] = new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.PercentMult, Value = -0.15f, SourceId = src + 1u };
@@ -7,7 +7,7 @@ namespace ProjectM.Simulation
Primary = 1, Primary = 1,
FastLight = 2, FastLight = 2,
SlowHeavy = 3, SlowHeavy = 3,
WarriorCone = 4, // Slice 2: the Warrior's aim-directed short-range cone secondary (Fire slot) WarriorCone = 4, // Slice 2: the Bathynaut's aim-directed short-range cone secondary (Fire slot)
// LANTERN Phase 1 Sparks (the gym's first socketables): // LANTERN Phase 1 Sparks (the gym's first socketables):
DecoyWisp = 5, // Aoe/spawn: a decoy ghost that draws aggro DecoyWisp = 5, // Aoe/spawn: a decoy ghost that draws aggro
HookPull = 6, // Projectile + pull: the Harpooner reel (yanks the hit target in) HookPull = 6, // Projectile + pull: the Harpooner reel (yanks the hit target in)
@@ -23,8 +23,8 @@ namespace ProjectM.Simulation
{ {
None = 0, None = 0,
Default = 1, Default = 1,
Warrior = 2, // Bathynaut-lineage melee-anchor bruiser (tankier, slower, longer/harder melee) Bathynaut = 2, // Bathynaut-lineage melee-anchor bruiser (tankier, slower, longer/harder melee)
Ranger = 3, // Harpooner-lineage ranged-anchor (squishier, faster, longer projectile range; weaker melee) Harpooner = 3, // Harpooner-lineage ranged-anchor (squishier, faster, longer projectile range; weaker melee)
} }
/// <summary> /// <summary>
@@ -42,8 +42,8 @@ namespace ProjectM.Simulation
MoveSpeed = 6, MoveSpeed = 6,
TurnRate = 7, TurnRate = 7,
MaxHealth = 8, MaxHealth = 8,
MeleeDamage = 9, // Slice 2: melee combo + Warrior cone damage axis (folded onto TuningConfig.MeleeDamage) MeleeDamage = 9, // Slice 2: melee combo + Bathynaut cone damage axis (folded onto TuningConfig.MeleeDamage)
MeleeRange = 10, // Slice 2: melee reach axis (Warrior longer, Ranger shorter) MeleeRange = 10, // Slice 2: melee reach axis (Bathynaut longer, Harpooner shorter)
} }
/// <summary>How a <see cref="StatModifier"/> combines into the effective stat.</summary> /// <summary>How a <see cref="StatModifier"/> combines into the effective stat.</summary>
@@ -7,5 +7,5 @@ namespace ProjectM.Simulation
/// NetworkStreamInGame to the connection (enabling snapshot/command flow) and spawns the /// NetworkStreamInGame to the connection (enabling snapshot/command flow) and spawns the
/// client's player ghost. Lives in Simulation so both worlds see the type for RPC source-gen. /// client's player ghost. Lives in Simulation so both worlds see the type for RPC source-gen.
/// </summary> /// </summary>
public struct GoInGameRequest : IRpcCommand { public byte ClassId; } // Slice 2: per-player class (FrameKind byte; 0 -> server defaults to Warrior) public struct GoInGameRequest : IRpcCommand { public byte ClassId; } // Slice 2: per-player class (FrameKind byte; 0 -> server defaults to Bathynaut)
} }
@@ -59,9 +59,9 @@ namespace ProjectM.Simulation
/// <summary>Set the <see cref="TuningKnob"/> ArgA to ArgB/1000f (live dash/Charger feel-tuning; MC-0).</summary> /// <summary>Set the <see cref="TuningKnob"/> ArgA to ArgB/1000f (live dash/Charger feel-tuning; MC-0).</summary>
public const byte SetTuning = 12; public const byte SetTuning = 12;
/// <summary>Swap the sender's class to ArgA (a <see cref="FrameKind"/> byte: Warrior=2 / Ranger=3). /// <summary>Swap the sender's class to ArgA (a <see cref="FrameKind"/> byte: Bathynaut=2 / Harpooner=3).
/// Strips the old class trait seeds, re-seeds the new ones, swaps the Fire ability, and heals a living /// Strips the old class trait seeds, re-seeds the new ones, swaps the Fire ability, and heals a living
/// player to the new class's max. Editor-only dev tool (class-switch); 0 / unknown -> Warrior.</summary> /// player to the new class's max. Editor-only dev tool (class-switch); 0 / unknown -> Bathynaut.</summary>
public const byte SetClass = 13; public const byte SetClass = 13;
/// <summary>GYM (editor): spawn <see cref="GymEnemyKind"/> ArgA near the sender, ArgB times (default 1). Reads the baked GymEnemyRoster.</summary> /// <summary>GYM (editor): spawn <see cref="GymEnemyKind"/> ArgA near the sender, ArgB times (default 1). Reads the baked GymEnemyRoster.</summary>
@@ -11,7 +11,7 @@ namespace ProjectM.Simulation
} }
/// <summary>One persisted per-class PERMANENT meta-upgrade tier (v6). ClassId = the normalized FrameKind /// <summary>One persisted per-class PERMANENT meta-upgrade tier (v6). ClassId = the normalized FrameKind
/// (Warrior=2/Ranger=3); UpgradeId = the append-only meta-catalog key (unknown ids round-trip preserved and are /// (Bathynaut=2/Harpooner=3); UpgradeId = the append-only meta-catalog key (unknown ids round-trip preserved and are
/// skipped live); Tier clamps to the catalog's MaxTier at seed/shop/spend, never at rest.</summary> /// skipped live); Tier clamps to the catalog's MaxTier at seed/shop/spend, never at rest.</summary>
[Serializable] [Serializable]
public struct MetaUpgradeSave public struct MetaUpgradeSave
+1 -1
View File
@@ -237,7 +237,7 @@ namespace ProjectM.Simulation
/// <summary>Base for per-slot equipment SourceIds; slot i tags its mods with <c>EquipSourceIdBase + i</c>.</summary> /// <summary>Base for per-slot equipment SourceIds; slot i tags its mods with <c>EquipSourceIdBase + i</c>.</summary>
public const uint EquipSourceIdBase = 0x00E91000u; public const uint EquipSourceIdBase = 0x00E91000u;
/// <summary>Slice 2: base SourceId for a class's permanent trait StatModifiers (Warrior/Ranger seeds). /// <summary>Slice 2: base SourceId for a class's permanent trait StatModifiers (Bathynaut/Harpooner seeds).
/// DISJOINT from equipment/upgrade/debug ranges; class traits are NEVER stripped (permanent per session).</summary> /// DISJOINT from equipment/upgrade/debug ranges; class traits are NEVER stripped (permanent per session).</summary>
public const uint ClassSourceId = 0x00C1A550u; public const uint ClassSourceId = 0x00C1A550u;
} }
+5 -289
View File
@@ -2401,54 +2401,6 @@ Transform:
- {fileID: 1683222666} - {fileID: 1683222666}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &380046993
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 380046995}
- component: {fileID: 380046994}
m_Layer: 0
m_Name: StructureCatalog
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &380046994
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 380046993}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 40093ed42072f5a4889f5f62f510aa27, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.StructureCatalogAuthoring
WallPrefab: {fileID: 3885353946372160549, guid: 1e321aea244cc484f99c1cdd68cb01c4, type: 3}
WallCostBiomass: 4
PylonPrefab: {fileID: 3885353946372160549, guid: 7d0637ef90f120a4c9e2ba637dfc00af, type: 3}
PylonCostOre: 2
--- !u!4 &380046995
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 380046993}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &383191086 --- !u!1 &383191086
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -2536,6 +2488,11 @@ MonoBehaviour:
- {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} - {fileID: 11400000, guid: 4cf5f3ead961b1242b0e3c79de96fa44, type: 2}
- {fileID: 11400000, guid: c1e799ca78899bc4d97be9399233606c, type: 2}
- {fileID: 11400000, guid: f57d643df7f809b40b9804bb9f8afa60, type: 2}
- {fileID: 11400000, guid: 5e9c506bc3657b44ab7869c037a9e9ca, type: 2}
- {fileID: 11400000, guid: f39412c52281a3e4590f77e94c9911e7, type: 2}
- {fileID: 11400000, guid: 66b9bc054810f3a4a808dd88aa2d539f, type: 2}
Characters: Characters:
- {fileID: 11400000, guid: e675b529048144a41a2054c729180bce, type: 2} - {fileID: 11400000, guid: e675b529048144a41a2054c729180bce, type: 2}
--- !u!4 &409538539 --- !u!4 &409538539
@@ -4309,59 +4266,6 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 4.0118155, y: 5, z: 1.5} m_Size: {x: 4.0118155, y: 5, z: 1.5}
m_Center: {x: 0, y: 2, z: 0} m_Center: {x: 0, y: 2, z: 0}
--- !u!1 &722706768
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 722706770}
- component: {fileID: 722706769}
m_Layer: 0
m_Name: ItemDatabase
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &722706769
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 722706768}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5ee44dc3bc9f3164592195d4068be8d1, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.ItemDatabaseAuthoring
Items:
- {fileID: 11400000, guid: 938a882b6fbd50d4c9a051ddabc5829b, type: 2}
- {fileID: 11400000, guid: b37686ead19d68d45b84e031bfe99f59, type: 2}
- {fileID: 11400000, guid: a2a0e6d3ae0218d458d2b5305891ce89, type: 2}
- {fileID: 11400000, guid: 441dbd6676662a2459607f3b75ee821b, type: 2}
- {fileID: 11400000, guid: 4ed399a329eb6d847921aef05bde213d, type: 2}
- {fileID: 11400000, guid: c09dc2c47feaa784486e21a3b7e4cb10, type: 2}
- {fileID: 11400000, guid: b69a26c8de798624b82e6799f8130291, type: 2}
- {fileID: 11400000, guid: 31ec40cfc6e81ef4ab9bbce57a40621e, type: 2}
--- !u!4 &722706770
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 722706768}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &746604218 --- !u!1 &746604218
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -8576,51 +8480,6 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 4.156388, y: 5, z: 1.5} m_Size: {x: 4.156388, y: 5, z: 1.5}
m_Center: {x: 0, y: 2, z: 0} m_Center: {x: 0, y: 2, z: 0}
--- !u!1 &1427126582
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1427126584}
- component: {fileID: 1427126583}
m_Layer: 0
m_Name: BoonCatalog
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1427126583
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1427126582}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 075a570afb8ef9541b6307280b53f4e7, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.BoonCatalogAuthoring
Rows: []
--- !u!4 &1427126584
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1427126582}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1428056924 --- !u!1 &1428056924
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -9409,51 +9268,6 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 3.2950234, y: 5, z: 1.5} m_Size: {x: 3.2950234, y: 5, z: 1.5}
m_Center: {x: 0, y: 2, z: 0} m_Center: {x: 0, y: 2, z: 0}
--- !u!1 &1518140826
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1518140828}
- component: {fileID: 1518140827}
m_Layer: 0
m_Name: MetaCatalog
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1518140827
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1518140826}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f007f7870c0afd4e93ea5b86fd21c8b, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.MetaCatalogAuthoring
Rows: []
--- !u!4 &1518140828
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1518140826}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1529835794 --- !u!1 &1529835794
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -11394,52 +11208,6 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 3.8984706, y: 5, z: 1.5} m_Size: {x: 3.8984706, y: 5, z: 1.5}
m_Center: {x: 0, y: 2, z: 0} m_Center: {x: 0, y: 2, z: 0}
--- !u!1 &1871304248
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1871304250}
- component: {fileID: 1871304249}
m_Layer: 0
m_Name: SpitterProjectileConfig
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1871304249
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1871304248}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4ce5223c5fd56694c81991e1bb1232de, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.SpitterProjectilePrefabAuthoring
ProjectilePrefab: {fileID: 3885353946372160549, guid: 8a13ef653e5266741b0896084f74038f, type: 3}
MaxLiveProjectiles: 24
--- !u!4 &1871304250
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1871304248}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1897463016 --- !u!1 &1897463016
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -11652,52 +11420,6 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 3.0690043, y: 5, z: 1.5} m_Size: {x: 3.0690043, y: 5, z: 1.5}
m_Center: {x: 0, y: 2, z: 0} m_Center: {x: 0, y: 2, z: 0}
--- !u!1 &1930969065
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1930969067}
- component: {fileID: 1930969066}
m_Layer: 0
m_Name: StorageSpawner
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1930969066
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1930969065}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 968b8c85b6f69ae438e56cb1f19a2450, type: 3}
m_Name:
m_EditorClassIdentifier: ProjectM.Authoring::ProjectM.Authoring.StorageSpawnerAuthoring
ContainerPrefab: {fileID: 3885353946372160549, guid: 6636e906a2ac46345889f5517658be67, type: 3}
Cell: {x: 19, y: 19}
--- !u!4 &1930969067
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1930969065}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1936047021 --- !u!1 &1936047021
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -12982,20 +12704,14 @@ SceneRoots:
- {fileID: 409538539} - {fileID: 409538539}
- {fileID: 1435545288} - {fileID: 1435545288}
- {fileID: 874705788} - {fileID: 874705788}
- {fileID: 1930969067}
- {fileID: 1301940441} - {fileID: 1301940441}
- {fileID: 2038854532} - {fileID: 2038854532}
- {fileID: 17637047} - {fileID: 17637047}
- {fileID: 1192434518} - {fileID: 1192434518}
- {fileID: 380046995}
- {fileID: 175286058} - {fileID: 175286058}
- {fileID: 1698085403} - {fileID: 1698085403}
- {fileID: 450973138} - {fileID: 450973138}
- {fileID: 379192464} - {fileID: 379192464}
- {fileID: 722706770}
- {fileID: 1957070224} - {fileID: 1957070224}
- {fileID: 1871304250}
- {fileID: 1427126584}
- {fileID: 1518140828}
- {fileID: 125166252} - {fileID: 125166252}
- {fileID: 1106173031} - {fileID: 1106173031}
@@ -7,7 +7,7 @@ namespace ProjectM.Tests
{ {
/// <summary> /// <summary>
/// Slice 2 — the pure class mapping: which Fire ability each class gets, and that the DRG-asymmetric trait /// 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 / /// seeds fold the right direction (Bathynaut = melee bruiser / tankier / slower; Harpooner = ranged / faster /
/// squishier + a wider auto-assist co-op hook), all on the reserved <see cref="Tuning.ClassSourceId"/> range. /// squishier + a wider auto-assist co-op hook), all on the reserved <see cref="Tuning.ClassSourceId"/> range.
/// </summary> /// </summary>
public class ClassTraitsTests public class ClassTraitsTests
@@ -27,21 +27,21 @@ namespace ProjectM.Tests
[Test] [Test]
public void Normalize_DefaultsToWarrior() public void Normalize_DefaultsToWarrior()
{ {
Assert.AreEqual(ClassTraits.WarriorClass, ClassTraits.Normalize(0)); Assert.AreEqual(ClassTraits.BathynautFrame, ClassTraits.Normalize(0));
Assert.AreEqual(ClassTraits.WarriorClass, ClassTraits.Normalize(99)); Assert.AreEqual(ClassTraits.BathynautFrame, ClassTraits.Normalize(99));
Assert.AreEqual(ClassTraits.RangerClass, ClassTraits.Normalize(ClassTraits.RangerClass)); Assert.AreEqual(ClassTraits.HarpoonerFrame, ClassTraits.Normalize(ClassTraits.HarpoonerFrame));
} }
[Test] [Test]
public void Warrior_Seeds_Buff_Melee_And_Tankiness_And_Slow() public void Warrior_Seeds_Buff_Melee_And_Tankiness_And_Slow()
{ {
using var world = new World("ClassTraitsWarrior"); using var world = new World("ClassTraitsWarrior");
var mods = SeededBuffer(world, ClassTraits.WarriorClass); var mods = SeededBuffer(world, ClassTraits.BathynautFrame);
Assert.AreEqual(4, mods.Length, "Warrior seeds 4 trait modifiers."); Assert.AreEqual(4, mods.Length, "Bathynaut seeds 4 trait modifiers.");
Assert.Greater(StatMath.Apply(10f, StatTarget.MeleeDamage, mods), 10f, "Warrior hits harder in melee."); Assert.Greater(StatMath.Apply(10f, StatTarget.MeleeDamage, mods), 10f, "Bathynaut hits harder in melee.");
Assert.Greater(StatMath.Apply(2.6f, StatTarget.MeleeRange, mods), 2.6f, "Warrior reaches further in melee."); Assert.Greater(StatMath.Apply(2.6f, StatTarget.MeleeRange, mods), 2.6f, "Bathynaut reaches further in melee.");
Assert.Less(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Warrior moves slower."); Assert.Less(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Bathynaut moves slower.");
Assert.Greater(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Warrior is tankier."); Assert.Greater(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Bathynaut is tankier.");
for (int i = 0; i < mods.Length; i++) for (int i = 0; i < mods.Length; i++)
Assert.GreaterOrEqual(mods[i].SourceId, Tuning.ClassSourceId, "class seeds use the reserved SourceId range."); Assert.GreaterOrEqual(mods[i].SourceId, Tuning.ClassSourceId, "class seeds use the reserved SourceId range.");
} }
@@ -50,13 +50,13 @@ namespace ProjectM.Tests
public void Ranger_Seeds_Buff_Range_Speed_Assist_And_Leave_Melee_Weak() public void Ranger_Seeds_Buff_Range_Speed_Assist_And_Leave_Melee_Weak()
{ {
using var world = new World("ClassTraitsRanger"); using var world = new World("ClassTraitsRanger");
var mods = SeededBuffer(world, ClassTraits.RangerClass); var mods = SeededBuffer(world, ClassTraits.HarpoonerFrame);
Assert.AreEqual(4, mods.Length, "Ranger seeds 4 trait modifiers."); Assert.AreEqual(4, mods.Length, "Harpooner seeds 4 trait modifiers.");
Assert.Greater(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Ranger moves faster."); Assert.Greater(StatMath.Apply(5f, StatTarget.MoveSpeed, mods), 5f, "Harpooner moves faster.");
Assert.Less(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Ranger is squishier."); Assert.Less(StatMath.Apply(100f, StatTarget.MaxHealth, mods), 100f, "Harpooner is squishier.");
Assert.Greater(StatMath.Apply(20f, StatTarget.Range, mods), 20f, "Ranger has longer projectile range."); Assert.Greater(StatMath.Apply(20f, StatTarget.Range, mods), 20f, "Harpooner has longer projectile range.");
Assert.Greater(StatMath.Apply(0f, StatTarget.AutoTargetRange, mods), 0f, "Ranger has a wider auto-assist (the co-op hook)."); Assert.Greater(StatMath.Apply(0f, StatTarget.AutoTargetRange, mods), 0f, "Harpooner 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)."); Assert.AreEqual(10f, StatMath.Apply(10f, StatTarget.MeleeDamage, mods), 0.001f, "Harpooner melee is unbuffed (weaker than the Bathynaut).");
} }
static int CountClassSeeds(DynamicBuffer<StatModifier> mods) static int CountClassSeeds(DynamicBuffer<StatModifier> mods)
@@ -77,7 +77,7 @@ namespace ProjectM.Tests
[Test] [Test]
public void AppendSeeds_EmitsExactlyClassSeedCount_AllInClassRange() public void AppendSeeds_EmitsExactlyClassSeedCount_AllInClassRange()
{ {
foreach (var classId in new[] { ClassTraits.WarriorClass, ClassTraits.RangerClass }) foreach (var classId in new[] { ClassTraits.BathynautFrame, ClassTraits.HarpoonerFrame })
{ {
using var world = new World("ClassTraitsCount"); using var world = new World("ClassTraitsCount");
var em = world.EntityManager; var em = world.EntityManager;
@@ -99,24 +99,24 @@ namespace ProjectM.Tests
var e = em.CreateEntity(); var e = em.CreateEntity();
em.AddBuffer<StatModifier>(e); em.AddBuffer<StatModifier>(e);
// Seed Warrior, swap to Ranger, then back to Warrior. // Seed Bathynaut, swap to Harpooner, then back to Bathynaut.
ClassTraits.Reapply(ClassTraits.WarriorClass, em.GetBuffer<StatModifier>(e)); ClassTraits.Reapply(ClassTraits.BathynautFrame, em.GetBuffer<StatModifier>(e));
Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(em.GetBuffer<StatModifier>(e)), "Warrior seeds the class-seed count."); Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(em.GetBuffer<StatModifier>(e)), "Bathynaut seeds the class-seed count.");
ClassTraits.Reapply(ClassTraits.RangerClass, em.GetBuffer<StatModifier>(e)); ClassTraits.Reapply(ClassTraits.HarpoonerFrame, em.GetBuffer<StatModifier>(e));
Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(em.GetBuffer<StatModifier>(e)), "Ranger leaves exactly the class-seed count (old seeds stripped)."); Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(em.GetBuffer<StatModifier>(e)), "Harpooner leaves exactly the class-seed count (old seeds stripped).");
Assert.Greater(StatMath.Apply(5f, StatTarget.MoveSpeed, em.GetBuffer<StatModifier>(e)), 5f, "Ranger moves faster after the swap."); Assert.Greater(StatMath.Apply(5f, StatTarget.MoveSpeed, em.GetBuffer<StatModifier>(e)), 5f, "Harpooner moves faster after the swap.");
ClassTraits.Reapply(ClassTraits.WarriorClass, em.GetBuffer<StatModifier>(e)); ClassTraits.Reapply(ClassTraits.BathynautFrame, em.GetBuffer<StatModifier>(e));
var back = em.GetBuffer<StatModifier>(e); var back = em.GetBuffer<StatModifier>(e);
Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(back), "Warrior again: no accumulation across swaps."); Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(back), "Bathynaut again: no accumulation across swaps.");
// Value-equality vs a fresh-spawned Warrior buffer (the ECB overload) — catches same-target PercentMult // Value-equality vs a fresh-spawned Bathynaut buffer (the ECB overload) — catches same-target PercentMult
// doubling or a strip-order regression that a count-only assert would miss. // doubling or a strip-order regression that a count-only assert would miss.
using var refWorld = new World("ClassTraitsWarriorRef"); using var refWorld = new World("ClassTraitsWarriorRef");
var fresh = SeededBuffer(refWorld, ClassTraits.WarriorClass); var fresh = SeededBuffer(refWorld, ClassTraits.BathynautFrame);
Assert.AreEqual(StatMath.Apply(100f, StatTarget.MaxHealth, fresh), StatMath.Apply(100f, StatTarget.MaxHealth, back), 1e-4f, "MaxHealth folds identically to a fresh Warrior."); Assert.AreEqual(StatMath.Apply(100f, StatTarget.MaxHealth, fresh), StatMath.Apply(100f, StatTarget.MaxHealth, back), 1e-4f, "MaxHealth folds identically to a fresh Bathynaut.");
Assert.AreEqual(StatMath.Apply(5f, StatTarget.MoveSpeed, fresh), StatMath.Apply(5f, StatTarget.MoveSpeed, back), 1e-4f, "MoveSpeed folds identically to a fresh Warrior."); Assert.AreEqual(StatMath.Apply(5f, StatTarget.MoveSpeed, fresh), StatMath.Apply(5f, StatTarget.MoveSpeed, back), 1e-4f, "MoveSpeed folds identically to a fresh Bathynaut.");
} }
[Test] [Test]
@@ -133,7 +133,7 @@ namespace ProjectM.Tests
seed.Add(new StatModifier { Target = (byte)StatTarget.Damage, Op = (byte)ModOp.PercentAdd, Value = 0.25f, SourceId = 0x00DEB061u }); seed.Add(new StatModifier { Target = (byte)StatTarget.Damage, Op = (byte)ModOp.PercentAdd, Value = 0.25f, SourceId = 0x00DEB061u });
seed.Add(new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.Flat, Value = 10f, SourceId = boundary }); seed.Add(new StatModifier { Target = (byte)StatTarget.MaxHealth, Op = (byte)ModOp.Flat, Value = 10f, SourceId = boundary });
ClassTraits.Reapply(ClassTraits.RangerClass, em.GetBuffer<StatModifier>(e)); ClassTraits.Reapply(ClassTraits.HarpoonerFrame, em.GetBuffer<StatModifier>(e));
var after = em.GetBuffer<StatModifier>(e); var after = em.GetBuffer<StatModifier>(e);
Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(after), "exactly the class-seed count of class seeds present."); Assert.AreEqual(ClassTraits.ClassSeedCount, CountClassSeeds(after), "exactly the class-seed count of class seeds present.");