예제 #1
0
        protected override Drawable MakeDrawable(string objName)
        {
            Drawable drawable;
            var      rulesSection   = Rules.GetOrCreateSection(objName);
            string   artSectionName = rulesSection.ReadString("Image", objName);
            var      artSection     = Art.GetOrCreateSection(artSectionName);

            switch (Type)
            {
            case CollectionType.Aircraft:
            case CollectionType.Vehicle:
                drawable = new UnitDrawable(rulesSection, artSection);
                break;

            case CollectionType.Building:
                drawable = new BuildingDrawable(rulesSection, artSection);
                break;

            case CollectionType.Infantry:
            case CollectionType.Overlay:
            case CollectionType.Smudge:
            case CollectionType.Terrain:
                drawable = new ShpDrawable(rulesSection, artSection);
                break;

            case CollectionType.Animation:
                drawable = new AnimDrawable(rulesSection, artSection);
                break;

            default:
                throw new InvalidEnumArgumentException();
            }
            return(drawable);
        }
예제 #2
0
		protected override Drawable MakeDrawable(string objName) {
			Drawable drawable;
			var rulesSection = Rules.GetOrCreateSection(objName);
			string artSectionName = rulesSection.ReadString("Image", objName);
			var artSection = Art.GetOrCreateSection(artSectionName);

			switch (Type) {
				case CollectionType.Aircraft:
				case CollectionType.Vehicle:
					drawable = new UnitDrawable(rulesSection, artSection);
					break;
				case CollectionType.Building:
					drawable = new BuildingDrawable(rulesSection, artSection);
					break;
				case CollectionType.Infantry:
				case CollectionType.Overlay:
				case CollectionType.Smudge:
				case CollectionType.Terrain:
					drawable = new ShpDrawable(rulesSection, artSection);
					break;
				case CollectionType.Animation:
					drawable = new AnimDrawable(rulesSection, artSection);
					break;
				default:
					throw new InvalidEnumArgumentException();
			}
			return drawable;
		}
예제 #3
0
        public override void LoadFromRules()
        {
            base.LoadFromArtEssential();

            if (IsVoxel)
            {
                var vxl = new VoxelDrawable(Rules, Art);
                vxl.OwnerCollection = OwnerCollection;
                vxl.Props           = Props;
                vxl.LoadFromRules();
                vxl.Vxl = VFS.Open <VxlFile>(vxl.Image + ".vxl");
                vxl.Hva = VFS.Open <HvaFile>(vxl.Image + ".hva");
                SubDrawables.Add(vxl);
            }
            else
            {
                var shp = new ShpDrawable(Rules, Art);
                shp.Props           = Props;
                shp.OwnerCollection = OwnerCollection;
                shp.LoadFromRules();
                shp.Shp = VFS.Open <ShpFile>(shp.GetFilename());
                shp.Props.FrameDecider = FrameDeciders.SHPVehicleFrameDecider(shp.StartStandFrame, shp.StandingFrames, shp.Facings);
                if (Ready_Start != -1 && Ready_Count != -1 && Ready_CountNext != -1)
                {
                    shp.Props.FrameDecider = FrameDeciders.InfantryFrameDecider(Ready_Start, Ready_Count, Ready_CountNext);
                }
                SubDrawables.Add(shp);
            }

            if (Rules.ReadBool("Turret") && IsVoxel)
            {
                var turretVxl = VFS.Open <VxlFile>(Image + "TUR.vxl");
                var turretHva = VFS.Open <HvaFile>(Image + "TUR.hva");
                var turret    = new VoxelDrawable(turretVxl, turretHva);
                turret.Props.Offset            = Props.Offset;
                turret.Props.Offset           += new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
                turret.Props.TurretVoxelOffset = Art.ReadFloat("TurretOffset");
                SubDrawables.Add(turret);

                var barrelVxl = VFS.Open <VxlFile>(Image + "BARL.vxl");
                var barrelHva = VFS.Open <HvaFile>(Image + "BARL.hva");
                if (barrelVxl != null && barrelHva != null)
                {
                    var barrel = new VoxelDrawable(barrelVxl, barrelHva);
                    barrel.Props = turret.Props;
                    SubDrawables.Add(barrel);
                }
            }
        }
