Add backend plumbing for model loaders.
This commit is contained in:
@@ -165,7 +165,7 @@ namespace OpenRA
|
|||||||
using (new PerfTimer("PrepareMap"))
|
using (new PerfTimer("PrepareMap"))
|
||||||
map = ModData.PrepareMap(mapUID);
|
map = ModData.PrepareMap(mapUID);
|
||||||
using (new PerfTimer("NewWorld"))
|
using (new PerfTimer("NewWorld"))
|
||||||
OrderManager.World = new World(map, OrderManager, type);
|
OrderManager.World = new World(ModData, map, OrderManager, type);
|
||||||
|
|
||||||
worldRenderer = new WorldRenderer(ModData, OrderManager.World);
|
worldRenderer = new WorldRenderer(ModData, OrderManager.World);
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace OpenRA
|
|||||||
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
|
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
|
||||||
public readonly TileSet TileSet;
|
public readonly TileSet TileSet;
|
||||||
public readonly SequenceProvider Sequences;
|
public readonly SequenceProvider Sequences;
|
||||||
|
public readonly IReadOnlyDictionary<string, MiniYamlNode> ModelSequences;
|
||||||
|
|
||||||
public Ruleset(
|
public Ruleset(
|
||||||
IReadOnlyDictionary<string, ActorInfo> actors,
|
IReadOnlyDictionary<string, ActorInfo> actors,
|
||||||
@@ -37,7 +38,8 @@ namespace OpenRA
|
|||||||
IReadOnlyDictionary<string, SoundInfo> notifications,
|
IReadOnlyDictionary<string, SoundInfo> notifications,
|
||||||
IReadOnlyDictionary<string, MusicInfo> music,
|
IReadOnlyDictionary<string, MusicInfo> music,
|
||||||
TileSet tileSet,
|
TileSet tileSet,
|
||||||
SequenceProvider sequences)
|
SequenceProvider sequences,
|
||||||
|
IReadOnlyDictionary<string, MiniYamlNode> modelSequences)
|
||||||
{
|
{
|
||||||
Actors = actors;
|
Actors = actors;
|
||||||
Weapons = weapons;
|
Weapons = weapons;
|
||||||
@@ -46,6 +48,7 @@ namespace OpenRA
|
|||||||
Music = music;
|
Music = music;
|
||||||
TileSet = tileSet;
|
TileSet = tileSet;
|
||||||
Sequences = sequences;
|
Sequences = sequences;
|
||||||
|
ModelSequences = modelSequences;
|
||||||
|
|
||||||
foreach (var a in Actors.Values)
|
foreach (var a in Actors.Values)
|
||||||
{
|
{
|
||||||
@@ -119,8 +122,11 @@ namespace OpenRA
|
|||||||
var music = MergeOrDefault("Manifest,Music", fs, m.Music, null, null,
|
var music = MergeOrDefault("Manifest,Music", fs, m.Music, null, null,
|
||||||
k => new MusicInfo(k.Key, k.Value));
|
k => new MusicInfo(k.Key, k.Value));
|
||||||
|
|
||||||
|
var modelSequences = MergeOrDefault("Manifest,ModelSequences", fs, m.VoxelSequences, null, null,
|
||||||
|
k => k);
|
||||||
|
|
||||||
// The default ruleset does not include a preferred tileset or sequence set
|
// The default ruleset does not include a preferred tileset or sequence set
|
||||||
ruleset = new Ruleset(actors, weapons, voices, notifications, music, null, null);
|
ruleset = new Ruleset(actors, weapons, voices, notifications, music, null, null, modelSequences);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (modData.IsOnMainThread)
|
if (modData.IsOnMainThread)
|
||||||
@@ -145,12 +151,13 @@ namespace OpenRA
|
|||||||
var dr = modData.DefaultRules;
|
var dr = modData.DefaultRules;
|
||||||
var ts = modData.DefaultTileSets[tileSet];
|
var ts = modData.DefaultTileSets[tileSet];
|
||||||
var sequences = modData.DefaultSequences[tileSet];
|
var sequences = modData.DefaultSequences[tileSet];
|
||||||
return new Ruleset(dr.Actors, dr.Weapons, dr.Voices, dr.Notifications, dr.Music, ts, sequences);
|
|
||||||
|
return new Ruleset(dr.Actors, dr.Weapons, dr.Voices, dr.Notifications, dr.Music, ts, sequences, dr.ModelSequences);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Ruleset Load(ModData modData, IReadOnlyFileSystem fileSystem, string tileSet,
|
public static Ruleset Load(ModData modData, IReadOnlyFileSystem fileSystem, string tileSet,
|
||||||
MiniYaml mapRules, MiniYaml mapWeapons, MiniYaml mapVoices, MiniYaml mapNotifications,
|
MiniYaml mapRules, MiniYaml mapWeapons, MiniYaml mapVoices, MiniYaml mapNotifications,
|
||||||
MiniYaml mapMusic, MiniYaml mapSequences)
|
MiniYaml mapMusic, MiniYaml mapSequences, MiniYaml mapModelSequences)
|
||||||
{
|
{
|
||||||
var m = modData.Manifest;
|
var m = modData.Manifest;
|
||||||
var dr = modData.DefaultRules;
|
var dr = modData.DefaultRules;
|
||||||
@@ -180,8 +187,12 @@ namespace OpenRA
|
|||||||
var sequences = mapSequences == null ? modData.DefaultSequences[tileSet] :
|
var sequences = mapSequences == null ? modData.DefaultSequences[tileSet] :
|
||||||
new SequenceProvider(fileSystem, modData, ts, mapSequences);
|
new SequenceProvider(fileSystem, modData, ts, mapSequences);
|
||||||
|
|
||||||
// TODO: Add support for custom voxel sequences
|
var modelSequences = dr.ModelSequences;
|
||||||
ruleset = new Ruleset(actors, weapons, voices, notifications, music, ts, sequences);
|
if (mapModelSequences != null)
|
||||||
|
modelSequences = MergeOrDefault("ModelSequences", fileSystem, m.VoxelSequences, mapModelSequences, dr.ModelSequences,
|
||||||
|
k => k);
|
||||||
|
|
||||||
|
ruleset = new Ruleset(actors, weapons, voices, notifications, music, ts, sequences, modelSequences);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (modData.IsOnMainThread)
|
if (modData.IsOnMainThread)
|
||||||
|
|||||||
69
OpenRA.Game/Graphics/Model.cs
Normal file
69
OpenRA.Game/Graphics/Model.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2017 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenRA.FileSystem;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public interface IModel
|
||||||
|
{
|
||||||
|
uint Frames { get; }
|
||||||
|
uint Sections { get; }
|
||||||
|
|
||||||
|
float[] TransformationMatrix(uint section, uint frame);
|
||||||
|
float[] Size { get; }
|
||||||
|
float[] Bounds(uint frame);
|
||||||
|
VoxelRenderData RenderData(uint section);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IModelCache : IDisposable
|
||||||
|
{
|
||||||
|
IModel GetModelSequence(string model, string sequence);
|
||||||
|
bool HasModelSequence(string model, string sequence);
|
||||||
|
IVertexBuffer<Vertex> VertexBuffer { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IModelSequenceLoader
|
||||||
|
{
|
||||||
|
Action<string> OnMissingModelError { get; set; }
|
||||||
|
IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelDefinitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlaceholderModelSequenceLoader : IModelSequenceLoader
|
||||||
|
{
|
||||||
|
public Action<string> OnMissingModelError { get; set; }
|
||||||
|
|
||||||
|
class PlaceholderModelCache : IModelCache
|
||||||
|
{
|
||||||
|
public IVertexBuffer<Vertex> VertexBuffer { get { throw new NotImplementedException(); } }
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
public IModel GetModelSequence(string model, string sequence)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasModelSequence(string model, string sequence)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaceholderModelSequenceLoader(ModData modData) { }
|
||||||
|
|
||||||
|
public IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelDefinitions)
|
||||||
|
{
|
||||||
|
return new PlaceholderModelCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,17 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class ModelSequenceFormat : IGlobalModData
|
||||||
|
{
|
||||||
|
public readonly string Type;
|
||||||
|
public readonly IReadOnlyDictionary<string, MiniYaml> Metadata;
|
||||||
|
public ModelSequenceFormat(MiniYaml yaml)
|
||||||
|
{
|
||||||
|
Type = yaml.Value;
|
||||||
|
Metadata = new ReadOnlyDictionary<string, MiniYaml>(yaml.ToDictionary());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ModMetadata
|
public class ModMetadata
|
||||||
{
|
{
|
||||||
public string Title;
|
public string Title;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenRA.FileSystem;
|
using OpenRA.FileSystem;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Support;
|
using OpenRA.Support;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
@@ -386,7 +387,7 @@ namespace OpenRA
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Rules = Ruleset.Load(modData, this, Tileset, RuleDefinitions, WeaponDefinitions,
|
Rules = Ruleset.Load(modData, this, Tileset, RuleDefinitions, WeaponDefinitions,
|
||||||
VoiceDefinitions, NotificationDefinitions, MusicDefinitions, SequenceDefinitions);
|
VoiceDefinitions, NotificationDefinitions, MusicDefinitions, SequenceDefinitions, VoxelSequenceDefinitions);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -307,8 +307,9 @@ namespace OpenRA
|
|||||||
var musicDefinitions = LoadRuleSection(yaml, "Music");
|
var musicDefinitions = LoadRuleSection(yaml, "Music");
|
||||||
var notificationDefinitions = LoadRuleSection(yaml, "Notifications");
|
var notificationDefinitions = LoadRuleSection(yaml, "Notifications");
|
||||||
var sequenceDefinitions = LoadRuleSection(yaml, "Sequences");
|
var sequenceDefinitions = LoadRuleSection(yaml, "Sequences");
|
||||||
|
var modelSequenceDefinitions = LoadRuleSection(yaml, "VoxelSequences");
|
||||||
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
|
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
|
||||||
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions);
|
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
|
||||||
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
|
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
|
||||||
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
|
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
|
||||||
return Pair.New(rules, flagged);
|
return Pair.New(rules, flagged);
|
||||||
@@ -390,8 +391,9 @@ namespace OpenRA
|
|||||||
var musicDefinitions = LoadRuleSection(rulesYaml, "Music");
|
var musicDefinitions = LoadRuleSection(rulesYaml, "Music");
|
||||||
var notificationDefinitions = LoadRuleSection(rulesYaml, "Notifications");
|
var notificationDefinitions = LoadRuleSection(rulesYaml, "Notifications");
|
||||||
var sequenceDefinitions = LoadRuleSection(rulesYaml, "Sequences");
|
var sequenceDefinitions = LoadRuleSection(rulesYaml, "Sequences");
|
||||||
|
var modelSequenceDefinitions = LoadRuleSection(rulesYaml, "VoxelSequences");
|
||||||
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
|
var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
|
||||||
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions);
|
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
|
||||||
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
|
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
|
||||||
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
|
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
|
||||||
return Pair.New(rules, flagged);
|
return Pair.New(rules, flagged);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace OpenRA
|
|||||||
public readonly ISoundLoader[] SoundLoaders;
|
public readonly ISoundLoader[] SoundLoaders;
|
||||||
public readonly ISpriteLoader[] SpriteLoaders;
|
public readonly ISpriteLoader[] SpriteLoaders;
|
||||||
public readonly ISpriteSequenceLoader SpriteSequenceLoader;
|
public readonly ISpriteSequenceLoader SpriteSequenceLoader;
|
||||||
|
public readonly IModelSequenceLoader ModelSequenceLoader;
|
||||||
public ILoadScreen LoadScreen { get; private set; }
|
public ILoadScreen LoadScreen { get; private set; }
|
||||||
public VoxelLoader VoxelLoader { get; private set; }
|
public VoxelLoader VoxelLoader { get; private set; }
|
||||||
public CursorProvider CursorProvider { get; private set; }
|
public CursorProvider CursorProvider { get; private set; }
|
||||||
@@ -73,13 +74,22 @@ namespace OpenRA
|
|||||||
|
|
||||||
var sequenceFormat = Manifest.Get<SpriteSequenceFormat>();
|
var sequenceFormat = Manifest.Get<SpriteSequenceFormat>();
|
||||||
var sequenceLoader = ObjectCreator.FindType(sequenceFormat.Type + "Loader");
|
var sequenceLoader = ObjectCreator.FindType(sequenceFormat.Type + "Loader");
|
||||||
var ctor = sequenceLoader != null ? sequenceLoader.GetConstructor(new[] { typeof(ModData) }) : null;
|
var sequenceCtor = sequenceLoader != null ? sequenceLoader.GetConstructor(new[] { typeof(ModData) }) : null;
|
||||||
if (sequenceLoader == null || !sequenceLoader.GetInterfaces().Contains(typeof(ISpriteSequenceLoader)) || ctor == null)
|
if (sequenceLoader == null || !sequenceLoader.GetInterfaces().Contains(typeof(ISpriteSequenceLoader)) || sequenceCtor == null)
|
||||||
throw new InvalidOperationException("Unable to find a sequence loader for type '{0}'.".F(sequenceFormat.Type));
|
throw new InvalidOperationException("Unable to find a sequence loader for type '{0}'.".F(sequenceFormat.Type));
|
||||||
|
|
||||||
SpriteSequenceLoader = (ISpriteSequenceLoader)ctor.Invoke(new[] { this });
|
SpriteSequenceLoader = (ISpriteSequenceLoader)sequenceCtor.Invoke(new[] { this });
|
||||||
SpriteSequenceLoader.OnMissingSpriteError = s => Log.Write("debug", s);
|
SpriteSequenceLoader.OnMissingSpriteError = s => Log.Write("debug", s);
|
||||||
|
|
||||||
|
var modelFormat = Manifest.Get<ModelSequenceFormat>();
|
||||||
|
var modelLoader = ObjectCreator.FindType(modelFormat.Type + "Loader");
|
||||||
|
var modelCtor = modelLoader != null ? modelLoader.GetConstructor(new[] { typeof(ModData) }) : null;
|
||||||
|
if (modelLoader == null || !modelLoader.GetInterfaces().Contains(typeof(IModelSequenceLoader)) || modelCtor == null)
|
||||||
|
throw new InvalidOperationException("Unable to find a model loader for type '{0}'.".F(modelFormat.Type));
|
||||||
|
|
||||||
|
ModelSequenceLoader = (IModelSequenceLoader)modelCtor.Invoke(new[] { this });
|
||||||
|
ModelSequenceLoader.OnMissingModelError = s => Log.Write("debug", s);
|
||||||
|
|
||||||
defaultRules = Exts.Lazy(() => Ruleset.LoadDefaults(this));
|
defaultRules = Exts.Lazy(() => Ruleset.LoadDefaults(this));
|
||||||
defaultTileSets = Exts.Lazy(() =>
|
defaultTileSets = Exts.Lazy(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -256,6 +256,7 @@
|
|||||||
<Compile Include="CryptoUtil.cs" />
|
<Compile Include="CryptoUtil.cs" />
|
||||||
<Compile Include="Support\VariableExpression.cs" />
|
<Compile Include="Support\VariableExpression.cs" />
|
||||||
<Compile Include="ExternalMods.cs" />
|
<Compile Include="ExternalMods.cs" />
|
||||||
|
<Compile Include="Graphics\Model.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="FileSystem\Folder.cs" />
|
<Compile Include="FileSystem\Folder.cs" />
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace OpenRA
|
|||||||
public Session LobbyInfo { get { return OrderManager.LobbyInfo; } }
|
public Session LobbyInfo { get { return OrderManager.LobbyInfo; } }
|
||||||
|
|
||||||
public readonly MersenneTwister SharedRandom;
|
public readonly MersenneTwister SharedRandom;
|
||||||
|
public readonly IModelCache ModelCache;
|
||||||
|
|
||||||
public Player[] Players = new Player[0];
|
public Player[] Players = new Player[0];
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal World(Map map, OrderManager orderManager, WorldType type)
|
internal World(ModData modData, Map map, OrderManager orderManager, WorldType type)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
OrderManager = orderManager;
|
OrderManager = orderManager;
|
||||||
@@ -156,6 +157,8 @@ namespace OpenRA
|
|||||||
Timestep = orderManager.LobbyInfo.GlobalSettings.Timestep;
|
Timestep = orderManager.LobbyInfo.GlobalSettings.Timestep;
|
||||||
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||||
|
|
||||||
|
ModelCache = modData.ModelSequenceLoader.CacheModels(map, modData, map.Rules.ModelSequences);
|
||||||
|
|
||||||
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World";
|
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World";
|
||||||
WorldActor = CreateActor(worldActorType, new TypeDictionary());
|
WorldActor = CreateActor(worldActorType, new TypeDictionary());
|
||||||
ActorMap = WorldActor.Trait<IActorMap>();
|
ActorMap = WorldActor.Trait<IActorMap>();
|
||||||
@@ -437,6 +440,8 @@ namespace OpenRA
|
|||||||
Game.Sound.StopAudio();
|
Game.Sound.StopAudio();
|
||||||
Game.Sound.StopVideo();
|
Game.Sound.StopVideo();
|
||||||
|
|
||||||
|
ModelCache.Dispose();
|
||||||
|
|
||||||
// Dispose newer actors first, and the world actor last
|
// Dispose newer actors first, and the world actor last
|
||||||
foreach (var a in actors.Values.Reverse())
|
foreach (var a in actors.Values.Reverse())
|
||||||
a.Dispose();
|
a.Dispose();
|
||||||
|
|||||||
@@ -30,3 +30,5 @@ SoundFormats:
|
|||||||
SpriteFormats:
|
SpriteFormats:
|
||||||
|
|
||||||
SpriteSequenceFormat: DefaultSpriteSequence
|
SpriteSequenceFormat: DefaultSpriteSequence
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|||||||
@@ -197,6 +197,8 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
|
|||||||
DESERT: .des
|
DESERT: .des
|
||||||
JUNGLE: .jun
|
JUNGLE: .jun
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|
||||||
GameSpeeds:
|
GameSpeeds:
|
||||||
slower:
|
slower:
|
||||||
Name: Slower
|
Name: Slower
|
||||||
|
|||||||
@@ -174,6 +174,8 @@ SpriteFormats: R8, ShpTD, TmpRA
|
|||||||
|
|
||||||
SpriteSequenceFormat: DefaultSpriteSequence
|
SpriteSequenceFormat: DefaultSpriteSequence
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|
||||||
GameSpeeds:
|
GameSpeeds:
|
||||||
slower:
|
slower:
|
||||||
Name: Slower
|
Name: Slower
|
||||||
|
|||||||
@@ -55,3 +55,5 @@ SoundFormats:
|
|||||||
SpriteFormats: ShpTD
|
SpriteFormats: ShpTD
|
||||||
|
|
||||||
SpriteSequenceFormat: DefaultSpriteSequence
|
SpriteSequenceFormat: DefaultSpriteSequence
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
|
|||||||
INTERIOR: .int
|
INTERIOR: .int
|
||||||
DESERT: .des
|
DESERT: .des
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|
||||||
GameSpeeds:
|
GameSpeeds:
|
||||||
slower:
|
slower:
|
||||||
Name: Slower
|
Name: Slower
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
|
|||||||
TEMPERATE: t
|
TEMPERATE: t
|
||||||
SNOW: a
|
SNOW: a
|
||||||
|
|
||||||
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|
||||||
GameSpeeds:
|
GameSpeeds:
|
||||||
slower:
|
slower:
|
||||||
Name: Slower
|
Name: Slower
|
||||||
|
|||||||
Reference in New Issue
Block a user