IEnumerator createLightsFromMarathonMap(Weland.Level Level) { string load = loadingText; for (int i = 0; i < Level.Lights.Count; i++) { Weland.Light light = Level.Lights[i]; mapLight ml = gameObject.AddComponent <mapLight>(); ml.id = i; ml.mapTag = light.TagIndex; ml.stateless = light.Stateless; ml.initiallyActive = light.InitiallyActive; ml.phase = light.Phase; ml.becomingActive.setFromMarathonObject(light.BecomingActive); ml.primaryActive.setFromMarathonObject(light.PrimaryActive); ml.secondaryActive.setFromMarathonObject(light.SecondaryActive); ml.becomingInactive.setFromMarathonObject(light.BecomingInactive); ml.primaryInactive.setFromMarathonObject(light.PrimaryInactive); ml.secondaryInactive.setFromMarathonObject(light.SecondaryInactive); if (light.Type == Weland.LightType.Strobe) { ml.type = 1; } if (light.Type == Weland.LightType.Media) { ml.type = 2; } lights.Add(ml); } yield return(null); }
IEnumerator spawnEntitiesFromMarathonMap(Weland.Level Level, Weland.ShapesFile shapes) { string load = loadingText; bool playerSpawned = false; for (int i = 0; i < Level.Objects.Count; i++) { MapObject obj = Level.Objects[i]; Quaternion facing = Quaternion.Euler(0, (float)obj.Facing + 90, 0); Vector3 pos = new Vector3(pos.x = (float)obj.X / 1024f, pos.y = (float)obj.Z / 1024f + segments[obj.PolygonIndex].centerPoint.y, pos.z = 0f - (float)obj.Y / 1024f ); if (obj.Type == ObjectType.Player && !playerSpawned) { playerSpawned = true; GameObject player = Instantiate(Resources.Load <GameObject>("player"), pos, facing); player.gameObject.name = "player"; player.GetComponent <playerController>().currentPolygon = obj.PolygonIndex; } if (obj.Type == ObjectType.Item) { GameObject item = createMapItemFromSpriteSequence(7, GlobalData.itemSequences[obj.Index - 1], shapes, "itemObject"); Vector3 rpos = pos; item.transform.position = rpos; item.transform.rotation = facing; item.name = "item" + i; } if (obj.Type == ObjectType.Sound) { } if (obj.Type == ObjectType.Scenery) { GameObject item = createMapItemFromSpriteSequence(GlobalData.sceneryCollections[obj.Index], GlobalData.scenerySequences[obj.Index], shapes, "sceneryObject"); Vector3 rpos = pos; if (obj.FromCeiling) { rpos.y = segments[obj.PolygonIndex].centerPoint.y + segments[obj.PolygonIndex].height.y; } item.transform.position = rpos; item.transform.rotation = facing; item.name = "scenery" + i; item.transform.Find("sprite").GetComponent <spriteController>().fromCeiling = obj.FromCeiling; } if (obj.Type == ObjectType.Goal) { } if (obj.Type == ObjectType.Monster) { Debug.Log("monster"); Debug.Log(obj.Index); } if (i % 7 == 0) { loadingText = load + i + "/" + Level.Objects.Count; yield return(null); } } }
IEnumerator makeWorldFromMarathonMap(Weland.Level Level) { string load = loadingText; //marathon maps have y +/- directions swapped so fix that for (int i = 0; i < Level.Endpoints.Count; i++) { Level.Endpoints[i] = new Point(Level.Endpoints[i].X, (short)(0 - Level.Endpoints[i].Y)); } //now we can generate mapsegment objects from each map polygon for (int p = 0; p < Level.Polygons.Count; p++) { GameObject pol = Instantiate(polygon); pol.name = "Polygon" + p; pol.tag = "polygon"; MapSegment seg = pol.GetComponent <MapSegment>(); segments.Add(seg); seg.height = new Vector3(0, (float)(Level.Polygons[p].CeilingHeight - Level.Polygons[p].FloorHeight) / 1024f, 0); if (Level.Polygons[p].Type == Weland.PolygonType.Platform) { foreach (Weland.Platform pl in Level.Platforms) { if (pl.PolygonIndex == p) { seg.platform = new PlatformObject(); seg.platform.comesFromCeiling = pl.ComesFromCeiling; seg.platform.comesFromFloor = pl.ComesFromFloor; seg.platform.initiallyExtended = pl.InitiallyExtended; seg.platform.maximumHeight = (float)pl.MaximumHeight / 1024f; seg.platform.minimumHeight = (float)pl.MinimumHeight / 1024f; seg.platform.speed = (float)pl.Speed / 64f; seg.platform.usesNativePolygonHeights = pl.UsesNativePolygonHeights; seg.platform.door = pl.IsDoor; seg.platform.initiallyActive = pl.InitiallyActive; seg.platform.parent = seg; seg.platform.activatesAdjacantPlatformsAtEachLevel = pl.ActivatesAdjacantPlatformsAtEachLevel; seg.platform.activatesAdjacentPlatformsWhenActivating = pl.ActivatesAdjacentPlatformsWhenActivating; seg.platform.activatesAdjacentPlatformsWhenDeactivating = pl.ActivatesAdjacentPlatformsWhenDeactivating; seg.platform.activatesLight = pl.ActivatesLight; seg.platform.activatesOnlyOnce = pl.ActivatesOnlyOnce; seg.platform.cannotBeExternallyDeactivated = pl.CannotBeExternallyDeactivated; seg.platform.causesDamage = pl.CausesDamage; seg.platform.contractsSlower = pl.ContractsSlower; seg.platform.deactivatesAdjacentPlatformsWhenActivating = pl.DeactivatesAdjacentPlatformsWhenActivating; seg.platform.deactivatesAdjacentPlatformsWhenDeactivating = pl.DeactivatesAdjacentPlatformsWhenDeactivating; seg.platform.deactivatesAtEachLevel = pl.DeactivatesAtEachLevel; seg.platform.deactivatesAtInitialLevel = pl.DeactivatesAtInitialLevel; seg.platform.deactivatesLight = pl.DeactivatesLight; seg.platform.delay = pl.Delay / 30f; seg.platform.delaysBeforeActivation = pl.DelaysBeforeActivation; seg.platform.doesNotActivateParent = pl.DoesNotActivateParent; seg.platform.extendsFloorToCeiling = pl.ExtendsFloorToCeiling; seg.platform.isMonsterControllable = pl.IsMonsterControllable; seg.platform.isPlayerControllable = pl.IsPlayerControllable; seg.platform.locked = pl.IsLocked; seg.platform.reversesDirectionWhenObstructed = pl.ReversesDirectionWhenObstructed; seg.platform.secret = pl.IsSecret; seg.platform.mapTag = pl.Tag; seg.platform.usesNativePolygonHeights = pl.UsesNativePolygonHeights; } } } if (Level.Polygons[p].MediaIndex >= 0) { seg.liquid = new Liquid(); Media media = Level.Medias[Level.Polygons[p].MediaIndex]; seg.liquid.currentSpeed = (float)media.CurrentMagnitude / 1024f; seg.liquid.currentDirectioin = Quaternion.Euler(0, (float)media.Direction + 90, 0); seg.liquid.high = (float)media.High / 1024f; seg.liquid.low = (float)media.Low / 1024f; seg.liquid.mediaLight = lights[media.LightIndex]; //?? where is the liquid data stored??? // Material mat = new Material(Shader.Find("Custom/StandardClippableV2")); Weland.ShapeDescriptor tex = new Weland.ShapeDescriptor(); switch (media.Type) { case MediaType.Water: tex.Collection = (byte)GlobalData.mediaCollections[0]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[0]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[0]; seg.liquid.density = GlobalData.mediaDensities[0]; break; case MediaType.Lava: tex.Collection = (byte)GlobalData.mediaCollections[1]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[1]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[1]; seg.liquid.density = GlobalData.mediaDensities[1]; break; case MediaType.Goo: tex.Collection = (byte)GlobalData.mediaCollections[2]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[2]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[2]; seg.liquid.density = GlobalData.mediaDensities[2]; break; case MediaType.Sewage: tex.Collection = (byte)GlobalData.mediaCollections[3]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[3]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[3]; seg.liquid.density = GlobalData.mediaDensities[3]; break; case MediaType.Jjaro: tex.Collection = (byte)GlobalData.mediaCollections[4]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[4]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[4]; seg.liquid.density = GlobalData.mediaDensities[4]; break; default: tex.Collection = (byte)GlobalData.mediaCollections[0]; tex.Bitmap = (byte)GlobalData.mediaBitmaps[0]; seg.liquid.surface = getTexture(tex); seg.liquid.colour = GlobalData.mediaColours[0]; seg.liquid.density = GlobalData.mediaDensities[0]; break; } seg.liquid.parent = seg; } switch (Level.Polygons[p].Type) { case Weland.PolygonType.AutomaticExit: seg.automaticExit = Level.Polygons[p].Permutation; break; case Weland.PolygonType.Base: seg.mapBase = Level.Polygons[p].Permutation; break; case Weland.PolygonType.DualMonsterTrigger: seg.dualMonsterTrigger = true; break; case Weland.PolygonType.Glue: seg.glue = true; break; case Weland.PolygonType.GlueTrigger: seg.glueTrigger = true; break; case Weland.PolygonType.Goal: seg.goal = true; break; case Weland.PolygonType.Hill: seg.hill = true; break; case Weland.PolygonType.InvisibleMonsterTrigger: seg.invisibleMonsterTrigger = true; break; case Weland.PolygonType.ItemImpassable: seg.itemImpassable = true; break; case Weland.PolygonType.ItemTrigger: seg.itemTrigger = true; break; case Weland.PolygonType.LightOffTrigger: seg.lightOffTrigger = Level.Polygons[p].Permutation; break; case Weland.PolygonType.LightOnTrigger: seg.lightOnTrigger = Level.Polygons[p].Permutation; break; case Weland.PolygonType.MajorOuch: seg.damage = 7; break; case Weland.PolygonType.MinorOuch: seg.damage = 3; break; case Weland.PolygonType.MonsterImpassable: seg.monsterImpassable = true; break; case Weland.PolygonType.MustBeExplored: seg.mustBeExplored = true; break; case Weland.PolygonType.PlatformOffTrigger: seg.platformOffTrigger = Level.Polygons[p].Permutation; break; case Weland.PolygonType.PlatformOnTrigger: seg.platformOnTrigger = Level.Polygons[p].Permutation; break; case Weland.PolygonType.Superglue: seg.superglue = true; break; case Weland.PolygonType.Teleporter: seg.teleporter = Level.Polygons[p].Permutation; break; case Weland.PolygonType.VisibleMonsterTrigger: seg.visibleMonsterTrigger = true; break; case Weland.PolygonType.ZoneBorder: seg.zoneBorder = true; break; } //get the map points that make up the polygon List <Vector3> points = new List <Vector3>(); //find the top most point so we can sort them clockwise to make int zPt = 0; int xPt = 0; for (int ep = 0; ep < Level.Polygons[p].VertexCount; ep++) { int x = Level.Endpoints[Level.Polygons[p].EndpointIndexes[ep]].X; int z = Level.Endpoints[Level.Polygons[p].EndpointIndexes[ep]].Y; if (z > Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].Y || (z == Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].Y && x > Level.Endpoints[Level.Polygons[p].EndpointIndexes[zPt]].X)) { zPt = ep; } if (x < Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].X || (x == Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].X && z > Level.Endpoints[Level.Polygons[p].EndpointIndexes[xPt]].Y)) { xPt = ep; } } //add the lines and sides for the polygon List <Weland.Line> Line = new List <Weland.Line>(); List <Weland.Side> Sides = new List <Weland.Side>(); int currentLine = -1; for (int ln = 0; ln < Level.Polygons[p].VertexCount; ln++) { Line.Add(Level.Lines[Level.Polygons[p].LineIndexes[ln]]); if (Level.Polygons[p].SideIndexes[ln] >= 0) { Sides.Add(Level.Sides[Level.Polygons[p].SideIndexes[ln]]); } //which lines are attached to the vertex int ep = -1; if (Line[Line.Count - 1].EndpointIndexes[0] == Level.Polygons[p].EndpointIndexes[zPt]) { ep = 0; } if (Line[Line.Count - 1].EndpointIndexes[1] == Level.Polygons[p].EndpointIndexes[zPt]) { ep = 1; } if (ep >= 0) { if (currentLine < 0) { currentLine = ln; } else { int lep = 0; if (Line[currentLine].EndpointIndexes[1] == Line[Line.Count - 1].EndpointIndexes[0] || Line[currentLine].EndpointIndexes[1] == Line[Line.Count - 1].EndpointIndexes[1]) { lep = 1; } Point point = Level.Endpoints[Line[currentLine].EndpointIndexes[lep]]; Vector2 a = new Vector2(point.X, point.Y); ep = Line[Line.Count - 1].EndpointIndexes[Mathf.Abs(ep - 1)]; lep = Line[currentLine].EndpointIndexes[Mathf.Abs(lep - 1)]; //make sure we are going clockwise Vector2 b = new Vector2(Level.Endpoints[lep].X, Level.Endpoints[lep].Y); Vector2 c = new Vector2(Level.Endpoints[ep].X, Level.Endpoints[ep].Y); if (Mathf.Atan2(b.y - a.y, b.x - a.x) < Mathf.Atan2(c.y - a.y, c.x - a.x)) { currentLine = ln; } } } } int lastPt = -1; while (Line.Count > 0) { //get the correct point for each line int pt = 0; int[] ei = { Line[currentLine].EndpointIndexes[0], Line[currentLine].EndpointIndexes[1] }; if (lastPt == -1) { if (Level.Endpoints[ei[1]].Y > Level.Endpoints[ei[0]].Y) { pt = 1; } if (Level.Endpoints[ei[1]].Y == Level.Endpoints[ei[0]].Y) { if (Level.Endpoints[ei[1]].X < Level.Endpoints[ei[0]].X) { pt = 1; } } } if (ei[1] == lastPt) { pt = 1; } // map segment vertices must be in clockwise order points.Add(new Vector3( (float)Level.Endpoints[ei[pt]].X / 1024f, 0, (float)Level.Endpoints[ei[pt]].Y / 1024f) ); MapSegmentSide mss = new MapSegmentSide(); mss.transparent = Line[currentLine].Transparent; mss.solid = Line[currentLine].Solid; Side side = new Side(); //get texture + lighting information for side if ((Line[currentLine].ClockwisePolygonSideIndex >= 0 && Line[currentLine].ClockwisePolygonOwner == p) || (Level.Polygons[p].Type == PolygonType.Platform && Line[currentLine].ClockwisePolygonSideIndex >= 0)) { side = Level.Sides[Line[currentLine].ClockwisePolygonSideIndex]; } else if ((Line[currentLine].CounterclockwisePolygonSideIndex >= 0 && Line[currentLine].CounterclockwisePolygonOwner == p) || (Level.Polygons[p].Type == PolygonType.Platform && Line[currentLine].CounterclockwisePolygonSideIndex >= 0)) { side = Level.Sides[Line[currentLine].CounterclockwisePolygonSideIndex]; } mss.upperMaterial = getTexture(side.Primary.Texture); mss.lowerMaterial = getTexture(side.Secondary.Texture); mss.middeMaterial = getTexture(side.Transparent.Texture); mss.upperOffset = new Vector2((float)side.Primary.X / 1024f, (float)side.Primary.Y / 1024f); mss.middleOffset = new Vector2((float)side.Transparent.X / 1024f, (float)side.Transparent.Y / 1024f); mss.lowerOffset = new Vector2((float)side.Secondary.X / 1024f, (float)side.Secondary.Y / 1024f); mss.upperLight = lights[side.PrimaryLightsourceIndex]; mss.lowerLight = lights[side.SecondaryLightsourceIndex]; mss.middleLight = lights[side.TransparentLightsourceIndex]; if (mss.lowerMaterial == null) { mss.lowerMaterial = mss.upperMaterial; mss.lowerOffset = mss.upperOffset; mss.lowerLight = mss.upperLight; } //get control panel information if needed if (side != null && (side.IsControlPanel || side.IsPlatformSwitch() || side.IsTagSwitch() || side.IsLightSwitch())) { mss.controlPanel = new ControlPanel(); mss.controlPanel.permutation = side.ControlPanelPermutation; mss.controlPanel.type = side.ControlPanelType; mss.controlPanel.controlPanel = side.IsControlPanel; if (side.IsPlatformSwitch()) { mss.controlPanel.platformSwitch = side.ControlPanelPermutation; } if (side.IsTagSwitch()) { mss.controlPanel.tagSwitch = side.ControlPanelPermutation; } if (side.IsLightSwitch()) { mss.controlPanel.lightSwitch = side.ControlPanelPermutation; } mss.controlPanel.inactiveMat = mss.upperMaterial; for (int t = 0; t < materials.Count; t++) { if (materials[t] == mss.controlPanel.inactiveMat) { mss.controlPanel.activeMat = materials[t - 1]; } } switch (side.Flags) { // case SideFlags.None: // break; case SideFlags.ControlPanelStatus: mss.controlPanel.controlPanelStatus = 1; //?? what is this for? break; case SideFlags.Dirty: mss.controlPanel.dirty = true; break; case SideFlags.IsDestructiveSwitch: mss.controlPanel.destructiveSwitch = true; break; // case SideFlags.IsLightedSwitch: // mss.controlPanel.active = true; // break; case SideFlags.IsRepairSwitch: mss.controlPanel.repairSwitch = true; break; case SideFlags.IsControlPanel: //mss.controlPanel.controlPanel = true; break; case SideFlags.SwitchCanBeDestroyed: mss.controlPanel.canBeDestroyed = true; break; case SideFlags.SwitchCanOnlyBeHitByProjectiles: mss.controlPanel.canOnlyBeHitByProjectiles = true; break; } } //connedtion information is used for occlusion culling seg.sides.Add(mss); if (Line[currentLine].ClockwisePolygonOwner == p) { mss.connectionID = Line[currentLine].CounterclockwisePolygonOwner; } else { mss.connectionID = Line[currentLine].ClockwisePolygonOwner; } pt = Mathf.Abs(pt - 1); lastPt = ei[pt]; //find next line that connects to the endpoint of this one to make the next side Line.RemoveAt(currentLine); for (int i = 0; i < Line.Count; i++) { if (Line[i].EndpointIndexes[0] == ei[pt] || Line[i].EndpointIndexes[1] == ei[pt]) { currentLine = i; } } } //get floor and ceiling texture data seg.ceiling.upperMaterial = getTexture(Level.Polygons[p].CeilingTexture); seg.floor.upperMaterial = getTexture(Level.Polygons[p].FloorTexture); seg.ceiling.upperOffset = new Vector2((float)Level.Polygons[p].CeilingOrigin.X / 1024f, (float)Level.Polygons[p].CeilingOrigin.Y / 1024f); seg.floor.upperOffset = new Vector2((float)Level.Polygons[p].FloorOrigin.X / 1024f, (float)Level.Polygons[p].FloorOrigin.Y / 1024f); seg.ceiling.lightID = Level.Polygons[p].CeilingLight; seg.ceiling.light = lights[Level.Polygons[p].CeilingLight]; seg.floor.lightID = Level.Polygons[p].FloorLight; seg.floor.light = lights[Level.Polygons[p].FloorLight]; seg.vertices = points; seg.centerPoint = new Vector3(0, (float)Level.Polygons[p].FloorHeight / 1024f, 0); seg.id = p; //convert points to be relative to the polygon average point seg.calculatePoints(); if (p % 77 == 0) { loadingText = load + "\nGenerating Polygons " + p + "/" + Level.Polygons.Count; yield return(null); } } load = load + "\nGenerating Polygons " + Level.Polygons.Count + "/" + Level.Polygons.Count; //if a polygon is a platform we need to change its floor/ceiling heights to actually be //the volume that the platform would be moving up and down in if it were an actual //object - which it will be. int count = 0; foreach (Weland.Platform pl in Level.Platforms) { count++; segments[pl.PolygonIndex].recalculatePlatformVolume(); if (count % 7 == 0) { loadingText = load + "\nRecalculate Platform Volumes " + count + "/" + Level.Platforms.Count; yield return(null); } } load = load + "\nRecalculate Platform Volumes " + count + "/" + Level.Platforms.Count; count = 0; foreach (MapSegment s in segments) { count++; s.generateMeshes(); if (count % 77 == 0) { loadingText = load + "\nGenerating Meshes " + count + "/" + segments.Count; yield return(null); } } load = load + "\nGenerating Meshes " + count + "/" + segments.Count; count = 0; foreach (MapSegment s in segments) { count++; s.checkIfImpossible(); if (count % 77 == 0) { loadingText = load + "\nFinding Impossible Space " + count + "/" + segments.Count; yield return(null); } } load = load + "\nFinding Impossible Space " + count + "/" + segments.Count; count = 0; string mapHash = CalculateMD5(GlobalData.mapsFilePath); mapHash = Application.persistentDataPath + "/" + mapHash + "-" + mapNo + ".cache"; if (!File.Exists(mapHash)) { activePolygonList apl = new activePolygonList(); apl.activePolygons = new List <bool[]>(); for (int i = 0; i < segments.Count; i++) { count++; segments[i].calculateVisibility(); apl.activePolygons.Add(segments[i].activePolygons); if (!GlobalData.skipOcclusion && count % 7 == 0) { loadingText = load + "\nOcclusion Culling " + count + "/" + segments.Count; yield return(null); } } BinaryFormatter bf = new BinaryFormatter(); FileStream fs = File.Open(mapHash, FileMode.Create); bf.Serialize(fs, apl); fs.Close(); } else { FileStream fs = File.Open(mapHash, FileMode.Open); BinaryFormatter bf = new BinaryFormatter(); activePolygonList apl = (activePolygonList)bf.Deserialize(fs); fs.Close(); for (int i = 0; i < apl.activePolygons.Count; i++) { if (segments.Count > i) { segments[i].activePolygons = apl.activePolygons[i]; } } } load = load + "\nOcclusion Culling " + count + "/" + segments.Count; count = 0; foreach (Weland.Platform pl in Level.Platforms) { count++; segments[pl.PolygonIndex].showHide(true); segments[pl.PolygonIndex].makePlatformObjects(); if (count % 27 == 0) { loadingText = load + "\nMaking Platforms " + count + "/" + Level.Platforms.Count; yield return(null); } } foreach (Weland.Platform pl in Level.Platforms) { if (segments[pl.PolygonIndex].platform.initiallyActive) { segments[pl.PolygonIndex].platform.activate(); } } }