예제 #4
0
        public override void LoadFromRules()
        {
            base.LoadFromArtEssential();

            if (IsVoxel)
            {
                var vxl = new VoxelDrawable(Rules, Art);
                vxl.OwnerCollection = OwnerCollection;
                vxl.Props           = Props;
                vxl.LoadFromRules();
                vxl.Vxl = VFS.Open <VxlFile>(vxl.Image + ".vxl");
                vxl.Hva = VFS.Open <HvaFile>(vxl.Image + ".hva");
                SubDrawables.Add(vxl);
            }
            else
            {
                var shp = new ShpDrawable(Rules, Art);
                shp.Props           = Props;
                shp.OwnerCollection = OwnerCollection;
                shp.LoadFromRules();
                shp.Shp = VFS.Open <ShpFile>(shp.GetFilename());
                SubDrawables.Add(shp);
            }

            if (Rules.ReadBool("Turret") && IsVoxel)
            {
                var turretVxl = VFS.Open <VxlFile>(Image + "TUR.vxl");
                var turretHva = VFS.Open <HvaFile>(Image + "TUR.hva");
                var turret    = new VoxelDrawable(turretVxl, turretHva);
                turret.Props.Offset            = Props.Offset;
                turret.Props.Offset           += new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
                turret.Props.TurretVoxelOffset = Art.ReadFloat("TurretOffset");
                SubDrawables.Add(turret);

                var barrelVxl = VFS.Open <VxlFile>(Image + "BARL.vxl");
                var barrelHva = VFS.Open <HvaFile>(Image + "BARL.hva");
                if (barrelVxl != null && barrelHva != null)
                {
                    var barrel = new VoxelDrawable(barrelVxl, barrelHva);
                    barrel.Props = turret.Props;
                    SubDrawables.Add(barrel);
                }
            }
        }
예제 #5
0
        private void LoadSimpleDrawable(ShpDrawable drawable)
        {
            InitDrawableDefaults(drawable);
            drawable.LoadFromRules();

            string shpFile = drawable.GetFilename();

            drawable.Shp = VFS.Open <ShpFile>(shpFile);

            if (Type == CollectionType.Smudge)
            {
                drawable.Foundation = new Size(drawable.Rules.ReadInt("Width", 1), drawable.Rules.ReadInt("Height", 1));
            }

            if (Type == CollectionType.Overlay)
            {
                LoadOverlayDrawable(drawable);
            }
        }
예제 #6
0
        public override void Draw(GameObject obj, DrawingSurface ds, bool shadows = true)
        {
            terrainShp = new ShpDrawable(Rules, Art);
            terrainShp.OwnerCollection = OwnerCollection;
            terrainShp.LoadFromArtEssential();
            terrainShp.Props = Props;
            terrainShp.Shp   = VFS.Open <ShpFile>(terrainShp.GetFilename());

            foreach (var sub in SubDrawables.OfType <AlphaDrawable>())
            {
                sub.Draw(obj, ds, false);
            }

            if (shadows)
            {
                terrainShp.DrawShadow(obj, ds);
            }
            terrainShp.Draw(obj, ds, false);
        }
예제 #7
0
        private void LoadOverlayDrawable(ShpDrawable drawable)
        {
            var            ovl     = new OverlayObject((byte)drawable.Index, 0);
            var            tibType = SpecialOverlays.GetOverlayTibType(ovl, Engine);
            DrawProperties props   = drawable.Props;

            if (Engine >= EngineType.RedAlert2)
            {
                if (tibType != OverlayTibType.NotSpecial)
                {
                    props.FrameDecider = FrameDeciders.OverlayValueFrameDecider;
                    props.PaletteType  = PaletteType.Overlay;
                    props.LightingType = LightingType.None;
                }
                else if (SpecialOverlays.IsHighBridge(ovl))
                {
                    props.OffsetHack       = OffsetHacks.RA2BridgeOffsets;
                    props.ShadowOffsetHack = OffsetHacks.RA2BridgeShadowOffsets;
                    drawable.TileElevation = 4;                     // for lighting
                    drawable.Foundation    = new Size(3, 1);        // ensures they're drawn later --> fixes overlap
                }
            }
            else if (Engine <= EngineType.Firestorm)
            {
                if (tibType != OverlayTibType.NotSpecial)
                {
                    props.FrameDecider   = FrameDeciders.OverlayValueFrameDecider;
                    props.PaletteType    = PaletteType.Unit;
                    props.LightingType   = LightingType.None;
                    drawable.IsRemapable = true;
                }
                else if (SpecialOverlays.IsHighBridge(ovl) || SpecialOverlays.IsTSHighRailsBridge(ovl))
                {
                    props.OffsetHack       = OffsetHacks.TSBridgeOffsets;
                    props.ShadowOffsetHack = OffsetHacks.TSBridgeShadowOffsets;
                    drawable.TileElevation = 4;                     // for lighting
                    //drawable.Foundation = new Size(3, 1); // ensures they're drawn later --> fixes overlap
                }
            }
        }
예제 #8
0
		public override void LoadFromRules() {
			base.LoadFromArtEssential();

			if (IsVoxel) {
				var vxl = new VoxelDrawable(Rules, Art);
				vxl.OwnerCollection = OwnerCollection;
				vxl.Props = Props;
				vxl.LoadFromRules();
				vxl.Vxl = VFS.Open<VxlFile>(vxl.Image + ".vxl");
				vxl.Hva = VFS.Open<HvaFile>(vxl.Image + ".hva");
				SubDrawables.Add(vxl);
			}
			else {
				var shp = new ShpDrawable(Rules, Art);
				shp.Props = Props;
				shp.OwnerCollection = OwnerCollection;
				shp.LoadFromRules();
				shp.Shp = VFS.Open<ShpFile>(shp.GetFilename());
                shp.Props.FrameDecider = FrameDeciders.SHPVehicleFrameDecider(shp.StartStandFrame, shp.StandingFrames, shp.Facings);
				SubDrawables.Add(shp);
			}

			if (Rules.ReadBool("Turret") && IsVoxel) {
				var turretVxl = VFS.Open<VxlFile>(Image + "TUR.vxl");
				var turretHva = VFS.Open<HvaFile>(Image + "TUR.hva");
				var turret = new VoxelDrawable(turretVxl, turretHva);
				turret.Props.Offset = Props.Offset;
				turret.Props.Offset += new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
				turret.Props.TurretVoxelOffset = Art.ReadFloat("TurretOffset");
				SubDrawables.Add(turret);

				var barrelVxl = VFS.Open<VxlFile>(Image + "BARL.vxl");
				var barrelHva = VFS.Open<HvaFile>(Image + "BARL.hva");
				if (barrelVxl != null && barrelHva != null) {
					var barrel = new VoxelDrawable(barrelVxl, barrelHva);
					barrel.Props = turret.Props;
					SubDrawables.Add(barrel);
				}
			}
		}
예제 #9
0
        private Drawable InitSimpleDrawable(IniFile.IniSection rulesSection, IniFile.IniSection artSection)
        {
            var drawable = new ShpDrawable(rulesSection, artSection);

            InitDrawableDefaults(drawable, artSection);
            drawable.LoadFromRules();

            string shpFile = drawable.GetFilename();

            drawable.Shp = VFS.Open <ShpFile>(shpFile);

            if (Type == CollectionType.Smudge)
            {
                drawable.Foundation = new Size(rulesSection.ReadInt("Width", 1), rulesSection.ReadInt("Height", 1));
            }

            if (Type == CollectionType.Overlay)
            {
                LoadOverlayDrawable(drawable);
            }

            return(drawable);
        }
예제 #10
0
        public override void LoadFromRules()
        {
            base.LoadFromArtEssential();

            ShpDrawable   shp = null;
            VoxelDrawable vxl = null;

            if (IsVoxel)
            {
                vxl = new VoxelDrawable(Rules, Art);
                vxl.OwnerCollection = OwnerCollection;
                vxl.Props           = Props;
                vxl.LoadFromRules();
                vxl.Vxl = VFS.Open <VxlFile>(vxl.Image + ".vxl");
                vxl.Hva = VFS.Open <HvaFile>(vxl.Image + ".hva");
                SubDrawables.Add(vxl);
            }
            else
            {
                shp                 = new ShpDrawable(Rules, Art);
                shp.Props           = Props;
                shp.OwnerCollection = OwnerCollection;
                shp.LoadFromRules();
                shp.Shp = VFS.Open <ShpFile>(shp.GetFilename());
                shp.Props.FrameDecider = FrameDeciders.SHPVehicleFrameDecider(shp.StartStandFrame, shp.StandingFrames, shp.StartWalkFrame, shp.WalkFrames, shp.Facings);
                SubDrawables.Add(shp);
            }

            if (shp != null || vxl != null)
            {
                if (Rules.ReadBool("Turret"))
                {
                    VoxelDrawable vxlturret = null;
                    ShpDrawable   shpturret = null;
                    var           turretVxl = VFS.Open <VxlFile>(Image + "TUR.vxl");
                    var           turretHva = VFS.Open <HvaFile>(Image + "TUR.hva");

                    if (turretVxl != null && turretHva != null)
                    {
                        vxlturret = new VoxelDrawable(turretVxl, turretHva);
                        vxlturret.Props.Offset            = Props.Offset;
                        vxlturret.Props.Offset           += new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
                        vxlturret.Props.TurretVoxelOffset = Art.ReadFloat("TurretOffset");
                        vxlturret.Props.Cloakable         = Props.Cloakable;
                        SubDrawables.Add(vxlturret);
                    }

                    if (vxlturret == null && shp != null)
                    {
                        shpturret                 = new ShpDrawable(Rules, Art);
                        shpturret.Props           = (DrawProperties)shp.Props.Clone();
                        shpturret.OwnerCollection = OwnerCollection;
                        shpturret.LoadFromRules();
                        shpturret.Shp = VFS.Open <ShpFile>(shpturret.GetFilename());
                        shpturret.Props.FrameDecider = FrameDeciders.SHPVehicleSHPTurretFrameDecider(shpturret.StartWalkFrame, shpturret.WalkFrames, shpturret.Facings);
                        shpturret.Props.Cloakable    = Props.Cloakable;
                        SubDrawables.Add(shpturret);
                    }

                    var barrelVxl = VFS.Open <VxlFile>(Image + "BARL.vxl");
                    var barrelHva = VFS.Open <HvaFile>(Image + "BARL.hva");
                    if (barrelVxl != null && barrelHva != null)
                    {
                        var barrel = new VoxelDrawable(barrelVxl, barrelHva);
                        if (vxlturret != null)
                        {
                            barrel.Props = vxlturret.Props;
                        }
                        else if (shp != null)
                        {
                            barrel.Props.Offset            = Props.Offset;
                            barrel.Props.Offset           += new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
                            barrel.Props.TurretVoxelOffset = Art.ReadFloat("TurretOffset");
                        }
                        barrel.Props.Cloakable = Props.Cloakable;
                        SubDrawables.Add(barrel);
                    }
                }
            }
        }
예제 #11
0
        public override void LoadFromRules()
        {
            base.LoadFromRules();

            IsBuildingPart  = true;
            InvisibleInGame = Rules.ReadBool("InvisibleInGame") || LampNames.Contains(Name.ToUpper());

            string foundation = Art.ReadString("Foundation", "1x1");

            if (!foundation.Equals("custom", StringComparison.InvariantCultureIgnoreCase))
            {
                int fx = foundation[0] - '0';
                int fy = foundation[2] - '0';
                Foundation = new Size(fx, fy);
            }
            else
            {
                int fx = Art.ReadInt("Foundation.X", 1);
                int fy = Art.ReadInt("Foundation.Y", 1);
                Foundation = new Size(fx, fy);
            }
            Props.SortIndex = Art.ReadInt("NormalYSort") - Art.ReadInt("NormalZAdjust");             // "main" building image before anims

            _baseShp = new ShpDrawable(Rules, Art);
            _baseShp.OwnerCollection = OwnerCollection;
            _baseShp.LoadFromArtEssential();
            _baseShp.Props = Props;
            _baseShp.Shp   = VFS.Open <ShpFile>(_baseShp.GetFilename());

            var extraProps = Props.Clone();

            extraProps.SortIndex = 0;
            foreach (string extraImage in AnimImages)
            {
                var extra = LoadExtraImage(extraImage, extraProps);
                if (extra != null && extra.Shp != null)
                {
                    _anims.Add(extra);

                    var extraDmg = LoadExtraImage(extraImage + "Damaged", extra.Props);
                    if (extraDmg != null && extraDmg.Shp != null)
                    {
                        _animsDamaged.Add(extraDmg);
                    }
                    else                     // no damaged anim --> use normal anim also in damaged state
                    {
                        _animsDamaged.Add(extra);
                    }
                }
            }

            // Starkku: New code for adding fire animations to buildings, supports custom-paletted animations.
            if (OwnerCollection.Engine >= EngineType.RedAlert2)
            {
                LoadFireAnimations();
            }

            // Add turrets
            if (Rules.ReadBool("Turret") && Rules.HasKey("TurretAnim"))
            {
                string   turretName = Rules.ReadString("TurretAnim");
                Drawable turret     = Rules.ReadBool("TurretAnimIsVoxel")
                                        ? (Drawable) new VoxelDrawable(VFS.Open <VxlFile>(turretName + ".vxl"), VFS.Open <HvaFile>(turretName + ".hva"))
                                        : new ShpDrawable(VFS.Open <ShpFile>(turretName + ".shp"));
                turret.Props.Offset       = Props.Offset + new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
                turret.Props.HasShadow    = Rules.ReadBool("UseTurretShadow");
                turret.Props.FrameDecider = FrameDeciders.TurretFrameDecider;
                turret.Props.ZAdjust      = Rules.ReadInt("TurretAnimZAdjust");
                SubDrawables.Add(turret);

                if (turret is VoxelDrawable && turretName.ToUpper().Contains("TUR"))
                {
                    string barrelName = turretName.Replace("TUR", "BARL");
                    if (VFS.Exists(barrelName + ".vxl"))
                    {
                        var barrel = new VoxelDrawable(VFS.Open <VxlFile>(barrelName + ".vxl"), VFS.Open <HvaFile>(barrelName + ".hva"));
                        SubDrawables.Add(barrel);
                        barrel.Props = turret.Props;
                    }
                }
            }

            // Bib
            if (Art.HasKey("BibShape"))
            {
                var bibImg = Art.ReadString("BibShape") + ".shp";
                if (NewTheater)
                {
                    bibImg = OwnerCollection.ApplyNewTheaterIfNeeded(bibImg, bibImg);
                }
                var bibShp = VFS.Open <ShpFile>(bibImg);
                if (bibShp != null)
                {
                    var bib = new ShpDrawable(bibShp);
                    bib.Props = this.Props.Clone();
                    bib.Flat  = true;
                    SubDrawables.Add(bib);
                }
            }

            // Powerup slots, at most 3
            for (int i = 1; i <= 3; i++)
            {
                if (!Art.HasKey(String.Format("PowerUp{0}LocXX", i)))
                {
                    break;
                }
                _powerupSlots.Add(new PowerupSlot {
                    X     = Art.ReadInt(String.Format("PowerUp{0}LocXX", i)),
                    Y     = Art.ReadInt(String.Format("PowerUp{0}LocYY", i)),
                    Z     = Art.ReadInt(String.Format("PowerUp{0}LocZZ", i)),
                    YSort = Art.ReadInt(String.Format("PowerUp{0}LocYSort", i)),
                });
            }
        }
