//TODO: Fade public static void LoadMap(GraphicsDevice graphics, int id, string spawn = "") { if (id == 999999999) // This is used to tell it not to load a new map.. return; sw.Restart(); MapLoaded = false; if (graphics != null) _device = graphics; if (Constants.Globals.Player == null) { Constants.Globals.Player = new MapleCharacter(MapleCharacter.CharacterColor.Light, 20000, 33400, _device); Constants.Globals.Player.SetTop(graphics, 1040002); } MapleMap map = new MapleMap(); map.MapID = id; MapleConsole.Write(MapleConsole.LogType.MESSAGE, "Loading Map \"" + map.FormattedMapID + "\"."); string path = "Map/Map" + map.FormattedMapID.Substring(0, 1) + "/" + map.FormattedMapID + ".img"; WZFile mapWz = new WZFile("Map.wz", WZVariant.GMS, true, WZReadSelection.LowMemory); try { mapWz.ResolvePath(path); } // Make sure the map exists catch (Exception) { MapleConsole.Write(MapleConsole.LogType.ERROR, "Map Doesn't Exist!"); return; } if (!Constants.Game.MuteMusic) MusicEngine.LoadMusic(mapWz.ResolvePath(path + "/info/bgm").ValueOrDefault<string>("")); // Load the music // TODO: Get map name bool boundsDefined = false; try { map.Top = mapWz.ResolvePath(path + "/info/VRTop").ValueOrDefault<int>(0); map.Bottom = mapWz.ResolvePath(path + "/info/VRBottom").ValueOrDefault<int>(0); map.Left = mapWz.ResolvePath(path + "/info/VRLeft").ValueOrDefault<int>(0); map.Right = mapWz.ResolvePath(path + "/info/VRRight").ValueOrDefault<int>(0); boundsDefined = true; } catch (Exception) { // TODO: Find out the coords for maps that don't tell you the camera limit.. //map.Top = 0; //map.Bottom = map.Top + 2009; // I got these values from orbis but I'm not sure whats going to happen on other maps.. } map.Width = map.Right - map.Left; map.Height = map.Bottom - map.Top; map.HideMinimap = mapWz.ResolvePath(path + "/info/hideMinimap").ValueOrDefault<int>(1) == 1 ? true : false; //int miniw = mapWz.ResolvePath(path + "/miniMap/width").ValueOrDefault<int>(0); //int minih = mapWz.ResolvePath(path + "/miniMap/height").ValueOrDefault<int>(0); // Set the global portal animation if its null if (Constants.Globals.PortalAnimation == null) { Dictionary<int, MapleFrame> frames = new Dictionary<int, MapleFrame>(); foreach (WZCanvasProperty frame in mapWz.ResolvePath("MapHelper.img/portal/game/pv")) { WZPointProperty offset = (WZPointProperty)frame["origin"]; frames.Add(int.Parse(frame.Name), new MapleFrame( new MapleCanvas(Tools.BitmapToTexture(_device, frame.Value), new Vector2(-offset.Value.X, -offset.Value.Y)), 100)); // wtf.. The portal frame delay isn't in the wz files?! } Constants.Globals.PortalAnimation = new MapleAnimation(frames); } #region Load Footholds foreach (WZObject fsp in mapWz.ResolvePath(path + "/foothold")) foreach (WZObject fs in fsp) foreach (WZObject fh in fs) { map.Footholds.Add(new MapleFoothold(int.Parse(fh.Name), new Vector2(fh["x1"].ValueOrDie<int>(), fh["y1"].ValueOrDie<int>()), new Vector2(fh["x2"].ValueOrDie<int>(), fh["y2"].ValueOrDie<int>()), int.Parse(fsp.Name))); } #endregion #region Load Backgrounds foreach (WZObject bg in mapWz.ResolvePath(path + "/back")) { if (bg is WZSubProperty && Tools.IsNumeric(bg.Name)) { try { string fPath = "Back/" + bg["bS"].ValueOrDefault<string>("") + ".img/back/" + bg["no"].ValueOrDefault<int>(0); WZCanvasProperty frame = (WZCanvasProperty)mapWz.ResolvePath(fPath); WZPointProperty origin = (WZPointProperty)frame["origin"]; Dictionary<int, MapleFrame> bgs = new Dictionary<int, MapleFrame>(); bool isBack = bg["no"].ValueOrDefault<int>(-1) == 0; if (!Constants.Globals.BackCache.ContainsKey(fPath)) Constants.Globals.BackCache.Add(fPath, Tools.BitmapToTexture(_device, frame.Value)); // TODO: Animated backgrounds.. // Again these algorithms are guessed.. Took me hours to get it realistic.. I pretty much just added random shit onto it XD float newX = bg["x"].ValueOrDefault<int>(0) - bg["rx"].ValueOrDefault<int>(0) / 100 * (map.Width + (_device.Viewport.Width / 2)) + (map.Left * 1.65f); float newY = bg["y"].ValueOrDefault<int>(0) - 100 + bg["ry"].ValueOrDefault<int>(0) / 100 * (map.Height + (_device.Viewport.Height / 2)) + map.Top + (map.Height - 300); // 300.. random if (isBack) { newX = map.Left; newY = map.Top; } bgs.Add(0, new MapleFrame(new MapleCanvas(Constants.Globals.BackCache[fPath], new Vector2(-origin.Value.X, -origin.Value.Y)), 100)); if (newX + -origin.Value.X > map.BackWidth) { int bW = (int)Math.Ceiling(newX); map.BackWidth = bW + -origin.Value.X; } if (-newY + -origin.Value.Y > map.BackHeight) // Somethings up with this o.o why do we need to make newY negative? { int bH = (int)Math.Ceiling(-newY); map.BackHeight = bH + -origin.Value.Y; } map.Backgrounds.Add(new MapleBackground(int.Parse(bg.Name), new MapleAnimation(bgs), new Vector2(newX, newY), bg["type"].ValueOrDie<int>(), isBack)); } catch (Exception) { continue; } } } #endregion #region Load Tiles/Objects foreach (WZObject wLayer in mapWz.ResolvePath(path)) { if (wLayer is WZSubProperty && Tools.IsNumeric(wLayer.Name)) { string tS = ""; List<MapleTile> tiles = new List<MapleTile>(); List<MapleObject> objs = new List<MapleObject>(); bool hasSetBounds = false; foreach (WZSubProperty item in wLayer) { switch (item.Name) { case "info": if (item.ChildCount > 0) tS = item["tS"].ValueOrDefault<string>(""); break; case "obj": foreach (WZObject wObj in item) { string oS = wObj["oS"].ValueOrDie<string>(); string l0 = wObj["l0"].ValueOrDie<string>(); string l1 = wObj["l1"].ValueOrDie<string>(); string l2 = wObj["l2"].ValueOrDie<string>(); string objPath = "Obj/" + oS + ".img/" + l0 + "/" + l1 + "/" + l2; if (l1 == "cherryBlossom") // Skip this shit.. its all over henesys.. continue; Dictionary<int, MapleFrame> frames = new Dictionary<int, MapleFrame>(); int z = wObj["z"].ValueOrDefault<int>(0); foreach (WZObject oF in mapWz.ResolvePath(objPath)) { if (oF is WZCanvasProperty && Tools.IsNumeric(oF.Name)) { try { WZPointProperty offset = null; int frameDelay = 150; if (!Constants.Globals.ObjectCache.ContainsKey(objPath + "/" + oF.Name)) Constants.Globals.ObjectCache.Add(objPath + "/" + oF.Name, Tools.BitmapToTexture(_device, ((WZCanvasProperty)oF).Value)); foreach (WZObject o in oF) if (o.Name == "origin") offset = (WZPointProperty)o; else if (o.Name == "delay") frameDelay = o.ValueOrDefault<int>(150); frames.Add(int.Parse(oF.Name), new MapleFrame(new MapleCanvas(Constants.Globals.ObjectCache[objPath + "/" + oF.Name], (offset != null) ? new Vector2(-offset.Value.X, -offset.Value.Y) : Vector2.Zero), frameDelay)); } catch (Exception ex) { MapleConsole.Write(MapleConsole.LogType.ERROR, "Error loading object \"" + objPath + "\": " + ex.Message); } } } objs.Add(new MapleObject(new Vector2(wObj["x"].ValueOrDefault<int>(0), wObj["y"].ValueOrDefault<int>(0)), z, new MapleAnimation(frames), int.Parse(wLayer.Name))); } break; case "tile": foreach (WZObject wTile in item) { MapleCanvas tileTex = null; Vector2 tileLoc = Vector2.Zero; string tilePath = "Tile/" + tS + ".img/" + wTile["u"].ValueOrDie<string>() + "/" + wTile["no"].ValueOrDefault<int>(0).ToString(); WZCanvasProperty tileCanvas = (WZCanvasProperty)mapWz.ResolvePath(tilePath); if (!Constants.Globals.TileCache.ContainsKey(tilePath)) Constants.Globals.TileCache.Add(tilePath, Tools.BitmapToTexture(_device, tileCanvas.Value)); WZPointProperty tOrigin = (WZPointProperty)tileCanvas["origin"]; tileTex = new MapleCanvas(Constants.Globals.TileCache[tilePath], new Vector2(-tOrigin.Value.X, -tOrigin.Value.Y)); tileLoc = new Vector2(wTile["x"].ValueOrDefault<int>(0), wTile["y"].ValueOrDefault<int>(0)); if (!boundsDefined) { // TODO Fix this.. if (!hasSetBounds) { map.Left = (int)tileLoc.X; map.Right = (int)tileLoc.X + tileTex.Texture.Width; map.Top = (int)tileLoc.Y; map.Bottom = (int)tileLoc.Y + tileTex.Texture.Height; hasSetBounds = true; } else { if (tileLoc.X < map.Left) map.Left = (int)tileLoc.X + -tOrigin.Value.X; if (tileLoc.X + tileTex.Texture.Width > map.Right) map.Right = (int)tileLoc.X + tileTex.Texture.Width + -tOrigin.Value.X; if (tileLoc.Y < map.Top) map.Top = (int)tileLoc.Y + -tOrigin.Value.Y; if (tileLoc.Y + tileTex.Texture.Height > map.Bottom) map.Bottom = (int)tileLoc.Y + tileTex.Texture.Height + -tOrigin.Value.Y; } } tiles.Add(new MapleTile(tileTex, tileLoc, int.Parse(wTile.Name))); } break; default: //lolwut o.o MapleConsole.Write(MapleConsole.LogType.WARNING, "Invalid Layer Property \"" + item.Name + "\"."); break; } } map.Layers.Add(int.Parse(wLayer.Name),new MapleLayer(int.Parse(wLayer.Name), tS, tiles, objs)); } } #endregion MapleConsole.Write(MapleConsole.LogType.WARNING, "Left: " + map.Left.ToString() + " - Top: " + map.Top.ToString() + " - Right: " + map.Right.ToString() + " - Bottom: " + map.Bottom.ToString()); #region Load Portals foreach (WZObject portal in mapWz.ResolvePath(path + "/portal")) { int pType = portal["pt"].ValueOrDefault<int>(-1); int pTo = portal["tm"].ValueOrDefault<int>(999999999); string script = ""; try { script = portal["script"].ValueOrDefault<string>(""); } catch (Exception) { } if (pTo == map.MapID || (pTo == 999999999 && script == "")) pType = 9; map.Portals.Add(new MaplePortal(portal["pn"].ValueOrDefault<string>(""), script, portal["tn"].ValueOrDefault<string>(""), new Vector2(portal["x"].ValueOrDefault<int>(0), portal["y"].ValueOrDefault<int>(0)), pTo, pType)); } #endregion #region Load Life WZFile npcWz = new WZFile("Npc.wz", WZVariant.GMS, true, WZReadSelection.LowMemory); WZFile mobWz = new WZFile("Mob.wz", WZVariant.GMS, true, WZReadSelection.LowMemory); foreach (WZObject life in mapWz.ResolvePath(path + "/life")) { if (life is WZSubProperty) { string type = life["type"].ValueOrDefault<string>(""); int lifeId = int.Parse(life["id"].ValueOrDie<string>()); if (lifeId == 9300018) continue; switch (type) { case "n": // NPC string lifePath = lifeId.ToString() + ".img"; Dictionary<int, MapleFrame> ani = new Dictionary<int, MapleFrame>(); try { foreach (WZObject f in npcWz.ResolvePath(lifePath + "/stand")) { if (f is WZCanvasProperty) { if (!Constants.Globals.LifeCache.ContainsKey(lifePath + "/stand/" + f.Name)) Constants.Globals.LifeCache.Add(lifePath + "/stand/" + f.Name, Tools.BitmapToTexture(_device, f.ValueOrDie<System.Drawing.Bitmap>())); WZPointProperty origin = (WZPointProperty)npcWz.ResolvePath(lifePath + "/stand/" + f.Name)["origin"]; int delay = 100; try { delay = f["delay"].ValueOrDefault<int>(100); } catch (Exception) { } ani.Add(int.Parse(f.Name), new MapleFrame(new MapleCanvas(Constants.Globals.LifeCache[lifePath + "/stand/" + f.Name], new Vector2(-origin.Value.X, -origin.Value.Y)), delay)); } } } catch (Exception) { continue; } bool hide = false; try { hide = life["hide"].ValueOrDefault<int>(1) == 0; } catch (Exception) { } int Layer = map.Footholds.Where(o => o.ID == life["fh"].ValueOrDefault<int>(7)).ToArray<MapleFoothold>()[0].Layer; map.Npcs.Add(new MapleNpc(lifeId, new MapleAnimation(ani), new Vector2(life["x"].ValueOrDefault<int>(0), life["cy"].ValueOrDefault<int>(0) + 0), Layer, !hide)); // Why is this 10px off? o.o break; case "m": // Mob break; default: // o.o MapleConsole.Write(MapleConsole.LogType.WARNING, "Invalid Life Type \"" + type + "\"."); break; } } } #endregion // Load strings from string.wz.. #region Load Strings #endregion if (!map.HideMinimap) { try { InterfaceEngine.MiniMap = new MapleMinimap(map, Tools.BitmapToTexture(_device, mapWz.ResolvePath(path + "/miniMap/canvas").ValueOrDie<System.Drawing.Bitmap>())); } catch (Exception) { map.HideMinimap = true; } } CurrentMap = map; Camera.Set(map.Left, map.Top); // Set camera inside map bounds.. TODO: Spawn Points Vector2 pOrigin = new Vector2(Constants.Globals.PortalAnimation.Frames[0].Canvas.Origin.X / 2, Constants.Globals.PortalAnimation.Frames[0].Canvas.Origin.Y / 2); if (spawn != "") Constants.Globals.Player.Position = map.Portals.Where(o => o.PortalName == spawn).ToArray<MaplePortal>()[0].Location + pOrigin; else Constants.Globals.Player.Position = map.Portals.Where(o => o.PortalName == "sp").ToArray<MaplePortal>()[0].Location + pOrigin; sw.Stop(); MapleConsole.Write(MapleConsole.LogType.MESSAGE, "Map loaded in " + sw.ElapsedMilliseconds.ToString() + "ms."); Constants.Globals.Player.CenterCamera(); MapLoaded = true; }
public MapleFrame(MapleCanvas c, int del) { Canvas = c; Delay = del; }
public MapleCharacter(CharacterColor c, int face, int hair, GraphicsDevice graphics) { try { SkinColor = c; WZFile charWz = new WZFile("Character.wz", WZVariant.GMS, true, WZReadSelection.LowMemory); string path = ((int)SkinColor).ToString("00000000") + ".img"; WZCanvasProperty h = (WZCanvasProperty)charWz.ResolvePath(((int)SkinColor).ToString("00010000") + ".img/front/head"); WZPointProperty o = (WZPointProperty)h["origin"]; Head = new MapleCanvas(Tools.BitmapToTexture(graphics, h.Value), new Vector2(-o.Value.X, -o.Value.Y)); Bounds.X = -o.Value.X; Bounds.Y = -o.Value.Y; WZPointProperty neckPos = (WZPointProperty)h["map"]["neck"]; NeckPosition = new Vector2(neckPos.Value.X, neckPos.Value.Y); foreach (CharacterState state in Enum.GetValues(typeof(CharacterState))) // Loop through the states and get the frames for each animation.. { Dictionary<int, MapleFrame> bodyState = new Dictionary<int, MapleFrame>(); Dictionary<int, MapleFrame> armState = new Dictionary<int, MapleFrame>(); foreach (WZObject frame in charWz.ResolvePath(path + "/" + States[(int)state])) if (Tools.IsNumeric(frame.Name)) { int delay = frame["delay"].ValueOrDefault<int>(250); Vector2 bodyNavel = Vector2.Zero; Vector2 frameNeckPos = Vector2.Zero; bool ani = Ani[(int)state]; foreach (WZObject part in frame) { WZObject p = part; if (p is WZCanvasProperty) { Texture2D PartTexture = Tools.BitmapToTexture(graphics, p.ValueOrDie<System.Drawing.Bitmap>()); WZPointProperty origin = (WZPointProperty)p["origin"]; switch (p.Name) { case "body": WZPointProperty navel = (WZPointProperty)p["map"]["navel"]; WZPointProperty neck = (WZPointProperty)p["map"]["neck"]; Navel.Add(States[(int)state] + frame.Name, new Vector2(-navel.Value.X, -navel.Value.Y)); bodyNavel = new Vector2(navel.Value.X, navel.Value.Y); frameNeckPos = new Vector2(-neck.Value.X, -neck.Value.Y); Vector2 BodyLoc = new Vector2(-origin.Value.X + frameNeckPos.X + NeckPosition.X, -origin.Value.Y + frameNeckPos.Y + NeckPosition.Y); bodyState.Add(bodyState.Count, new MapleFrame(new MapleCanvas(PartTexture, BodyLoc), delay)); break; case "arm": WZPointProperty armNavel = (WZPointProperty)p["map"]["navel"]; Vector2 ArmLoc = new Vector2((-origin.Value.X + -armNavel.Value.X - -bodyNavel.X) + frameNeckPos.X + NeckPosition.X, (-origin.Value.Y + -armNavel.Value.Y - -bodyNavel.Y) + frameNeckPos.Y + NeckPosition.Y); armState.Add(armState.Count, new MapleFrame(new MapleCanvas(PartTexture, ArmLoc), delay)); break; } } } if (ani == false) break; } Body.Add(state, new MapleAnimation(bodyState, true)); Arm.Add(state, new MapleAnimation(armState)); if (Hair.ContainsKey(HairStates[(int)state])) continue; // Hair string hairPath = "Hair/" + hair.ToString("00000000") + ".img"; Dictionary<int, MapleFrame> hf = new Dictionary<int, MapleFrame>(); Dictionary<int, MapleFrame> hfh = new Dictionary<int, MapleFrame>(); WZCanvasProperty hairCanvas = (WZCanvasProperty)charWz.ResolvePath(hairPath + "/" + HairStates[(int)state] + "/hairOverHead"); WZPointProperty hairOrigin = (WZPointProperty)hairCanvas["origin"]; WZCanvasProperty hhatCanvas = (WZCanvasProperty)charWz.ResolvePath(hairPath + "/" + HairStates[(int)state] + "/hair"); WZPointProperty hhatOrigin = (WZPointProperty)hhatCanvas["origin"]; hf.Add(hf.Count, new MapleFrame(new MapleCanvas(Tools.BitmapToTexture(graphics, hairCanvas.Value), new Vector2(-hairOrigin.Value.X - 2, -hairOrigin.Value.Y - 5)), 100)); hfh.Add(hfh.Count, new MapleFrame(new MapleCanvas(Tools.BitmapToTexture(graphics, hhatCanvas.Value), new Vector2(-hhatOrigin.Value.X - 2, -hhatOrigin.Value.Y - 5)), 100)); Hair.Add(HairStates[(int)state], new MapleAnimation(hf)); HatHair.Add(HairStates[(int)state], new MapleAnimation(hfh)); } // Face string facePath = "Face/" + face.ToString("00000000") + ".img"; Dictionary<int, MapleFrame> ff = new Dictionary<int, MapleFrame>(); foreach (WZObject fs in charWz.ResolvePath(facePath + "/default")) // TODO Other expressions { if (fs is WZCanvasProperty && fs.Name == "face") { WZPointProperty faceOrigin = (WZPointProperty)fs["origin"]; ff.Add(ff.Count, new MapleFrame(new MapleCanvas(Tools.BitmapToTexture(graphics, fs.ValueOrDie<System.Drawing.Bitmap>()), new Vector2(-faceOrigin.Value.X - 3, -faceOrigin.Value.Y + 7)), 0)); } } Face = new MapleAnimation(ff); } catch (Exception ex) { MapleConsole.Write(MapleConsole.LogType.ERROR, "Error initializing character: " + ex.Message); MapleConsole.Write(MapleConsole.LogType.WARNING, "StackTrace", ex.StackTrace); } }