diff --git a/Assets/Desert/Assets/Desert.asset b/Assets/Desert/Assets/Desert.asset index 452209e..b7fe71f 100644 --- a/Assets/Desert/Assets/Desert.asset +++ b/Assets/Desert/Assets/Desert.asset @@ -24,8 +24,7 @@ MonoBehaviour: spawnDoor: {fileID: 11400000, guid: 6e937b2e9f774999b5962c4b40947165, type: 2} exitDoorTypes: - {fileID: 11400000, guid: 29e2ae36585f4e65966bc9ea2f95ac4a, type: 2} - puzzleCount: {x: 2, y: 5} + puzzleCount: {x: 2, y: 3} puzzleTypes: - {fileID: 11400000, guid: 2a6dd6683bdc4db9b200ccfab1dd4bed, type: 2} - - {fileID: 11400000, guid: bd8605f18a5175146b6518413ead986d, type: 2} - {fileID: 11400000, guid: 3f79d37154e44ca47b54bb43bbe8d9aa, type: 2} diff --git a/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset b/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset new file mode 100644 index 0000000..0a99b51 --- /dev/null +++ b/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset @@ -0,0 +1,15 @@ +%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: 6e3f3bf07aae4a03834a7943c255f37d, type: 3} + m_Name: Ball Relation + m_EditorClassIdentifier: + relatedModule: {fileID: 11400000, guid: bd8605f18a5175146b6518413ead986d, type: 2} diff --git a/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset.meta b/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset.meta new file mode 100644 index 0000000..deebcff --- /dev/null +++ b/Assets/Desert/Assets/Modules/Puzzle A/Ball Relation.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45b46441a03830743a3fa25e7e3c8fba +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Desert/Assets/Modules/Puzzle A Ball.asset b/Assets/Desert/Assets/Modules/Puzzle A/Puzzle A Ball.asset similarity index 100% rename from Assets/Desert/Assets/Modules/Puzzle A Ball.asset rename to Assets/Desert/Assets/Modules/Puzzle A/Puzzle A Ball.asset diff --git a/Assets/Desert/Assets/Modules/Puzzle A Ball.asset.meta b/Assets/Desert/Assets/Modules/Puzzle A/Puzzle A Ball.asset.meta similarity index 100% rename from Assets/Desert/Assets/Modules/Puzzle A Ball.asset.meta rename to Assets/Desert/Assets/Modules/Puzzle A/Puzzle A Ball.asset.meta diff --git a/Assets/Desert/Assets/Modules/Puzzle A Terminal.asset b/Assets/Desert/Assets/Modules/Puzzle A/Puzzle A.asset similarity index 86% rename from Assets/Desert/Assets/Modules/Puzzle A Terminal.asset rename to Assets/Desert/Assets/Modules/Puzzle A/Puzzle A.asset index be5db45..ccdbad7 100644 --- a/Assets/Desert/Assets/Modules/Puzzle A Terminal.asset +++ b/Assets/Desert/Assets/Modules/Puzzle A/Puzzle A.asset @@ -10,11 +10,13 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: f928b97941e3469a9015316bb5ac1309, type: 3} - m_Name: Puzzle A Terminal + m_Name: Puzzle A m_EditorClassIdentifier: types: 02000000 modulePrefab: {fileID: 5383329221585827905, guid: 02a72e7f56d97334c93a1449eedc9d91, type: 3} + preconditionRequirements: + - {fileID: 11400000, guid: 45b46441a03830743a3fa25e7e3c8fba, type: 2} placementRequirements: - {fileID: 11400000, guid: 43eb2a566a244964aa3a3319eaafe1a8, type: 2} - {fileID: 11400000, guid: ed4830127e9381245a6af07e42c52422, type: 2} diff --git a/Assets/Desert/Assets/Modules/Puzzle A Terminal.asset.meta b/Assets/Desert/Assets/Modules/Puzzle A/Puzzle A.asset.meta similarity index 100% rename from Assets/Desert/Assets/Modules/Puzzle A Terminal.asset.meta rename to Assets/Desert/Assets/Modules/Puzzle A/Puzzle A.asset.meta diff --git a/Assets/Engine/Runtime/Engine.cs b/Assets/Engine/Runtime/Engine.cs index 3586412..8ecd41e 100644 --- a/Assets/Engine/Runtime/Engine.cs +++ b/Assets/Engine/Runtime/Engine.cs @@ -81,9 +81,10 @@ namespace EscapeRoomEngine.Engine.Runtime var exit = new Passage(exitDoor); // add puzzles - for (var i = 0; i < Utilities.Utilities.RandomInclusive(theme.puzzleCount.x, theme.puzzleCount.y); i++) + var puzzleCount = Utilities.Utilities.RandomInclusive(theme.puzzleCount.x, theme.puzzleCount.y); + for (var i = 0; i < puzzleCount; i++) { - space.AddModuleWithRequirements(new PuzzleModule(space, theme.puzzleTypes.RandomElement())); + space.AddModuleWithRequirements(Module.CreateModuleByType(space, theme.puzzleTypes.RandomElement())); } room.AddSpace(space, exit); diff --git a/Assets/Engine/Runtime/Modules/DoorState.cs b/Assets/Engine/Runtime/Modules/DoorState.cs index 6552803..3719582 100644 --- a/Assets/Engine/Runtime/Modules/DoorState.cs +++ b/Assets/Engine/Runtime/Modules/DoorState.cs @@ -47,7 +47,7 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules } else { - throw new Exception("Tried to set wrong type of module."); + throw new Exception($"Tried to set wrong type of module ({module.GetType()} instead of DoorModule)"); } } diff --git a/Assets/Engine/Runtime/Modules/Module.cs b/Assets/Engine/Runtime/Modules/Module.cs index 44c909a..ca45966 100644 --- a/Assets/Engine/Runtime/Modules/Module.cs +++ b/Assets/Engine/Runtime/Modules/Module.cs @@ -103,6 +103,24 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules State.SetModule(this); } + internal static Module CreateModuleByType(Space space, ModuleDescription description) + { + if (description.HasType(ModuleType.Puzzle) && + description is PuzzleModuleDescription puzzleModuleDescription) + { + return new PuzzleModule(space, puzzleModuleDescription); + } + else if((description.HasType(ModuleType.DoorEntrance) || description.HasType(ModuleType.DoorExit)) && + description is DoorModuleDescription doorModuleDescription) + { + return new DoorModule(space, doorModuleDescription); + } + else + { + throw new Exception("Module description does not have fitting type."); + } + } + public override string ToString() { return $"Module ({string.Join(", ", description.types.ToList().ConvertAll(type => type.ToString()))})"; diff --git a/Assets/Engine/Runtime/Modules/ModuleDescription.cs b/Assets/Engine/Runtime/Modules/ModuleDescription.cs index a087459..81a6a28 100644 --- a/Assets/Engine/Runtime/Modules/ModuleDescription.cs +++ b/Assets/Engine/Runtime/Modules/ModuleDescription.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using EscapeRoomEngine.Engine.Runtime.Requirements; +using NaughtyAttributes; using UnityEngine; namespace EscapeRoomEngine.Engine.Runtime.Modules @@ -9,7 +10,16 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules { public List types = new(); public ModuleState modulePrefab; + [BoxGroup("Requirements")] + public List preconditionRequirements = new(); + [BoxGroup("Requirements")] public List placementRequirements = new(); + [BoxGroup("Requirements")] public List orientationRequirements = new(); + + internal bool HasType(ModuleType type) + { + return types.Contains(type); + } } } \ No newline at end of file diff --git a/Assets/Engine/Runtime/Modules/PuzzleState.cs b/Assets/Engine/Runtime/Modules/PuzzleState.cs index de13057..c32c31b 100644 --- a/Assets/Engine/Runtime/Modules/PuzzleState.cs +++ b/Assets/Engine/Runtime/Modules/PuzzleState.cs @@ -64,7 +64,7 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules } else { - throw new Exception("Tried to set wrong type of module."); + throw new Exception($"Tried to set wrong type of module ({module.GetType()} instead of PuzzleModule)"); } } diff --git a/Assets/Engine/Runtime/Requirements/OrientationRequirement.cs b/Assets/Engine/Runtime/Requirements/OrientationRequirement.cs index 44b8340..39cdd49 100644 --- a/Assets/Engine/Runtime/Requirements/OrientationRequirement.cs +++ b/Assets/Engine/Runtime/Requirements/OrientationRequirement.cs @@ -11,6 +11,12 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements public static bool TryOrienting(Module module, Space space) { + if (module.description.orientationRequirements.Count == 0) + { + // don't evaluate requirements if there are none + return true; + } + var orientationCandidates = Candidates( Module.EveryOrientation, module.description.orientationRequirements, diff --git a/Assets/Engine/Runtime/Requirements/PlacementRequirement.cs b/Assets/Engine/Runtime/Requirements/PlacementRequirement.cs index ced085b..925ca2c 100644 --- a/Assets/Engine/Runtime/Requirements/PlacementRequirement.cs +++ b/Assets/Engine/Runtime/Requirements/PlacementRequirement.cs @@ -14,6 +14,12 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements public static bool TryPlacing(Module module, Space space) { + if (module.description.placementRequirements.Count == 0) + { + // don't evaluate requirements if there are none + return true; + } + var placementCandidates = Candidates( space.rrDimensions.EveryPosition, module.description.placementRequirements, diff --git a/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs b/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs new file mode 100644 index 0000000..13e5a02 --- /dev/null +++ b/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using EscapeRoomEngine.Engine.Runtime.Modules; +using UnityEngine; +using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger; +using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType; + +namespace EscapeRoomEngine.Engine.Runtime.Requirements +{ + public abstract class PreconditionRequirement : Requirement + { + protected static readonly HashSet TrueSet = new(new[] { true }), FalseSet = new(new[] { false }); + + protected abstract override IEnumerable GenerateCandidates(Module module, Space space); + + public static bool CheckPreconditions(Module module, Space space) + { + Debug.Log($"{module}, {module.description.preconditionRequirements}"); + if (module.description.preconditionRequirements.Count == 0) + { + // don't evaluate requirements if there are none + return true; + } + + var preconditionsMet = Candidates( + TrueSet, + module.description.preconditionRequirements, + module, space) + .Contains(true); + + Logger.Log( + preconditionsMet + ? $"Preconditions for {module} satisfied" + : $"Could not satisfy preconditions for {module}", + LogType.ModulePlacement); + + return preconditionsMet; + } + + protected static HashSet SetFor(bool value) + { + return value ? TrueSet : FalseSet; + } + } +} \ No newline at end of file diff --git a/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs.meta b/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs.meta new file mode 100644 index 0000000..4d18b9d --- /dev/null +++ b/Assets/Engine/Runtime/Requirements/PreconditionRequirement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a73316a9f52d4c5982f9c7936e322ec4 +timeCreated: 1668945634 \ No newline at end of file diff --git a/Assets/Engine/Runtime/Requirements/RelatedModule.cs b/Assets/Engine/Runtime/Requirements/RelatedModule.cs new file mode 100644 index 0000000..9b87491 --- /dev/null +++ b/Assets/Engine/Runtime/Requirements/RelatedModule.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using EscapeRoomEngine.Engine.Runtime.Modules; +using NaughtyAttributes; +using UnityEngine; + +namespace EscapeRoomEngine.Engine.Runtime.Requirements +{ + [CreateAssetMenu(menuName = "Requirements/Related Module")] + class RelatedModule : PreconditionRequirement + { + [InfoBox("A related module that must be added to the same space successfully before this module is added.")] + [Required] + public ModuleDescription relatedModule; + + protected override IEnumerable GenerateCandidates(Module module, Space space) + { + return new []{ space.AddModuleWithRequirements(Module.CreateModuleByType(space, relatedModule)) }; + } + } +} \ No newline at end of file diff --git a/Assets/Engine/Runtime/Requirements/RelatedModule.cs.meta b/Assets/Engine/Runtime/Requirements/RelatedModule.cs.meta new file mode 100644 index 0000000..3859969 --- /dev/null +++ b/Assets/Engine/Runtime/Requirements/RelatedModule.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6e3f3bf07aae4a03834a7943c255f37d +timeCreated: 1668947627 \ No newline at end of file diff --git a/Assets/Engine/Runtime/Space.cs b/Assets/Engine/Runtime/Space.cs index ecec5bd..578900c 100644 --- a/Assets/Engine/Runtime/Space.cs +++ b/Assets/Engine/Runtime/Space.cs @@ -42,6 +42,7 @@ namespace EscapeRoomEngine.Engine.Runtime internal bool AddModuleWithRequirements(Module module) { var requirementsFulfilled = + PreconditionRequirement.CheckPreconditions(module, this) && PlacementRequirement.TryPlacing(module, this) && OrientationRequirement.TryOrienting(module, this); diff --git a/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png b/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png new file mode 100644 index 0000000..554c2ba --- /dev/null +++ b/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a4be41a58606a3647242c389b483d8168d1f63fc8d2ced409586d81a76c24ae +size 1036 diff --git a/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png.meta b/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png.meta new file mode 100644 index 0000000..46ebdf3 --- /dev/null +++ b/Assets/Gizmos/EscapeRoomEngine/Engine/Runtime/Requirements/RelatedModule icon.png.meta @@ -0,0 +1,124 @@ +fileFormatVersion: 2 +guid: b0bb48ebc472f4e4e98d7658b3b20b00 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: