public Object Clone()
 {
     ObjectState state = new ObjectState();
     state.fpsDivider = fpsDivider;
     state.frames = new ArrayList(frames.Count);
     for (int i = 0; i < frames.Count; ++i)
     {
         ExtendedFrame frm = (ExtendedFrame)frames[i];
         state.frames.Add(frm.Clone());
     }
     return state;
 }
 public AdvObject(AdvData data, int numStates)
 {
     mData = data;
     Name = "Object" + (mData.NumObjects + 1);
     mSize = new Vec2i(100, 100);
     for (int state = 0; state < numStates; ++state)
     {
         ObjectState ost = new ObjectState();
         ost.frames = new System.Collections.ArrayList();
         ost.fpsDivider = 20;
         Add(ost);
     }
 }
 public int Add(ObjectState os)
 {
     return mStates.Add(os);
 }
 protected bool readObjectsLoop(StreamReader rdr, int ver_major, int ver_minor, TreeNode parent)
 {
     string str;
     while (!rdr.EndOfStream)
     {
         str = rdr.ReadLine();
         if (rdr.EndOfStream)
             return true;
         if (str.Length < 2)
             continue;
         string rest = str.Substring(2);
         //TODO check
         string[] typename = new string[2];
         int idx = rest.IndexOf(' ');
         typename[0] = rest.Substring(0, idx);
         typename[1] = rest.Substring(idx+1);
         //ITEM
         if (typename[0] == "Item")
         {
             Item it = new Item(mAdv);
             it.Name = typename[1];
             int numStates = STATES_MAX;
             int delim = 2;
             if (ver_major == 2 || (ver_major == 3 && ver_minor == 0))
             {
                 numStates = 1;
                 delim = 1;
             }
             for (int state = 0; state < numStates; ++state)
             {
                 ItemState ist;
                 ist.frames = new System.Collections.ArrayList();
                 ist.scripts = new System.Collections.ArrayList();
                 for (int frames = 0; frames < FRAMES_MAX; ++frames)
                 {
                     str = rdr.ReadLine();
                     if (str.Length > 0)
                     {
                         if (delim == 2)
                         {
                             string[] split = str.Split(';');
                             ist.frames.Add(split[0]);
                             if (split.Length > 1)
                                 ist.scripts.Add(split[1].Replace('\xaf', ';'));
                             else
                                 ist.scripts.Add("");
                         }
                         else
                         {
                             ist.frames.Add(str.Substring(0, str.Length + 1 - delim));
                             ist.scripts.Add("");
                         }
                     }
                 }
                 str = rdr.ReadLine();
                 ist.fpsDivider = Convert.ToInt32(str);
                 it.Add(ist);
             }
             if (ver_major == 2 || (ver_major == 3 && ver_minor == 0))
             {
                 for (int i = 1; i < STATES_MAX; ++i)
                 {
                     ItemState ist;
                     ist.frames = new System.Collections.ArrayList();
                     ist.scripts = new System.Collections.ArrayList();
                     ist.fpsDivider = 20;
                     it.Add(ist);
                 }
             }
             mAdv.addItem(it);
         }
         //OBJECT
         else if (typename[0] == "Object")
         {
             AdvObject obj = mAdv.getObject(typename[1]);
             if (obj == null)
             {
                 obj = new AdvObject(mAdv);
                 obj.Name = typename[1];
                 mAdv.addObject(obj);
             }
             str = rdr.ReadLine();
             int x = Convert.ToInt32(str);
             str = rdr.ReadLine();
             int y = Convert.ToInt32(str);
             obj.setSize(0, new Vec2i(x, y));
             str = rdr.ReadLine();
             x = Convert.ToInt32(str);
             obj.Lighten = x != 0;
             for (int state = 0; state < STATES_MAX; ++state)
             {
                 ObjectState os = new ObjectState();
                 os.fpsDivider = readExtendedFrames(rdr, os.frames);
                 obj.Add(os);
             }
         }
         //CHARACTER
         else if (typename[0] == "Character")
         {
             AdvCharacter chr = new AdvCharacter(mAdv);
             chr.Name = typename[1];
             str = rdr.ReadLine();
             chr.TextColor = Convert.ToUInt32(str);
             chr.WalkSpeed = Convert.ToInt32(rdr.ReadLine());
             if (ver_major > 0)
             {
                 int tmp = Convert.ToInt32(rdr.ReadLine());
                 chr.NoZoom = tmp != 0;
                 if (ver_major > 3 || (ver_major == 3 && ver_minor > 0))
                 {
                     tmp = Convert.ToInt32(rdr.ReadLine());
                     chr.RealLeftAnimations = tmp != 0;
                 }
                 tmp = Convert.ToInt32(rdr.ReadLine());
                 chr.MemoryReistent = tmp != 0;
                 tmp = Convert.ToInt32(rdr.ReadLine());
                 chr.Ghost = tmp != 0;
                 chr.Walksound = rdr.ReadLine();
             }
             if (ver_major >= 3)
             {
                 str = rdr.ReadLine();
                 string[] names = str.Split(';');
                 for (int i = 0; i < names.Length - 1; ++i)
                 {
                     chr.setStateName(16 + i, names[i]);
                 }
             }
             else
             {
                 for (int i = 0; i < 20; ++i)
                     chr.setStateName(16 + i, "");
             }
             if (ver_major > 0)
             {
                 chr.Font = Convert.ToInt32(rdr.ReadLine());
                 chr.Zoom = Convert.ToInt32(rdr.ReadLine());
             }
             else
                 chr.Zoom = 100;
             for (int state = 0; state < CHAR_STATES_MAX; ++state)
             {
                 CharacterState cs = new CharacterState();
                 cs.size.x = Convert.ToInt32(rdr.ReadLine());
                 cs.size.y = Convert.ToInt32(rdr.ReadLine());
                 cs.basepoint.x = Convert.ToInt32(rdr.ReadLine());
                 cs.basepoint.y = Convert.ToInt32(rdr.ReadLine());
                 cs.fpsDivider = readExtendedFrames(rdr, cs.frames);
                 chr.Add(cs);
             }
             mAdv.addCharacter(chr);
         }
         //CHARACTER INSTANCE
         else if (typename[0] == "Rcharacter")
         {
             string chr = rdr.ReadLine();
             CharacterInstance charinst = new CharacterInstance(mAdv.getCharacter(chr), mAdv);
             if (charinst.Character == null)
                 throw new UnexpectedValueException("No character for character instance found");
             charinst.Name = typename[1];
             charinst.Room = rdr.ReadLine();
             Vec2i pos;
             pos.x = Convert.ToInt32(rdr.ReadLine());
             pos.y = Convert.ToInt32(rdr.ReadLine());
             charinst.RawPosition = pos;
             charinst.LookDir = Convert.ToInt32(rdr.ReadLine());
             charinst.Unmovable = Convert.ToInt32(rdr.ReadLine()) == 0;
             charinst.Locked = Convert.ToInt32(rdr.ReadLine()) != 0;
             if (!mAdv.CharacterInstances.ContainsKey(charinst.Room.ToLower()))
             {
                 mAdv.CharacterInstances[charinst.Room.ToLower()] = new System.Collections.ArrayList();
             }
             mAdv.CharacterInstances[charinst.Room.ToLower()].Add(charinst);
         }
         //ROOM
         else if (typename[0] == "Room")
         {
             Room room = new Room();
             room.Data = mAdv;
             room.Name = typename[1];
             room.Size.x = Convert.ToInt32(rdr.ReadLine());
             room.Size.y = Convert.ToInt32(rdr.ReadLine());
             room.ScrollOffset.x = Convert.ToInt32(rdr.ReadLine());
             room.ScrollOffset.y = Convert.ToInt32(rdr.ReadLine());
             room.Depthmap.x = Convert.ToInt32(rdr.ReadLine());
             room.Depthmap.y = Convert.ToInt32(rdr.ReadLine());
             room.Zoom = Convert.ToInt32(rdr.ReadLine());
             room.Background = rdr.ReadLine();
             room.ParallaxBackground = rdr.ReadLine();
             room.FXShapes = new System.Collections.ArrayList();
             if (ver_major >= 3)
             {
                 int tmp = Convert.ToInt32(rdr.ReadLine());
                 room.DoubleWalkmap = tmp != 0;
             }
             else
             {
                 room.DoubleWalkmap = false;
             }
             if (ver_major > 3 || (ver_major == 3 && ver_minor >= 5))
             {
                 str = rdr.ReadLine();
                 string[] col = str.Split(';');
                 room.Lighting = Color.FromArgb(Convert.ToInt32(col[0]), Convert.ToInt32(col[1]), Convert.ToInt32(col[2]));
             }
             else
                 room.Lighting = Color.FromArgb(255, 255, 255);
             if (ver_major >= 3 || (ver_major == 2 && ver_minor >= 8))
             {
                 for (int i = 0; i < FXSHAPES_MAX; ++i)
                 {
                     FxShape shape = new FxShape();
                     str = rdr.ReadLine();
                     string[] split = str.Split(';');
                     shape.Active = Convert.ToInt32(split[0]) != 0;
                     shape.DependingOnRoomPosition = Convert.ToInt32(split[1]) != 0;
                     shape.Effect = (FxShape.FxEffect)Convert.ToInt32(rdr.ReadLine());
                     shape.Room = rdr.ReadLine();
                     shape.Depth = Convert.ToInt32(rdr.ReadLine());
                     shape.MirrorOffset.x = Convert.ToInt32(rdr.ReadLine());
                     shape.MirrorOffset.y = Convert.ToInt32(rdr.ReadLine());
                     shape.Strength = Convert.ToInt32(rdr.ReadLine());
                     str = rdr.ReadLine();
                     split = str.Split(';');
                     for (int pos = 0; pos < 4; ++pos)
                     {
                         shape.Positions[pos].x = Convert.ToInt32(split[2 * pos]);
                         shape.Positions[pos].y = Convert.ToInt32(split[2 * pos + 1]);
                     }
                     room.FXShapes.Add(shape);
                 }
             }
             else
             {
                 for (int i = 0; i < FXSHAPES_MAX; ++i)
                 {
                     FxShape fs = new FxShape(i);
                     room.FXShapes.Add(fs);
                 }
             }
             //inventory
             room.HasInventory = Convert.ToInt32(rdr.ReadLine()) != 0;
             str = rdr.ReadLine();
             string[] inventory = str.Split(';');
             room.InvPos.x = Convert.ToInt32(inventory[0]);
             room.InvPos.y = Convert.ToInt32(inventory[1]);
             room.InvSize.x = Convert.ToInt32(inventory[2]);
             room.InvSize.y = Convert.ToInt32(inventory[3]);
             if (ver_major < 3)
             {
                 if (room.InvSize.x == 0 || room.InvSize.y == 0)
                     room.HasInventory = false;
                 else
                     room.HasInventory = true;
             }
             System.Globalization.NumberFormatInfo info = new System.Globalization.NumberFormatInfo();
             info.NumberDecimalSeparator = ",";
             try
             {
                 room.InvScale.x = Single.Parse(inventory[4], info);
                 room.InvScale.y = Single.Parse(inventory[5], info);
             }
             catch (Exception)
             {
                 info.NumberDecimalSeparator = ".";
                 room.InvScale.x = Single.Parse(inventory[4], info);
                 room.InvScale.y = Single.Parse(inventory[5], info);
             }
             if (ver_major > 3 || (ver_major == 3 && ver_minor >= 5)){
                 room.InvSpacing = Convert.ToInt32(inventory[6]);
             }
             else
                 room.InvSpacing = 10;
             //walkmap
             str = rdr.ReadLine();
             int walkmapX = 32;
             int walkGridSize = mAdv.Settings.Resolution.x / walkmapX;
             int walkmapY = mAdv.Settings.Resolution.y / walkGridSize;
             walkmapX *= 3;
             walkmapY *= 2;
             int walkmapXOut = walkmapX * 2;
             int walkmapYOut = walkmapY * 2;
             if (ver_major >= 3)
             {
                 walkmapX *= 2;
                 walkmapY *= 2;
             }
             room.Walkmap = new Room.WalkMapEntry[walkmapXOut, walkmapYOut];
             for (int i = 0; i < walkmapX * walkmapY; ++i)
             {
                 int x = i / walkmapY;
                 int y = i % walkmapY;
                 room.Walkmap[x, y].isFree = str[2 * i] != '1';
                 room.Walkmap[x, y].hasScript = str[2 * i + 1] == '1';
             }
             if (mAdv.CharacterInstances.ContainsKey(room.Name.ToLower()))
                 room.Characters = mAdv.CharacterInstances[room.Name.ToLower()];
             mAdv.addRoom(room);
             mLastRoom = room;
         }
         //OBJECT INSTANCE
         else if (typename[0] == "Roomobject")
         {
             string obj = rdr.ReadLine();
             AdvObject newobj = mAdv.getObject(obj);
             if (newobj == null)
             {
                 //this happens during room import
                 newobj = new AdvObject(mAdv);
                 newobj.Name = obj;
                 mAdv.addObject(newobj);
                 //auto add objects
                 if (parent != null)
                 {
                     TreeNode tno = new TreeNode(obj);
                     tno.Tag = ResourceID.OBJECT;
                     tno.ImageIndex = Utilities.ResourceIDToImageIndex((ResourceID)tno.Tag);
                     tno.SelectedImageIndex = tno.ImageIndex;
                     parent.Nodes.Add(tno);
                 }
             }
             ObjectInstance objinst = new ObjectInstance(mAdv.getObject(obj), mAdv);
             objinst.Name = typename[1];
             objinst.Position.x = Convert.ToInt32(rdr.ReadLine());
             objinst.Position.y = Convert.ToInt32(rdr.ReadLine());
             objinst.State = Convert.ToInt32(rdr.ReadLine());
             objinst.Layer = Convert.ToInt32(rdr.ReadLine());
             objinst.Depth = Convert.ToInt32(rdr.ReadLine())*2;
             if (ver_major > 3 || (ver_major == 3 && ver_minor >= 5))
             {
                 objinst.Depth = Convert.ToInt32(rdr.ReadLine());
             }
             objinst.Locked = Convert.ToInt32(rdr.ReadLine()) != 0;
             mLastRoom.Objects.Add(objinst);
         }
     }
     return true;
 }