예제 #12
0
		private void LoadOverlayDrawable(ShpDrawable drawable) {
			var ovl = new OverlayObject((byte)drawable.Index, 0);
			var tibType = SpecialOverlays.GetOverlayTibType(ovl, Engine);
			DrawProperties props = drawable.Props;

			if (Engine >= EngineType.RedAlert2) {
				if (tibType != OverlayTibType.NotSpecial) {
					props.FrameDecider = FrameDeciders.OverlayValueFrameDecider;
					props.PaletteType = PaletteType.Overlay;
					props.LightingType = LightingType.None;
				}
				else if (SpecialOverlays.IsHighBridge(ovl)) {
					props.OffsetHack = OffsetHacks.RA2BridgeOffsets;
					props.ShadowOffsetHack = OffsetHacks.RA2BridgeShadowOffsets;
					drawable.TileElevation = 4; // for lighting
					drawable.Foundation = new Size(3, 1); // ensures they're drawn later --> fixes overlap
				}
			}
			else if (Engine <= EngineType.Firestorm) {
				if (tibType != OverlayTibType.NotSpecial) {
					props.FrameDecider = FrameDeciders.OverlayValueFrameDecider;
					props.PaletteType = PaletteType.Unit;
					props.LightingType = LightingType.None;
					drawable.IsRemapable = true;
				}
				else if (SpecialOverlays.IsHighBridge(ovl) || SpecialOverlays.IsTSHighRailsBridge(ovl)) {
					props.OffsetHack = OffsetHacks.TSBridgeOffsets;
					props.ShadowOffsetHack = OffsetHacks.TSBridgeShadowOffsets;
					drawable.TileElevation = 4; // for lighting
					//drawable.Foundation = new Size(3, 1); // ensures they're drawn later --> fixes overlap
				}
			}
		}
예제 #13
0
		private void LoadSimpleDrawable(ShpDrawable drawable) {
			InitDrawableDefaults(drawable);
			drawable.LoadFromRules();

			string shpFile = drawable.GetFilename();
			drawable.Shp = VFS.Open<ShpFile>(shpFile);

			if (Type == CollectionType.Smudge)
				drawable.Foundation = new Size(drawable.Rules.ReadInt("Width", 1), drawable.Rules.ReadInt("Height", 1));

			if (Type == CollectionType.Overlay)
				LoadOverlayDrawable(drawable);
		}
