mysimulation/server/tso.files/Formats/IFF/Chunks/SLOT.cs

219 lines
7.5 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using FSO.Files.Utils;
using Microsoft.Xna.Framework;
namespace FSO.Files.Formats.IFF.Chunks
{
/// <summary>
/// This format isn't documented on the wiki! Thanks, Darren!
/// </summary>
public class SLOT : IffChunk
{
public static float[] HeightOffsets = {
//NOTE: 1 indexed! to get offset for a height, lookup (SLOT.Height-1)
0, //floor
2.5f, //low table
4, //table
4, //counter
0, //non-standard (appears to use offset height)
0, //in hand (unused probably. we handle avatar hands as a special case.)
7, //sitting (used for chairs)
4, //end table
0 //TODO: unknown
};
public Dictionary<ushort, List<SLOTItem>> Slots = new Dictionary<ushort, List<SLOTItem>>();
public List<SLOTItem> Chronological = new List<SLOTItem>();
public uint Version;
public override void Read(IffFile iff, System.IO.Stream stream)
{
using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN)){
var zero = io.ReadUInt32();
var version = io.ReadUInt32();
Version = version;
var slotMagic = io.ReadBytes(4);
var numSlots = io.ReadUInt32();
/** The span for version 4 is 34.
* The span for version 6 is 54.
* The span for version 7 is 58.
* The span for version 8 is 62.
* The span for version 9 is 66.
* The span for version 10 is 70. **/
for (var i = 0; i < numSlots; i++){
var item = new SLOTItem();
item.Type = io.ReadUInt16();
item.Offset = new Vector3(
io.ReadFloat(),
io.ReadFloat(),
io.ReadFloat()
);
var standing = io.ReadInt32();
var sitting = io.ReadInt32();
var ground = io.ReadInt32();
var rsflags = io.ReadInt32();
var snaptargetslot = io.ReadInt32();
//bonuses (0 means never)
item.Standing = standing; //score bonus for standing destinations
item.Sitting = sitting; //score bonus for sitting destinations
item.Ground = ground; //score bonus for sitting on ground
item.Rsflags = (SLOTFlags)rsflags;
item.SnapTargetSlot = snaptargetslot;
if (version >= 6)
{
var minproximity = io.ReadInt32();
var maxproximity = io.ReadInt32();
var optimalproximity = io.ReadInt32();
var i9 = io.ReadInt32();
var i10 = io.ReadInt32();
item.MinProximity = minproximity;
item.MaxProximity = maxproximity;
item.OptimalProximity = optimalproximity;
item.MaxSize = i9;
item.I10 = i10;
}
if (version <= 9) {
item.MinProximity *= 16;
item.MaxProximity *= 16;
item.OptimalProximity *= 16;
}
if (version >= 7) item.Gradient = io.ReadFloat();
if (version >= 8) item.Height = io.ReadInt32();
if (item.Height == 0) item.Height = 5; //use offset height, nonstandard.
if (version >= 9)
{
item.Facing = (SLOTFacing)io.ReadInt32();
}
if (version >= 10) item.Resolution = io.ReadInt32();
if (!Slots.ContainsKey(item.Type)) Slots.Add(item.Type, new List<SLOTItem>());
Slots[item.Type].Add(item);
Chronological.Add(item);
}
}
}
public override bool Write(IffFile iff, Stream stream)
{
using (var io = IoWriter.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
{
io.WriteInt32(0);
io.WriteInt32(10); //version
io.WriteCString("TOLS", 4);
io.WriteUInt32((uint)Chronological.Count);
foreach (var slot in Chronological)
{
io.WriteUInt16(slot.Type);
io.WriteFloat(slot.Offset.X);
io.WriteFloat(slot.Offset.Y);
io.WriteFloat(slot.Offset.Z);
io.WriteInt32(slot.Standing);
io.WriteInt32(slot.Sitting);
io.WriteInt32(slot.Ground);
io.WriteInt32((int)slot.Rsflags);
io.WriteInt32(slot.SnapTargetSlot);
io.WriteInt32(slot.MinProximity);
io.WriteInt32(slot.MaxProximity);
io.WriteInt32(slot.OptimalProximity);
io.WriteInt32(slot.MaxSize);
io.WriteInt32(slot.I10);
io.WriteFloat(slot.Gradient);
io.WriteInt32(slot.Height);
io.WriteInt32((int)slot.Facing);
io.WriteInt32(slot.Resolution);
}
}
return true;
}
}
[Flags]
public enum SLOTFlags : int
{
NORTH = 1,
NORTH_EAST = 2,
EAST = 4,
SOUTH_EAST = 8,
SOUTH = 16,
SOUTH_WEST = 32,
WEST = 64,
NORTH_WEST = 128,
AllowAnyRotation = 256, //unknown - used for snap to offset? (but not all the time?)
Absolute = 512, //do not rotate goal around object
FacingAwayFromObject = 1024, //deprecated. does not appear - replaced by Facing field
IgnoreRooms = 2048,
SnapToDirection = 4096,
RandomScoring = 8192,
AllowFailureTrees = 16385,
AllowDifferentAlts = 32768,
UseAverageObjectLocation = 65536,
FSOEqualProximityScore = 1 << 29,
FSOSquare = 1 << 30
}
public enum SLOTFacing : int
{
FaceAnywhere = -3,
FaceTowardsObject = -2,
FaceAwayFromObject = -1,
}
public class SLOTItem
{
public ushort Type { get; set; }
public Vector3 Offset;
public int Standing { get; set; } = 1;
public int Sitting { get; set; } = 0;
public int Ground { get; set; } = 0;
public SLOTFlags Rsflags { get; set; }
public int SnapTargetSlot { get; set; } = -1;
public int MinProximity { get; set; }
public int MaxProximity { get; set; } = 0;
public int OptimalProximity { get; set; } = 0;
public int MaxSize { get; set; } = 100;
public int I10;
public float Gradient { get; set; }
public SLOTFacing Facing { get; set; } = SLOTFacing.FaceTowardsObject;
public int Resolution { get; set; } = 16;
public int Height { get; set; }
public float OffsetX
{
get => Offset.X;
set => Offset.X = value;
}
public float OffsetY
{
get => Offset.Y;
set => Offset.Y = value;
}
public float OffsetZ
{
get => Offset.Z;
set => Offset.Z = value;
}
}
}