예제 #14
0
		public override void LoadFromRules() {
			base.LoadFromRules();

			IsBuildingPart = true;
			InvisibleInGame = Rules.ReadBool("InvisibleInGame") || LampNames.Contains(Name.ToUpper());
			string foundation = Art.ReadString("Foundation", "1x1");
			if (!foundation.Equals("custom", StringComparison.InvariantCultureIgnoreCase)) {
				int fx = foundation[0] - '0';
				int fy = foundation[2] - '0';
				Foundation = new Size(fx, fy);
			}
			else {
				int fx = Art.ReadInt("Foundation.X", 1);
				int fy = Art.ReadInt("Foundation.Y", 1);
				Foundation = new Size(fx, fy);
			}
			Props.SortIndex = Art.ReadInt("NormalYSort") - Art.ReadInt("NormalZAdjust"); // "main" building image before anims
			Props.ZShapePointMove = Art.ReadPoint("ZShapePointMove");

			_baseShp = new ShpDrawable(Rules, Art);
			_baseShp.OwnerCollection = OwnerCollection;
			_baseShp.LoadFromArtEssential();
			_baseShp.Props = Props;
			_baseShp.Shp = VFS.Open<ShpFile>(_baseShp.GetFilename());

			var extraProps = Props.Clone();
			extraProps.SortIndex = 0;
			foreach (string extraImage in AnimImages) {

				var extra = LoadExtraImage(extraImage, extraProps);
				if (extra != null && extra.Shp != null) {
					_anims.Add(extra);

					var extraDmg = LoadExtraImage(extraImage + "Damaged", extra.Props);
					if (extraDmg != null && extraDmg.Shp != null)
						_animsDamaged.Add(extraDmg);
					else // no damaged anim --> use normal anim also in damaged state
						_animsDamaged.Add(extra);
				}
			}

			// Starkku: New code for adding fire animations to buildings, supports custom-paletted animations.
			if (OwnerCollection.Engine >= EngineType.RedAlert2)
				LoadFireAnimations();

			// Add turrets
			if (Rules.ReadBool("Turret") && Rules.HasKey("TurretAnim")) {
				string turretName = Rules.ReadString("TurretAnim");
                // Starkku: NewTheater/generic image fallback support for turrets.
                string turretNameShp = NewTheater ? OwnerCollection.ApplyNewTheaterIfNeeded(turretName, turretName) : turretName;
				turretNameShp += ".shp";
				Drawable turret = Rules.ReadBool("TurretAnimIsVoxel")
					? (Drawable)new VoxelDrawable(VFS.Open<VxlFile>(turretName + ".vxl"), VFS.Open<HvaFile>(turretName + ".hva"))
					: new ShpDrawable(VFS.Open<ShpFile>(turretNameShp));
				turret.Props.Offset = Props.Offset + new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY"));
				turret.Props.HasShadow = Rules.ReadBool("UseTurretShadow");
				turret.Props.FrameDecider = FrameDeciders.TurretFrameDecider;
				turret.Props.ZAdjust = Rules.ReadInt("TurretAnimZAdjust");
				SubDrawables.Add(turret);

				if (turret is VoxelDrawable && turretName.ToUpper().Contains("TUR")) {
					string barrelName = turretName.Replace("TUR", "BARL");
					if (VFS.Exists(barrelName + ".vxl")) {
						var barrel = new VoxelDrawable(VFS.Open<VxlFile>(barrelName + ".vxl"), VFS.Open<HvaFile>(barrelName + ".hva"));
						SubDrawables.Add(barrel);
						barrel.Props = turret.Props;
					}
				}
			}

			// Bib
			if (Art.HasKey("BibShape")) {
				var bibImg = Art.ReadString("BibShape") + ".shp";
				if (NewTheater)
					bibImg = OwnerCollection.ApplyNewTheaterIfNeeded(bibImg, bibImg);
				var bibShp = VFS.Open<ShpFile>(bibImg);
				if (bibShp != null) {
					var bib = new ShpDrawable(bibShp);
					bib.Props = this.Props.Clone();
					bib.Flat = true;
					SubDrawables.Add(bib);
				}
			}

			// Powerup slots, at most 3
			for (int i = 1; i <= 3; i++) {
				if (!Art.HasKey(String.Format("PowerUp{0}LocXX", i))) break;
				_powerupSlots.Add(new PowerupSlot {
					X = Art.ReadInt(String.Format("PowerUp{0}LocXX", i)),
					Y = Art.ReadInt(String.Format("PowerUp{0}LocYY", i)),
					Z = Art.ReadInt(String.Format("PowerUp{0}LocZZ", i)),
					YSort = Art.ReadInt(String.Format("PowerUp{0}LocYSort", i)),
				});
			}
		}