Compare commits
90 Commits
playtest-2
...
playtest-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db5920e83a | ||
|
|
80555235d7 | ||
|
|
acd842f178 | ||
|
|
a5dacd52e8 | ||
|
|
6e045e864a | ||
|
|
0541b04c3a | ||
|
|
07b2bcbfdf | ||
|
|
0e2b4bb721 | ||
|
|
ab3c06cd04 | ||
|
|
299ee7f82c | ||
|
|
ddd56e6f9b | ||
|
|
839043ea1b | ||
|
|
1e8aea616b | ||
|
|
727a88d82a | ||
|
|
1f54ad3238 | ||
|
|
694fd84188 | ||
|
|
271be551b0 | ||
|
|
fe481d7445 | ||
|
|
7a10ae3dea | ||
|
|
8c39e372e3 | ||
|
|
af6660d6ca | ||
|
|
d0da9d11bf | ||
|
|
0a2d39f15b | ||
|
|
8118a17e3c | ||
|
|
0f6564f31a | ||
|
|
dda6556e17 | ||
|
|
5c1408d4d7 | ||
|
|
aa6e671d89 | ||
|
|
e0de1427e9 | ||
|
|
db16ab4cdc | ||
|
|
ae703d50b2 | ||
|
|
f6c6255f64 | ||
|
|
a569c712f0 | ||
|
|
5c8c8d5e6e | ||
|
|
3f4f1ff75e | ||
|
|
1aa4f57a68 | ||
|
|
3f3ac377b2 | ||
|
|
de12233edc | ||
|
|
b36b101392 | ||
|
|
726449b6fb | ||
|
|
a0d7435550 | ||
|
|
11aed465a8 | ||
|
|
0f953226a6 | ||
|
|
ad181544cd | ||
|
|
df19163ce5 | ||
|
|
4328fbc350 | ||
|
|
7cd9afb6d2 | ||
|
|
1ad8b58f1b | ||
|
|
62e3d548c8 | ||
|
|
ea7abcb585 | ||
|
|
441bffecfc | ||
|
|
2c1ab33893 | ||
|
|
74500c369c | ||
|
|
6e0158039a | ||
|
|
c600239c54 | ||
|
|
93a48c0cf1 | ||
|
|
b88512df43 | ||
|
|
ca6debde66 | ||
|
|
8dd9848636 | ||
|
|
ec9da154ad | ||
|
|
46fc0ef563 | ||
|
|
514c92a998 | ||
|
|
96f9f33776 | ||
|
|
20553a112d | ||
|
|
9e49cad1c2 | ||
|
|
5c6e2a5e42 | ||
|
|
44d7aa14a4 | ||
|
|
bf8e3645cb | ||
|
|
6ea8d4e6d3 | ||
|
|
16c3223f3e | ||
|
|
b98e180361 | ||
|
|
80aade857e | ||
|
|
58700e4c07 | ||
|
|
d364472862 | ||
|
|
5d688a2e27 | ||
|
|
f4fa053a35 | ||
|
|
90373529b0 | ||
|
|
0416b6b429 | ||
|
|
bd991e33ca | ||
|
|
f162c5956e | ||
|
|
e6f717ff04 | ||
|
|
eb0c895e2c | ||
|
|
3af0d2f6a4 | ||
|
|
8f6fe8344b | ||
|
|
cb5307bb17 | ||
|
|
d9acf1a3e5 | ||
|
|
6fc945ac91 | ||
|
|
e5878e8207 | ||
|
|
b982a52086 | ||
|
|
f28ec846e7 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,6 +25,7 @@ log.txt
|
||||
*.exe
|
||||
OpenRA
|
||||
OpenRA.app
|
||||
*.vqa
|
||||
|
||||
# backup files by various editors
|
||||
*~
|
||||
|
||||
7
Makefile
7
Makefile
@@ -16,7 +16,7 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll WindowsBase.dll
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll thirdparty/WindowsBase.dll
|
||||
|
||||
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||
gl_TARGET = OpenRA.Gl.dll
|
||||
@@ -113,11 +113,12 @@ install: all
|
||||
|
||||
@cp -r shaders $(INSTALL_DIR)
|
||||
@cp *.ttf $(INSTALL_DIR)
|
||||
@cp -r thirdparty $(INSTALL_DIR)
|
||||
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) thirdparty/WindowsBase.dll $(INSTALL_DIR)
|
||||
|
||||
@echo "#!/bin/sh" > openra
|
||||
@echo "cd "$(datadir)"/openra" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.openra" >> openra
|
||||
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.openra \"$$""@\"" >> openra
|
||||
@$(INSTALL_PROGRAM) -d $(BIN_INSTALL_DIR)
|
||||
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
|
||||
|
||||
|
||||
@@ -76,6 +76,32 @@ namespace OpenRA.FileFormats
|
||||
return (short)current;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(byte[] raw, ref int index)
|
||||
{
|
||||
var br = new BinaryReader(new MemoryStream(raw));
|
||||
var dataSize = raw.Length;
|
||||
var outputSize = raw.Length * 4;
|
||||
|
||||
var output = new byte[outputSize];
|
||||
var offset = 0;
|
||||
var currentSample = 0;
|
||||
|
||||
while (dataSize-- > 0)
|
||||
{
|
||||
var b = br.ReadByte();
|
||||
|
||||
var t = DecodeSample(b, ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
|
||||
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace OpenRA.FileFormats.Graphics
|
||||
IVertexBuffer<Vertex> CreateVertexBuffer( int length );
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
ITexture CreateTexture();
|
||||
IShader CreateShader( Stream stream );
|
||||
|
||||
Size WindowSize { get; }
|
||||
@@ -71,6 +72,7 @@ namespace OpenRA.FileFormats.Graphics
|
||||
public interface ITexture
|
||||
{
|
||||
void SetData( Bitmap bitmap );
|
||||
void SetData(uint[,] colors);
|
||||
}
|
||||
|
||||
public interface IFont
|
||||
|
||||
295
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
295
OpenRA.FileFormats/Graphics/VqaReader.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class VqaReader
|
||||
{
|
||||
public readonly ushort Frames;
|
||||
public readonly byte Framerate;
|
||||
public readonly ushort Width;
|
||||
public readonly ushort Height;
|
||||
|
||||
Stream stream;
|
||||
int currentFrame;
|
||||
ushort flags;
|
||||
ushort numColors;
|
||||
ushort blockWidth;
|
||||
ushort blockHeight;
|
||||
byte cbParts;
|
||||
int2 blocks;
|
||||
UInt32[] offsets;
|
||||
uint[] palette;
|
||||
|
||||
// Stores a list of subpixels, referenced by the VPTZ chunk
|
||||
byte[] cbf;
|
||||
byte[] cbp;
|
||||
int cbChunk = 0;
|
||||
int cbOffset = 0;
|
||||
|
||||
// Top half contains block info, bottom half contains references to cbf array
|
||||
byte[] origData;
|
||||
|
||||
// Final frame output
|
||||
uint[,] frameData;
|
||||
byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed.
|
||||
|
||||
public byte[] AudioData { get { return audioData; } }
|
||||
public int CurrentFrame { get { return currentFrame; } }
|
||||
|
||||
public VqaReader( Stream stream )
|
||||
{
|
||||
this.stream = stream;
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
|
||||
// Decode FORM chunk
|
||||
if (new String(reader.ReadChars(4)) != "FORM")
|
||||
throw new InvalidDataException("Invalid vqa (invalid FORM section)");
|
||||
/*var length = */ reader.ReadUInt32();
|
||||
|
||||
if (new String(reader.ReadChars(8)) != "WVQAVQHD")
|
||||
throw new InvalidDataException("Invalid vqa (not WVQAVQHD)");
|
||||
/* var length = */reader.ReadUInt32();
|
||||
|
||||
/*var version = */reader.ReadUInt16();
|
||||
flags = reader.ReadUInt16();
|
||||
Frames = reader.ReadUInt16();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
|
||||
blockWidth = reader.ReadByte();
|
||||
blockHeight = reader.ReadByte();
|
||||
Framerate = reader.ReadByte();
|
||||
cbParts = reader.ReadByte();
|
||||
blocks = new int2(Width / blockWidth, Height / blockHeight);
|
||||
|
||||
numColors = reader.ReadUInt16();
|
||||
/*var maxBlocks = */reader.ReadUInt16();
|
||||
/*var unknown1 = */reader.ReadUInt16();
|
||||
/*var unknown2 = */reader.ReadUInt32();
|
||||
|
||||
// Audio
|
||||
/*var freq = */reader.ReadUInt16();
|
||||
/*var channels = */reader.ReadByte();
|
||||
/*var bits = */reader.ReadByte();
|
||||
var unknown3 = reader.ReadChars(14);
|
||||
|
||||
|
||||
var frameSize = NextPowerOf2(Math.Max(Width,Height));
|
||||
cbf = new byte[Width*Height];
|
||||
cbp = new byte[Width*Height];
|
||||
palette = new uint[numColors];
|
||||
origData = new byte[2*blocks.X*blocks.Y];
|
||||
frameData = new uint[frameSize,frameSize];
|
||||
|
||||
var type = new String(reader.ReadChars(4));
|
||||
if (type != "FINF")
|
||||
{
|
||||
reader.ReadBytes(27);
|
||||
type = new String(reader.ReadChars(4));
|
||||
}
|
||||
|
||||
/*var length = */reader.ReadUInt16();
|
||||
/*var unknown4 = */reader.ReadUInt16();
|
||||
|
||||
// Frame offsets
|
||||
offsets = new UInt32[Frames];
|
||||
for (int i = 0; i < Frames; i++)
|
||||
{
|
||||
offsets[i] = reader.ReadUInt32();
|
||||
if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000;
|
||||
offsets[i] <<= 1;
|
||||
}
|
||||
|
||||
CollectAudioData();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
currentFrame = cbOffset = cbChunk = 0;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void CollectAudioData()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
var adpcmIndex = 0;
|
||||
|
||||
bool compressed = false;
|
||||
for (var i = 0; i < Frames; i++)
|
||||
{
|
||||
stream.Seek(offsets[i], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length;
|
||||
|
||||
while (reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "SND0":
|
||||
case "SND2":
|
||||
var rawAudio = reader.ReadBytes((int)length);
|
||||
ms.Write(rawAudio);
|
||||
compressed = (type == "SND2");
|
||||
break;
|
||||
default:
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
audioData = (compressed) ? AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex) : ms.ToArray();
|
||||
}
|
||||
|
||||
public void AdvanceFrame()
|
||||
{
|
||||
currentFrame++;
|
||||
LoadFrame();
|
||||
}
|
||||
|
||||
void LoadFrame()
|
||||
{
|
||||
if (currentFrame >= Frames)
|
||||
return;
|
||||
|
||||
// Seek to the start of the frame
|
||||
stream.Seek(offsets[currentFrame], SeekOrigin.Begin);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
var end = (currentFrame < Frames - 1) ? offsets[currentFrame+1] : stream.Length;
|
||||
|
||||
while(reader.BaseStream.Position < end)
|
||||
{
|
||||
var type = new String(reader.ReadChars(4));
|
||||
var length = int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case "VQFR":
|
||||
DecodeVQFR(reader);
|
||||
break;
|
||||
default:
|
||||
// Don't parse sound here.
|
||||
reader.ReadBytes((int)length);
|
||||
break;
|
||||
}
|
||||
|
||||
// Chunks are aligned on even bytes; advance by a byte if the next one is null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
// VQA Frame
|
||||
public void DecodeVQFR(BinaryReader reader)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
// Chunks are aligned on even bytes; may be padded with a single null
|
||||
if (reader.PeekChar() == 0) reader.ReadByte();
|
||||
var type = new String(reader.ReadChars(4));
|
||||
int subchunkLength = (int)int2.Swap(reader.ReadUInt32());
|
||||
|
||||
switch(type)
|
||||
{
|
||||
// Full frame-modifier
|
||||
case "CBFZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), cbf );
|
||||
break;
|
||||
case "CBF0":
|
||||
cbf = reader.ReadBytes(subchunkLength);
|
||||
break;
|
||||
|
||||
// frame-modifier chunk
|
||||
case "CBP0":
|
||||
case "CBPZ":
|
||||
// Partial buffer is full; dump and recreate
|
||||
if (cbChunk == cbParts)
|
||||
{
|
||||
if (type == "CBP0")
|
||||
cbf = (byte[])cbp.Clone();
|
||||
else
|
||||
Format80.DecodeInto( cbp, cbf );
|
||||
|
||||
cbOffset = cbChunk = 0;
|
||||
}
|
||||
|
||||
var bytes = reader.ReadBytes(subchunkLength);
|
||||
bytes.CopyTo(cbp,cbOffset);
|
||||
cbOffset += subchunkLength;
|
||||
cbChunk++;
|
||||
break;
|
||||
|
||||
// Palette
|
||||
case "CPL0":
|
||||
for (int i = 0; i < numColors; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
palette[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
break;
|
||||
|
||||
// Frame data
|
||||
case "VPTZ":
|
||||
Format80.DecodeInto( reader.ReadBytes(subchunkLength), origData );
|
||||
// This is the last subchunk
|
||||
return;
|
||||
default:
|
||||
throw new InvalidDataException("Unknown sub-chunk {0}".F(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cachedFrame = -1;
|
||||
public uint[,] FrameData { get
|
||||
{
|
||||
if (cachedFrame != currentFrame)
|
||||
{
|
||||
cachedFrame = currentFrame;
|
||||
for (var y = 0; y < blocks.Y; y++)
|
||||
for (var x = 0; x < blocks.X; x++)
|
||||
{
|
||||
var px = origData[x + y*blocks.X];
|
||||
var mod = origData[x + (y + blocks.Y)*blocks.X];
|
||||
for (var j = 0; j < blockHeight; j++)
|
||||
for (var i = 0; i < blockWidth; i++)
|
||||
{
|
||||
var cbfi = (mod*256 + px)*8 + j*blockWidth + i;
|
||||
byte color = (mod == 0x0f) ? px : cbf[cbfi];
|
||||
frameData[y*blockHeight + j, x*blockWidth + i] = palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
return frameData;
|
||||
}}
|
||||
|
||||
int NextPowerOf2(int v)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
++v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -99,6 +99,7 @@
|
||||
<Compile Include="Map\SmudgeReference.cs" />
|
||||
<Compile Include="Map\PlayerReference.cs" />
|
||||
<Compile Include="CompressedPackage.cs" />
|
||||
<Compile Include="Graphics\VqaReader.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -11,20 +11,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Palette
|
||||
{
|
||||
List<Color> colors = new List<Color>();
|
||||
|
||||
uint[] colors;
|
||||
public Color GetColor(int index)
|
||||
{
|
||||
return colors[index];
|
||||
return Color.FromArgb((int)colors[index]);
|
||||
}
|
||||
|
||||
public void SetColor(int index, Color color)
|
||||
{
|
||||
colors[index] = (uint)color.ToArgb();
|
||||
}
|
||||
|
||||
public void SetColor(int index, uint color)
|
||||
{
|
||||
colors[index] = (uint)color;
|
||||
}
|
||||
|
||||
public uint[] Values
|
||||
{
|
||||
get { return colors; }
|
||||
}
|
||||
|
||||
public Palette(Stream s, bool remapTransparent)
|
||||
{
|
||||
colors = new uint[256];
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(s))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
@@ -32,24 +50,28 @@ namespace OpenRA.FileFormats
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
|
||||
colors.Add(Color.FromArgb(r, g, b));
|
||||
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
|
||||
colors[0] = Color.FromArgb(0, 0, 0, 0);
|
||||
|
||||
colors[0] = 0;
|
||||
if (remapTransparent)
|
||||
{
|
||||
colors[3] = Color.FromArgb(178, 0, 0, 0);
|
||||
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||
colors[3] = 178u << 24;
|
||||
colors[4] = 140u << 24;
|
||||
}
|
||||
}
|
||||
|
||||
public Palette(Palette p, IPaletteRemap r)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||
colors = new uint[256];
|
||||
for(int i = 0; i < 256; i++)
|
||||
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb();
|
||||
}
|
||||
|
||||
public Palette(Palette p)
|
||||
{
|
||||
colors = (uint[])p.colors.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,5 +53,11 @@ namespace OpenRA
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
|
||||
public override string ToString() { return string.Format("{0},{1}", X, Y); }
|
||||
|
||||
// Change endianness of a uint32
|
||||
public static uint Swap(uint orig)
|
||||
{
|
||||
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.FileFormats
|
||||
public readonly string[]
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, TileSets;
|
||||
Weapons, Voices, Music, Movies, TileSets;
|
||||
|
||||
public readonly string ShellmapUid;
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace OpenRA.FileFormats
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Music = YamlList(yaml, "Music");
|
||||
Movies = YamlList(yaml, "Movies");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
|
||||
ShellmapUid = yaml["ShellmapUid"].Value;
|
||||
|
||||
@@ -96,10 +96,12 @@ namespace OpenRA
|
||||
request.Headers.Add("Channel", kvp.Key);
|
||||
// request.Headers.Add("Diff", kvp.Value.Diff ? "1" : "0");
|
||||
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
requestStream.Write(buffer, 0, buffer.Length);
|
||||
|
||||
//var response = (HttpWebResponse)request.GetResponse();
|
||||
try
|
||||
{
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
requestStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception){}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace OpenRA
|
||||
public class Actor
|
||||
{
|
||||
[Sync]
|
||||
public readonly TypeDictionary traits = new TypeDictionary();
|
||||
readonly TypeDictionary traits = new TypeDictionary();
|
||||
public readonly ActorInfo Info;
|
||||
|
||||
public readonly World World;
|
||||
public readonly uint ActorID;
|
||||
|
||||
public int2 Location { get { return traits.Get<IOccupySpace>().TopLeft; } }
|
||||
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
|
||||
[Sync]
|
||||
public Player Owner;
|
||||
|
||||
@@ -51,10 +51,10 @@ namespace OpenRA
|
||||
|
||||
Info = Rules.Info[name.ToLowerInvariant()];
|
||||
foreach (var trait in Info.TraitsInConstructOrder())
|
||||
traits.Add(trait.Create(init));
|
||||
AddTrait(trait.Create(init));
|
||||
}
|
||||
|
||||
if( CenterLocation == float2.Zero && traits.Contains<IOccupySpace>() )
|
||||
if( CenterLocation == float2.Zero && HasTrait<IOccupySpace>() )
|
||||
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||
|
||||
Size = Lazy.New(() =>
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA
|
||||
return new float2(si.Bounds[0], si.Bounds[1]);
|
||||
|
||||
// auto size from render
|
||||
var firstSprite = traits.WithInterface<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size;
|
||||
});
|
||||
@@ -83,7 +83,7 @@ namespace OpenRA
|
||||
if (currentActivity is Idle)
|
||||
{
|
||||
if (!wasIdle)
|
||||
foreach (var ni in traits.WithInterface<INotifyIdle>())
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.Idle(this);
|
||||
|
||||
break;
|
||||
@@ -102,8 +102,8 @@ namespace OpenRA
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
var mods = traits.WithInterface<IRenderModifier>();
|
||||
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));
|
||||
var mods = TraitsImplementing<IRenderModifier>();
|
||||
var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this));
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace OpenRA
|
||||
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
return traits.WithInterface<IIssueOrder>()
|
||||
return TraitsImplementing<IIssueOrder>()
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
@@ -137,7 +137,7 @@ namespace OpenRA
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var move = traits.GetOrDefault<IMove>();
|
||||
var move = TraitOrDefault<IMove>();
|
||||
if (move != null) loc -= new float2(0, move.Altitude);
|
||||
}
|
||||
|
||||
@@ -188,5 +188,30 @@ namespace OpenRA
|
||||
{
|
||||
return "{0} {1}{2}".F( Info.Name, ActorID, IsInWorld ? "" : " (not in world)" );
|
||||
}
|
||||
|
||||
public T Trait<T>()
|
||||
{
|
||||
return traits.Get<T>();
|
||||
}
|
||||
|
||||
public T TraitOrDefault<T>()
|
||||
{
|
||||
return traits.GetOrDefault<T>();
|
||||
}
|
||||
|
||||
public IEnumerable<T> TraitsImplementing<T>()
|
||||
{
|
||||
return traits.WithInterface<T>();
|
||||
}
|
||||
|
||||
public bool HasTrait<T>()
|
||||
{
|
||||
return traits.Contains<T>();
|
||||
}
|
||||
|
||||
public void AddTrait( object t )
|
||||
{
|
||||
traits.Add( t );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA
|
||||
|
||||
public static World world;
|
||||
public static Viewport viewport;
|
||||
internal static UserSettings Settings;
|
||||
public static UserSettings Settings;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
|
||||
@@ -384,7 +384,7 @@ namespace OpenRA
|
||||
LoadMap(map);
|
||||
world.Queries = new World.AllQueries(world);
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
foreach (var gs in world.WorldActor.TraitsImplementing<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
orderManager.StartGame();
|
||||
}
|
||||
@@ -398,7 +398,7 @@ namespace OpenRA
|
||||
|
||||
world.Queries = new World.AllQueries(world);
|
||||
|
||||
foreach (var gs in world.WorldActor.traits.WithInterface<IGameStarted>())
|
||||
foreach (var gs in world.WorldActor.TraitsImplementing<IGameStarted>())
|
||||
gs.GameStarted(world);
|
||||
|
||||
viewport.GoToStartLocation(world.LocalPlayer);
|
||||
@@ -503,7 +503,7 @@ namespace OpenRA
|
||||
|
||||
// Load the default mod to access required files
|
||||
LoadModPackages();
|
||||
|
||||
|
||||
Renderer.SheetSize = Settings.SheetSize;
|
||||
|
||||
var resolution = GetResolution(settings, Game.Settings.WindowMode);
|
||||
|
||||
@@ -13,38 +13,16 @@ using OpenRA.FileFormats;
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class MusicInfo
|
||||
{
|
||||
public readonly MusicPool Pool;
|
||||
public readonly string[] Music = { };
|
||||
{
|
||||
public readonly string Filename = null;
|
||||
public readonly string Title = null;
|
||||
public readonly int Length = 0; // seconds
|
||||
|
||||
public MusicInfo( MiniYaml y )
|
||||
public MusicInfo( string key, MiniYaml value )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
Pool = new MusicPool(Music);
|
||||
FieldLoader.Load(this, value);
|
||||
if (Filename == null)
|
||||
Filename = key+".aud";
|
||||
}
|
||||
}
|
||||
|
||||
public class MusicPool
|
||||
{
|
||||
readonly string[] clips;
|
||||
int playing = 0;
|
||||
|
||||
public MusicPool(params string[] clips)
|
||||
{
|
||||
this.clips = clips;
|
||||
}
|
||||
|
||||
public string GetNext()
|
||||
{
|
||||
playing = (playing + 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetPrev()
|
||||
{
|
||||
playing = (playing + clips.Length - 1) % clips.Length;
|
||||
return clips[playing];
|
||||
}
|
||||
public string GetCurrent(){ return clips[playing];}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace OpenRA
|
||||
public static Dictionary<string, WeaponInfo> Weapons;
|
||||
public static Dictionary<string, VoiceInfo> Voices;
|
||||
public static Dictionary<string, MusicInfo> Music;
|
||||
public static Dictionary<string, string> Movies;
|
||||
public static Dictionary<string, TileSet> TileSets;
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
@@ -31,7 +32,8 @@ namespace OpenRA
|
||||
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, map.Music, (k, _) => new MusicInfo(k.Value));
|
||||
Music = LoadYamlRules(m.Music, map.Music, (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
Movies = LoadYamlRules(m.Movies, new Dictionary<string,MiniYaml>(), (k, v) => k.Value.Value);
|
||||
|
||||
TileSets = new Dictionary<string, TileSet>();
|
||||
foreach (var file in m.TileSets)
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace OpenRA.GameRules
|
||||
//Sound Settings
|
||||
public float SoundVolume = 0.5f;
|
||||
public float MusicVolume = 0.5f;
|
||||
public float VideoVolume = 0.5f;
|
||||
public bool MusicPlayer = false;
|
||||
|
||||
// Internal game settings
|
||||
|
||||
@@ -9,33 +9,35 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class VoiceInfo
|
||||
{
|
||||
public readonly string[] SovietVariants = { ".aud" };
|
||||
public readonly string[] AlliedVariants = { ".aud" };
|
||||
public readonly string[] Select = { };
|
||||
public readonly string[] Move = { };
|
||||
public readonly string[] Attack = null;
|
||||
public readonly string[] Die = { };
|
||||
public readonly Dictionary<string,string[]> Variants;
|
||||
public readonly Dictionary<string,string[]> Voices;
|
||||
public readonly string DefaultVariant = ".aud" ;
|
||||
public readonly string[] DisableVariants = { };
|
||||
|
||||
Func<MiniYaml, string, Dictionary<string, string[]>> Load = (y,name) => (y.Nodes.ContainsKey(name))? y.Nodes[name].Nodes.ToDictionary(a => a.Key,
|
||||
a => (string[])FieldLoader.GetValue( "(value)", typeof(string[]), a.Value.Value ))
|
||||
: new Dictionary<string, string[]>();
|
||||
|
||||
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
|
||||
public VoiceInfo( MiniYaml y )
|
||||
{
|
||||
FieldLoader.Load(this, y);
|
||||
|
||||
Pools = Lazy.New(() =>
|
||||
new Dictionary<string, VoicePool>
|
||||
{
|
||||
{ "Select", new VoicePool(Select) },
|
||||
{ "Move", new VoicePool(Move) },
|
||||
{ "Attack", new VoicePool( Attack ?? Move ) },
|
||||
{ "Die", new VoicePool(Die) },
|
||||
});
|
||||
FieldLoader.LoadFields(this, y.Nodes, new string[] { "DisableVariants" });
|
||||
Variants = Load(y, "Variants");
|
||||
Voices = Load(y, "Voices");
|
||||
|
||||
if (!Voices.ContainsKey("Attack"))
|
||||
Voices.Add("Attack", Voices["Move"]);
|
||||
|
||||
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,75 +13,68 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette : Sheet
|
||||
class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
|
||||
// We need to store the Palettes themselves for the remap palettes to work
|
||||
// We should probably try to fix this somehow
|
||||
static Dictionary<string, Palette> palettes;
|
||||
static Dictionary<string, int> indices;
|
||||
ITexture texture;
|
||||
Dictionary<string, Palette> palettes;
|
||||
Dictionary<string, int> indices;
|
||||
|
||||
public HardwarePalette(Map map)
|
||||
: base(new Size(256, MaxPalettes))
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
try { return palettes[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
Palette ret;
|
||||
if (!palettes.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
try { return indices[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
int ret;
|
||||
if (!indices.TryGetValue(name,out ret))
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int AddPalette(string name, Palette p)
|
||||
public void AddPalette(string name, Palette p)
|
||||
{
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, allocated)] = p.GetColor(i);
|
||||
}
|
||||
return allocated++;
|
||||
}
|
||||
|
||||
public void UpdatePalette(string name, Palette p)
|
||||
{
|
||||
palettes[name] = p;
|
||||
var j = indices[name];
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, j)] = p.GetColor(i);
|
||||
}
|
||||
indices.Add(name, allocated++);
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
var b = new Bitmap(Bitmap);
|
||||
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
|
||||
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(b);
|
||||
|
||||
Texture.SetData(b);
|
||||
Game.Renderer.PaletteTexture = Texture;
|
||||
mod.AdjustPalette(copy);
|
||||
|
||||
var data = new uint[MaxPalettes,256];
|
||||
foreach (var pal in copy)
|
||||
{
|
||||
var j = indices[pal.Key];
|
||||
var c = pal.Value.Values;
|
||||
for (var i = 0; i < 256; i++)
|
||||
data[j,i] = c[i];
|
||||
}
|
||||
|
||||
// Doesn't work
|
||||
texture.SetData(data);
|
||||
Game.Renderer.PaletteTexture = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace OpenRA.Graphics
|
||||
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||
PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
|
||||
|
||||
foreach (var r in world.WorldActor.traits.WithInterface<IRenderOverlay>())
|
||||
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
|
||||
r.Render();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,6 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
Timer.Time( "DrawRegions start" );
|
||||
|
||||
world.WorldRenderer.palette.Update(
|
||||
world.WorldActor.traits.WithInterface<IPaletteModifier>());
|
||||
|
||||
float2 r1 = new float2(2, -2) / screenSize;
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
@@ -76,9 +73,16 @@ namespace OpenRA.Graphics
|
||||
Timer.Time( "endFrame: {0}" );
|
||||
}
|
||||
|
||||
public void RefreshPalette()
|
||||
{
|
||||
Game.world.WorldRenderer.palette.Update(
|
||||
Game.world.WorldActor.TraitsImplementing<IPaletteModifier>());
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
cursorFrame += 0.5f;
|
||||
RefreshPalette();
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(int2 loc)
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace OpenRA.Graphics
|
||||
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
|
||||
public Palette GetPalette(string name) { return palette.GetPalette(name); }
|
||||
public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
|
||||
public void UpdatePalette(string name, Palette pal) { palette.UpdatePalette(name, pal); }
|
||||
|
||||
class SpriteComparer : IComparer<Renderable>
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace OpenRA.Network
|
||||
order.Player.Stances[targetPlayer] = (Stance)order.TargetLocation.Y;
|
||||
|
||||
if (targetPlayer == world.LocalPlayer)
|
||||
world.WorldActor.traits.Get<Shroud>().UpdatePlayerStance(world, order.Player, oldStance, order.Player.Stances[targetPlayer]);
|
||||
world.WorldActor.Trait<Shroud>().UpdatePlayerStance(world, order.Player, oldStance, order.Player.Stances[targetPlayer]);
|
||||
|
||||
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
|
||||
order.Player.PlayerName, targetPlayer.PlayerName, order.Player.Stances[targetPlayer]));
|
||||
@@ -79,7 +79,7 @@ namespace OpenRA.Network
|
||||
default:
|
||||
{
|
||||
if( !order.IsImmediate )
|
||||
foreach (var t in order.Subject.traits.WithInterface<IResolveOrder>())
|
||||
foreach (var t in order.Subject.TraitsImplementing<IResolveOrder>())
|
||||
t.ResolveOrder(order.Subject, order);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -221,6 +221,8 @@
|
||||
<Compile Include="Traits\Health.cs" />
|
||||
<Compile Include="Traits\RepairableBuilding.cs" />
|
||||
<Compile Include="Traits\Activities\Drag.cs" />
|
||||
<Compile Include="Widgets\VqaPlayerWidget.cs" />
|
||||
<Compile Include="Widgets\Delegates\VideoPlayerDelegate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
@@ -230,6 +232,7 @@
|
||||
<Compile Include="ActorInitializer.cs" />
|
||||
<Compile Include="ActorReference.cs" />
|
||||
<Compile Include="Map.cs" />
|
||||
<Compile Include="Traits\PrimaryBuilding.cs" />
|
||||
<Compile Include="Widgets\Delegates\DeveloperModeDelegate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -260,7 +263,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Folder Include="Traits\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Orders
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
var producing = Producer.traits.Get<Traits.ProductionQueue>().CurrentItem( Rules.Info[ Building ].Category );
|
||||
var producing = Producer.Trait<Traits.ProductionQueue>().CurrentItem( Rules.Info[ Building ].Category );
|
||||
if (producing == null || producing.Item != Building || producing.RemainingTime != 0)
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
@@ -38,21 +38,21 @@ namespace OpenRA.Orders
|
||||
public void RenderBeforeWorld(World world)
|
||||
{
|
||||
foreach (var a in world.Selection.Actors)
|
||||
foreach (var t in a.traits.WithInterface<IPreRenderSelection>())
|
||||
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
|
||||
t.RenderBeforeWorld(a);
|
||||
}
|
||||
|
||||
public void RenderAfterWorld( World world )
|
||||
{
|
||||
foreach (var a in world.Selection.Actors)
|
||||
foreach (var t in a.traits.WithInterface<IPostRenderSelection>())
|
||||
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
|
||||
t.RenderAfterWorld(a);
|
||||
}
|
||||
|
||||
public string GetCursor( World world, int2 xy, MouseInput mi )
|
||||
{
|
||||
var c = Order(world, xy, mi)
|
||||
.Select(o => o.Subject.traits.WithInterface<IOrderCursor>()
|
||||
.Select(o => o.Subject.TraitsImplementing<IOrderCursor>()
|
||||
.Select(pc => pc.CursorForOrder(o.Subject, o)).FirstOrDefault(a => a != null))
|
||||
.FirstOrDefault(a => a != null);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace OpenRA
|
||||
{
|
||||
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
||||
{
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
var mobile = self.Trait<Mobile>();
|
||||
var tilesInRange = world.FindTilesInCircle(target, range)
|
||||
.Where( t => mobile.CanEnterCell(t));
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace OpenRA
|
||||
return q =>
|
||||
p != q &&
|
||||
((p - q).LengthSquared < dist * dist) &&
|
||||
(world.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(q).Any(a => a.Group != self.Group));
|
||||
(world.WorldActor.Trait<UnitInfluence>().GetUnitsAt(q).Any(a => a.Group != self.Group));
|
||||
}
|
||||
|
||||
public List<int2> FindPath( PathSearch search )
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA
|
||||
this.self = self;
|
||||
world = self.World;
|
||||
cellInfo = InitCellInfo();
|
||||
mobile = self.traits.Get<Mobile>();
|
||||
mobile = self.Trait<Mobile>();
|
||||
queue = new PriorityQueue<PathDistance>();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA
|
||||
public void Add(World w, Actor a)
|
||||
{
|
||||
actors.Add(a);
|
||||
foreach (var ns in w.WorldActor.traits.WithInterface<INotifySelection>())
|
||||
foreach (var ns in w.WorldActor.TraitsImplementing<INotifySelection>())
|
||||
ns.SelectionChanged();
|
||||
}
|
||||
|
||||
@@ -42,9 +42,10 @@ namespace OpenRA
|
||||
actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList();
|
||||
|
||||
var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasVoice());
|
||||
Sound.PlayVoice("Select", voicedUnit);
|
||||
if (voicedUnit != null)
|
||||
Sound.PlayVoice("Select", voicedUnit, voicedUnit.Owner.Country.Race);
|
||||
|
||||
foreach (var ns in world.WorldActor.traits.WithInterface<INotifySelection>())
|
||||
foreach (var ns in world.WorldActor.TraitsImplementing<INotifySelection>())
|
||||
ns.SelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ namespace OpenRA.Server
|
||||
static string masterServerUrl;
|
||||
static bool isInitialPing;
|
||||
|
||||
public static void ServerMain(bool internetServer, string masterServerUrl, string name, int port, int extport, string[] mods, string map, bool cheats)
|
||||
public static void ServerMain(bool internetServer, string masterServerUrl, string name, int port, int extport,
|
||||
string[] mods, string map, bool cheats)
|
||||
{
|
||||
Log.AddChannel("server", "server.log", false, false);
|
||||
|
||||
@@ -86,7 +87,7 @@ namespace OpenRA.Server
|
||||
checkRead.Add( listener.Server );
|
||||
foreach( var c in conns ) checkRead.Add( c.socket );
|
||||
|
||||
Socket.Select( checkRead, null, null, MasterPingInterval * 1000000 );
|
||||
Socket.Select( checkRead, null, null, MasterPingInterval * 10000 );
|
||||
|
||||
foreach( Socket s in checkRead )
|
||||
if( s == listener.Server ) AcceptConnection();
|
||||
@@ -94,6 +95,10 @@ namespace OpenRA.Server
|
||||
|
||||
if (Environment.TickCount - lastPing > MasterPingInterval * 1000)
|
||||
PingMasterServer();
|
||||
else
|
||||
lock (masterServerMessages)
|
||||
while (masterServerMessages.Count > 0)
|
||||
SendChat(null, masterServerMessages.Dequeue());
|
||||
|
||||
if (conns.Count() == 0)
|
||||
{
|
||||
@@ -420,8 +425,6 @@ namespace OpenRA.Server
|
||||
|
||||
public static void DropClient(Connection toDrop, Exception e)
|
||||
{
|
||||
Log.Write("server", "Client dropped: {0}.", toDrop.socket.RemoteEndPoint);
|
||||
|
||||
conns.Remove(toDrop);
|
||||
SendChat(toDrop, "Connection Dropped");
|
||||
|
||||
@@ -447,50 +450,57 @@ namespace OpenRA.Server
|
||||
PingMasterServer();
|
||||
}
|
||||
|
||||
static volatile bool isBusy;
|
||||
static Queue<string> masterServerMessages = new Queue<string>();
|
||||
static void PingMasterServer()
|
||||
{
|
||||
if (wc.IsBusy || !isInternetServer) return;
|
||||
|
||||
var url = "ping.php?port={0}&name={1}&state={2}&players={3}&mods={4}&map={5}";
|
||||
wc.DownloadDataCompleted += PingMasterServerResponse;
|
||||
if (isInitialPing)
|
||||
{
|
||||
url += "&new=1";
|
||||
isInitialPing = false;
|
||||
}
|
||||
else
|
||||
wc.DownloadDataCompleted -= PingMasterServerResponse;
|
||||
|
||||
wc.DownloadDataAsync(new Uri(
|
||||
masterServerUrl + url.F(
|
||||
ExternalPort, Uri.EscapeUriString(Name),
|
||||
GameStarted ? 2 : 1, // todo: post-game states, etc.
|
||||
lobbyInfo.Clients.Count,
|
||||
string.Join(",", lobbyInfo.GlobalSettings.Mods),
|
||||
lobbyInfo.GlobalSettings.Map)));
|
||||
if (isBusy || !isInternetServer) return;
|
||||
|
||||
lastPing = Environment.TickCount;
|
||||
}
|
||||
isBusy = true;
|
||||
|
||||
static void PingMasterServerResponse(object sender, DownloadDataCompletedEventArgs e)
|
||||
{
|
||||
if (e.Error != null)
|
||||
{
|
||||
Log.Write("server", "Error pinging Master Server; {0}", e.Error.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Result.Length == 0)
|
||||
{
|
||||
Log.Write("server", "Error pinging Master Server; Empty Response");
|
||||
return;
|
||||
}
|
||||
|
||||
string s = Encoding.UTF8.GetString(e.Result);
|
||||
int gameId;
|
||||
if (int.TryParse(s.Trim(), out gameId))
|
||||
Game.SetGameId(gameId);
|
||||
Log.Write("server", "Game ID: {0}", gameId);
|
||||
Action a = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = "ping.php?port={0}&name={1}&state={2}&players={3}&mods={4}&map={5}";
|
||||
if (isInitialPing) url += "&new=1";
|
||||
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
var result = wc.DownloadData(
|
||||
masterServerUrl + url.F(
|
||||
ExternalPort, Uri.EscapeUriString(Name),
|
||||
GameStarted ? 2 : 1, // todo: post-game states, etc.
|
||||
lobbyInfo.Clients.Count,
|
||||
string.Join(",", lobbyInfo.GlobalSettings.Mods),
|
||||
lobbyInfo.GlobalSettings.Map));
|
||||
|
||||
if (isInitialPing)
|
||||
{
|
||||
isInitialPing = false;
|
||||
|
||||
var s = Encoding.UTF8.GetString(result);
|
||||
int gameId;
|
||||
if (int.TryParse(s.Trim(), out gameId))
|
||||
Game.SetGameId(gameId);
|
||||
|
||||
lock (masterServerMessages)
|
||||
masterServerMessages.Enqueue("Master server communication established. Game ID = {0}".F(gameId));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.Write("server", ex.ToString());
|
||||
lock( masterServerMessages )
|
||||
masterServerMessages.Enqueue( "Master server communication failed." );
|
||||
}
|
||||
|
||||
isBusy = false;
|
||||
};
|
||||
|
||||
a.BeginInvoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA
|
||||
|
||||
public ShroudRenderer(Player owner, Map map)
|
||||
{
|
||||
this.shroud = owner.World.WorldActor.traits.Get<Traits.Shroud>();
|
||||
this.shroud = owner.World.WorldActor.Trait<Traits.Shroud>();
|
||||
this.map = map;
|
||||
|
||||
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
|
||||
|
||||
@@ -21,10 +21,10 @@ namespace OpenRA
|
||||
{
|
||||
static ISoundEngine soundEngine;
|
||||
static Cache<string, ISoundSource> sounds;
|
||||
static ISoundSource rawSource;
|
||||
static ISound music;
|
||||
|
||||
static bool paused;
|
||||
static bool stopped;
|
||||
static ISound video;
|
||||
static string currentMusic;
|
||||
|
||||
static ISoundSource LoadSound(string filename)
|
||||
{
|
||||
@@ -32,13 +32,18 @@ namespace OpenRA
|
||||
return soundEngine.AddSoundSourceFromMemory(data, 1, 16, 22050);
|
||||
}
|
||||
|
||||
static ISoundSource LoadSoundRaw(byte[] rawData)
|
||||
{
|
||||
return soundEngine.AddSoundSourceFromMemory(rawData, 1, 16, 22050);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
soundEngine = new OpenAlSoundEngine();
|
||||
sounds = new Cache<string, ISoundSource>(LoadSound);
|
||||
music = null;
|
||||
paused = false;
|
||||
stopped = false;
|
||||
currentMusic = null;
|
||||
video = null;
|
||||
}
|
||||
|
||||
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
|
||||
@@ -73,36 +78,59 @@ namespace OpenRA
|
||||
Play(name, pos);
|
||||
}
|
||||
|
||||
public static void PlayVideo(byte[] raw)
|
||||
{
|
||||
rawSource = LoadSoundRaw(raw);
|
||||
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, SoundVolume);
|
||||
}
|
||||
|
||||
public static void PlayVideo()
|
||||
{
|
||||
if (video != null)
|
||||
soundEngine.PauseSound(video, false);
|
||||
}
|
||||
|
||||
public static void PauseVideo()
|
||||
{
|
||||
if (video != null)
|
||||
soundEngine.PauseSound(video, true);
|
||||
}
|
||||
|
||||
public static void StopVideo()
|
||||
{
|
||||
if (video != null)
|
||||
soundEngine.StopSound(video);
|
||||
}
|
||||
|
||||
public static void PlayMusic(string name)
|
||||
{
|
||||
if (name == "" || name == null)
|
||||
return;
|
||||
|
||||
if (music != null)
|
||||
soundEngine.StopSound(music);
|
||||
if (name == currentMusic && music != null)
|
||||
{
|
||||
soundEngine.PauseSound(music, false);
|
||||
return;
|
||||
}
|
||||
StopMusic();
|
||||
|
||||
currentMusic = name;
|
||||
var sound = sounds[name];
|
||||
music = soundEngine.Play2D(sound, true, true, float2.Zero, MusicVolume);
|
||||
}
|
||||
|
||||
public static bool MusicPaused
|
||||
public static void StopMusic()
|
||||
{
|
||||
get { return paused; }
|
||||
set {
|
||||
paused = value;
|
||||
if (music != null)
|
||||
soundEngine.PauseSound(music, paused);
|
||||
}
|
||||
if (music != null)
|
||||
soundEngine.StopSound(music);
|
||||
|
||||
currentMusic = null;
|
||||
}
|
||||
|
||||
public static bool MusicStopped
|
||||
public static void PauseMusic()
|
||||
{
|
||||
get { return stopped; }
|
||||
set {
|
||||
stopped = value;
|
||||
if (music != null && stopped)
|
||||
soundEngine.StopSound(music);
|
||||
}
|
||||
if (music != null)
|
||||
soundEngine.PauseSound(music, true);
|
||||
}
|
||||
|
||||
public static float GlobalVolume
|
||||
@@ -117,7 +145,7 @@ namespace OpenRA
|
||||
set
|
||||
{
|
||||
Game.Settings.SoundVolume = value;
|
||||
soundEngine.SetSoundVolume(value, music);
|
||||
soundEngine.SetSoundVolume(value, music, video);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,8 +160,29 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public static float VideoVolume
|
||||
{
|
||||
get { return Game.Settings.VideoVolume; }
|
||||
set
|
||||
{
|
||||
Game.Settings.VideoVolume = value;
|
||||
if (video != null)
|
||||
video.Volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static float MusicSeekPosition
|
||||
{
|
||||
get { return (music != null)? music.SeekPosition : 0; }
|
||||
}
|
||||
|
||||
public static float VideoSeekPosition
|
||||
{
|
||||
get { return (video != null)? video.SeekPosition : 0; }
|
||||
}
|
||||
|
||||
// Returns true if it played a phrase
|
||||
public static bool PlayVoice(string phrase, Actor voicedUnit)
|
||||
public static bool PlayVoice(string phrase, Actor voicedUnit, string variant)
|
||||
{
|
||||
if (voicedUnit == null) return false;
|
||||
if (phrase == null) return false;
|
||||
@@ -147,20 +196,10 @@ namespace OpenRA
|
||||
var clip = vi.Pools.Value[phrase].GetNext();
|
||||
if (clip == null)
|
||||
return false;
|
||||
|
||||
if (clip.Contains(".")) /* no variants! */
|
||||
{
|
||||
Play(clip);
|
||||
return true;
|
||||
}
|
||||
|
||||
// todo: fix this
|
||||
var variants = (voicedUnit.Owner.Country.Race == "allies")
|
||||
? vi.AlliedVariants : vi.SovietVariants;
|
||||
|
||||
var variant = variants[voicedUnit.ActorID % variants.Length];
|
||||
|
||||
Play(clip + variant);
|
||||
|
||||
var variantext = (vi.Variants.ContainsKey(variant) && !vi.DisableVariants.Contains(phrase))?
|
||||
vi.Variants[variant][voicedUnit.ActorID % vi.Variants.Count] : vi.DefaultVariant;
|
||||
Play(clip + variantext);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -175,13 +214,14 @@ namespace OpenRA
|
||||
void SetAllSoundsPaused(bool paused);
|
||||
void StopAllSounds();
|
||||
void SetListenerPosition(float2 position);
|
||||
void SetSoundVolume(float volume, ISound music);
|
||||
void SetSoundVolume(float volume, ISound music, ISound video);
|
||||
}
|
||||
|
||||
interface ISoundSource {}
|
||||
interface ISound
|
||||
{
|
||||
float Volume { get; set; }
|
||||
float SeekPosition { get; }
|
||||
}
|
||||
|
||||
class OpenAlSoundEngine : ISoundEngine
|
||||
@@ -288,14 +328,15 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSoundVolume(float volume, ISound music)
|
||||
public void SetSoundVolume(float volume, ISound music, ISound video)
|
||||
{
|
||||
var sounds = sourcePool.Select(s => s.Key).Where( b =>
|
||||
{
|
||||
int state;
|
||||
Al.alGetSourcei(b, Al.AL_SOURCE_STATE, out state);
|
||||
return ((state == Al.AL_PLAYING || state == Al.AL_PAUSED) &&
|
||||
((music != null)? b != ((OpenAlSound) music).source : true));
|
||||
((music != null)? b != ((OpenAlSound) music).source : true) &&
|
||||
((video != null)? b != ((OpenAlSound) video).source : true));
|
||||
}).ToList();
|
||||
foreach (var s in sounds)
|
||||
{
|
||||
@@ -371,7 +412,6 @@ namespace OpenRA
|
||||
Al.alSourcef(source, Al.AL_REFERENCE_DISTANCE, 200);
|
||||
Al.alSourcef(source, Al.AL_MAX_DISTANCE, 1500);
|
||||
Volume = volume;
|
||||
|
||||
Al.alSourcePlay(source);
|
||||
}
|
||||
|
||||
@@ -384,5 +424,15 @@ namespace OpenRA
|
||||
Al.alSourcef(source, Al.AL_GAIN, volume = value);
|
||||
}
|
||||
}
|
||||
|
||||
public float SeekPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
float pos;
|
||||
Al.alGetSourcef(source, Al.AL_SAMPLE_OFFSET, out pos);
|
||||
return pos/22050f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace OpenRA.Traits.Activities
|
||||
|
||||
public IActivity Tick( Actor self )
|
||||
{
|
||||
var mobile = self.traits.Get<Mobile>();
|
||||
var mobile = self.Trait<Mobile>();
|
||||
|
||||
if( move != null )
|
||||
{
|
||||
@@ -165,10 +165,10 @@ namespace OpenRA.Traits.Activities
|
||||
|
||||
void NudgeBlocker(Actor self, int2 nextCell)
|
||||
{
|
||||
var blocker = self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(nextCell).FirstOrDefault();
|
||||
var blocker = self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(nextCell).FirstOrDefault();
|
||||
if (blocker == null) return;
|
||||
|
||||
var nudge = blocker.traits.GetOrDefault<INudge>();
|
||||
var nudge = blocker.TraitOrDefault<INudge>();
|
||||
if (nudge != null)
|
||||
nudge.OnNudge(blocker, self);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace OpenRA.Traits.Activities
|
||||
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
||||
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
var refundFraction = self.Info.Traits.Get<BuildingInfo>().RefundPercent * (health == null ? 1f : health.HPFraction);
|
||||
|
||||
self.Owner.PlayerActor.traits.Get<PlayerResources>().GiveCash((int)(refundFraction * cost));
|
||||
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash((int)(refundFraction * cost));
|
||||
|
||||
foreach (var ns in self.traits.WithInterface<INotifySold>())
|
||||
foreach (var ns in self.TraitsImplementing<INotifySold>())
|
||||
ns.Sold(self);
|
||||
self.World.AddFrameEndTask( _ => self.World.Remove( self ) );
|
||||
}
|
||||
@@ -37,10 +37,10 @@ namespace OpenRA.Traits.Activities
|
||||
{
|
||||
if( !started )
|
||||
{
|
||||
framesRemaining = self.traits.Get<RenderSimple>().anim.HasSequence("make")
|
||||
? self.traits.Get<RenderSimple>().anim.GetSequence( "make" ).Length : 0;
|
||||
framesRemaining = self.Trait<RenderSimple>().anim.HasSequence("make")
|
||||
? self.Trait<RenderSimple>().anim.GetSequence( "make" ).Length : 0;
|
||||
|
||||
foreach( var ns in self.traits.WithInterface<INotifySold>() )
|
||||
foreach( var ns in self.TraitsImplementing<INotifySold>() )
|
||||
ns.Selling( self );
|
||||
|
||||
started = true;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Traits.Activities
|
||||
|
||||
public IActivity Tick( Actor self )
|
||||
{
|
||||
var facing = self.traits.Get<IFacing>();
|
||||
var facing = self.Trait<IFacing>();
|
||||
|
||||
if( desiredFacing == facing.Facing )
|
||||
return NextActivity;
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Traits.Activities
|
||||
|
||||
public void Cancel( Actor self )
|
||||
{
|
||||
desiredFacing = self.traits.Get<IFacing>().Facing;
|
||||
desiredFacing = self.Trait<IFacing>().Facing;
|
||||
NextActivity = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.Traits
|
||||
|
||||
public bool Disabled
|
||||
{
|
||||
get { return self.traits.WithInterface<IDisable>().Any(t => t.Disabled); }
|
||||
get { return self.TraitsImplementing<IDisable>().Any(t => t.Disabled); }
|
||||
}
|
||||
|
||||
public Building(ActorInitializer init)
|
||||
@@ -61,14 +61,14 @@ namespace OpenRA.Traits
|
||||
|
||||
public int GetPowerUsage()
|
||||
{
|
||||
var modifier = self.traits
|
||||
.WithInterface<IPowerModifier>()
|
||||
var modifier = self
|
||||
.TraitsImplementing<IPowerModifier>()
|
||||
.Select(t => t.GetPowerModifier())
|
||||
.Product();
|
||||
|
||||
if (Info.Power > 0)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
var healthFraction = (health == null) ? 1f : health.HPFraction;
|
||||
return (int)(modifier * healthFraction * Info.Power);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
if (e.DamageState == DamageState.Dead)
|
||||
{
|
||||
self.World.WorldActor.traits.Get<ScreenShaker>().AddEffect(10, self.CenterLocation, 1);
|
||||
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(10, self.CenterLocation, 1);
|
||||
Sound.Play(Info.DestroyedSound, self.CenterLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Traits
|
||||
var oldState = this.DamageState;
|
||||
|
||||
/* apply the damage modifiers, if we have any. */
|
||||
var modifier = (float)self.traits.WithInterface<IDamageModifier>()
|
||||
var modifier = (float)self.TraitsImplementing<IDamageModifier>()
|
||||
.Select(t => t.GetDamageModifier(warhead)).Product();
|
||||
|
||||
damage = (int)(damage * modifier);
|
||||
@@ -103,7 +103,7 @@ namespace OpenRA.Traits
|
||||
|
||||
if (hp > MaxHP) hp = MaxHP;
|
||||
|
||||
foreach (var nd in self.traits.WithInterface<INotifyDamage>())
|
||||
foreach (var nd in self.TraitsImplementing<INotifyDamage>())
|
||||
nd.Damaged(self, new AttackInfo
|
||||
{
|
||||
Attacker = attacker,
|
||||
@@ -140,26 +140,26 @@ namespace OpenRA.Traits
|
||||
{
|
||||
public static bool IsDead(this Actor self)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
return (health == null) ? true : health.IsDead;
|
||||
}
|
||||
|
||||
public static DamageState GetDamageState(this Actor self)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
return (health == null) ? DamageState.Undamaged : health.DamageState;
|
||||
}
|
||||
|
||||
public static void InflictDamage(this Actor self, Actor attacker, int damage, WarheadInfo warhead)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
if (health == null) return;
|
||||
health.InflictDamage(self, attacker, damage, warhead);
|
||||
}
|
||||
|
||||
public static void Kill(this Actor self, Actor attacker)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
if (health == null) return;
|
||||
health.InflictDamage(self, attacker, health.HP, null);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace OpenRA.Traits
|
||||
{
|
||||
public readonly string[] TerrainTypes;
|
||||
public readonly float[] TerrainSpeeds;
|
||||
public readonly string[] TerrainCostOverrides;
|
||||
public readonly float[] TerrainCosts;
|
||||
public readonly string[] Crushes;
|
||||
public readonly int WaitAverage = 60;
|
||||
public readonly int WaitSpread = 20;
|
||||
@@ -77,10 +79,10 @@ namespace OpenRA.Traits
|
||||
this.self = init.self;
|
||||
this.Info = info;
|
||||
|
||||
shroud = self.World.WorldActor.traits.Get<Shroud>();
|
||||
uim = self.World.WorldActor.traits.Get<UnitInfluence>();
|
||||
bim = self.World.WorldActor.traits.Get<BuildingInfluence>();
|
||||
canShareCell = self.traits.Contains<SharesCell>();
|
||||
shroud = self.World.WorldActor.Trait<Shroud>();
|
||||
uim = self.World.WorldActor.Trait<UnitInfluence>();
|
||||
bim = self.World.WorldActor.Trait<BuildingInfluence>();
|
||||
canShareCell = self.HasTrait<SharesCell>();
|
||||
|
||||
if (init.Contains<LocationInit>())
|
||||
{
|
||||
@@ -97,9 +99,17 @@ namespace OpenRA.Traits
|
||||
if (info.TerrainTypes.Count() != info.TerrainSpeeds.Count())
|
||||
throw new InvalidOperationException("Mobile TerrainType/TerrainSpeed length mismatch");
|
||||
|
||||
if (info.TerrainCostOverrides != null)
|
||||
for (int i = 0; i < info.TerrainCostOverrides.Count(); i++)
|
||||
{
|
||||
TerrainCost.Add(info.TerrainCostOverrides[i], info.TerrainCosts[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < info.TerrainTypes.Count(); i++)
|
||||
{
|
||||
TerrainCost.Add(info.TerrainTypes[i], 1f/info.TerrainSpeeds[i]);
|
||||
{
|
||||
if (!TerrainCost.ContainsKey(info.TerrainTypes[i]))
|
||||
TerrainCost.Add(info.TerrainTypes[i], 1f/info.TerrainSpeeds[i]);
|
||||
|
||||
TerrainSpeed.Add(info.TerrainTypes[i], info.TerrainSpeeds[i]);
|
||||
}
|
||||
}
|
||||
@@ -139,7 +149,7 @@ namespace OpenRA.Traits
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
w.Add(new MoveFlash(self.World, order.TargetLocation));
|
||||
var line = self.traits.GetOrDefault<DrawLineToTarget>();
|
||||
var line = self.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTarget(self, Target.FromOrder(order), Color.Green);
|
||||
});
|
||||
@@ -193,7 +203,7 @@ namespace OpenRA.Traits
|
||||
if (Info.Crushes == null)
|
||||
return false;
|
||||
|
||||
var crushable = building.traits.WithInterface<ICrushable>();
|
||||
var crushable = building.TraitsImplementing<ICrushable>();
|
||||
if (crushable.Count() == 0)
|
||||
return false;
|
||||
|
||||
@@ -205,11 +215,11 @@ namespace OpenRA.Traits
|
||||
if (checkTransientActors && uim.AnyUnitsAt(cell))
|
||||
{
|
||||
var actors = uim.GetUnitsAt(cell).Where(a => a != self && a != ignoreActor).ToArray();
|
||||
var nonshareable = canShareCell ? actors : actors.Where(a => !a.traits.Contains<SharesCell>()).ToArray();
|
||||
var nonshareable = canShareCell ? actors : actors.Where(a => !a.HasTrait<SharesCell>()).ToArray();
|
||||
|
||||
if (canShareCell)
|
||||
{
|
||||
var shareable = actors.Where(a => a.traits.Contains<SharesCell>());
|
||||
var shareable = actors.Where(a => a.HasTrait<SharesCell>());
|
||||
|
||||
// only allow 5 in a cell
|
||||
if (shareable.Count() >= 5)
|
||||
@@ -220,8 +230,8 @@ namespace OpenRA.Traits
|
||||
if (Info.Crushes == null && nonshareable.Length > 0)
|
||||
return false;
|
||||
|
||||
if (nonshareable.Length > 0 && nonshareable.Any(a => !(a.traits.Contains<ICrushable>() &&
|
||||
a.traits.WithInterface<ICrushable>().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))))
|
||||
if (nonshareable.Length > 0 && nonshareable.Any(a => !(a.HasTrait<ICrushable>() &&
|
||||
a.TraitsImplementing<ICrushable>().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -231,10 +241,10 @@ namespace OpenRA.Traits
|
||||
|
||||
public virtual void FinishedMoving(Actor self)
|
||||
{
|
||||
var crushable = uim.GetUnitsAt(toCell).Where(a => a != self && a.traits.Contains<ICrushable>());
|
||||
var crushable = uim.GetUnitsAt(toCell).Where(a => a != self && a.HasTrait<ICrushable>());
|
||||
foreach (var a in crushable)
|
||||
{
|
||||
var crushActions = a.traits.WithInterface<ICrushable>().Where(b => b.CrushClasses.Intersect(Info.Crushes).Any());
|
||||
var crushActions = a.TraitsImplementing<ICrushable>().Where(b => b.CrushClasses.Intersect(Info.Crushes).Any());
|
||||
foreach (var b in crushActions)
|
||||
b.OnCrush(self);
|
||||
}
|
||||
@@ -253,8 +263,8 @@ namespace OpenRA.Traits
|
||||
{
|
||||
var type = self.World.GetTerrainType(cell);
|
||||
|
||||
var modifier = self.traits
|
||||
.WithInterface<ISpeedModifier>()
|
||||
var modifier = self
|
||||
.TraitsImplementing<ISpeedModifier>()
|
||||
.Select(t => t.GetSpeedModifier())
|
||||
.Product();
|
||||
return Info.Speed * TerrainSpeed[type] * modifier;
|
||||
@@ -313,7 +323,7 @@ namespace OpenRA.Traits
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
var line = self.traits.GetOrDefault<DrawLineToTarget>();
|
||||
var line = self.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(self, Target.FromCell(moveTo.Value), Color.Green);
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Traits
|
||||
}
|
||||
case "DevGiveCash":
|
||||
{
|
||||
self.traits.Get<PlayerResources>().GiveCash(Info.Cash);
|
||||
self.Trait<PlayerResources>().GiveCash(Info.Cash);
|
||||
break;
|
||||
}
|
||||
case "DevShroud":
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
var prevItems = GetNumBuildables(self.Owner);
|
||||
|
||||
var queue = self.traits.Get<ProductionQueue>();
|
||||
var queue = self.Trait<ProductionQueue>();
|
||||
var unit = Rules.Info[order.TargetString];
|
||||
var producing = queue.CurrentItem(unit.Category);
|
||||
|
||||
@@ -82,11 +82,11 @@ namespace OpenRA.Traits
|
||||
var producers = self.World.Queries.OwnedBy[ self.Owner ].WithTrait<Production>()
|
||||
.Where( x => x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains( unit.Category ) )
|
||||
.ToList();
|
||||
var producer = producers.Where( x => x.Trait.IsPrimary ).Concat( producers )
|
||||
var producer = producers.Where( x => x.Actor.IsPrimaryBuilding() ).Concat( producers )
|
||||
.FirstOrDefault();
|
||||
|
||||
if( producer.Actor != null )
|
||||
producer.Actor.traits.WithInterface<RenderSimple>().First().PlayCustomAnim( producer.Actor, "build" );
|
||||
producer.Actor.TraitsImplementing<RenderSimple>().First().PlayCustomAnim( producer.Actor, "build" );
|
||||
}
|
||||
|
||||
static int GetNumBuildables(Player p)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Traits
|
||||
void TickOre(Actor self)
|
||||
{
|
||||
OreCapacity = self.World.Queries.OwnedBy[Owner].WithTrait<IStoreOre>()
|
||||
.Sum(a => a.Actor.traits.WithInterface<IStoreOre>().Sum(b => b.Capacity));
|
||||
.Sum(a => a.Actor.TraitsImplementing<IStoreOre>().Sum(b => b.Capacity));
|
||||
|
||||
if (Ore > OreCapacity)
|
||||
Ore = OreCapacity;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
while( p.Value.Count > 0 && !Rules.TechTree.BuildableItems( self.Owner, p.Key ).Contains( p.Value[ 0 ].Item ) )
|
||||
{
|
||||
self.Owner.PlayerActor.traits.Get<PlayerResources>().GiveCash(p.Value[0].TotalCost - p.Value[0].RemainingCost); // refund what's been paid so far.
|
||||
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(p.Value[0].TotalCost - p.Value[0].RemainingCost); // refund what's been paid so far.
|
||||
FinishProduction(p.Key);
|
||||
}
|
||||
if( p.Value.Count > 0 )
|
||||
@@ -101,7 +101,7 @@ namespace OpenRA.Traits
|
||||
if (unit == null || ! unit.Traits.Contains<BuildableInfo>())
|
||||
return 0;
|
||||
|
||||
if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.traits.Get<DeveloperMode>().FastBuild) return 0;
|
||||
if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.Trait<DeveloperMode>().FastBuild) return 0;
|
||||
var ui = unit.Traits.Get<BuildableInfo>();
|
||||
var time = ui.Cost
|
||||
* self.Owner.PlayerActor.Info.Traits.Get<ProductionQueueInfo>().BuildSpeed /* todo: country-specific build speed bonus */
|
||||
@@ -139,7 +139,7 @@ namespace OpenRA.Traits
|
||||
else if( lastIndex == 0 )
|
||||
{
|
||||
var item = queue[0];
|
||||
self.Owner.PlayerActor.traits.Get<PlayerResources>().GiveCash(item.TotalCost - item.RemainingCost); // refund what's been paid so far.
|
||||
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(item.TotalCost - item.RemainingCost); // refund what's been paid so far.
|
||||
FinishProduction(category);
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ namespace OpenRA.Traits
|
||||
|
||||
static bool IsDisabledBuilding(Actor a)
|
||||
{
|
||||
var building = a.traits.GetOrDefault<Building>();
|
||||
var building = a.TraitOrDefault<Building>();
|
||||
return building != null && building.Disabled;
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace OpenRA.Traits
|
||||
var producers = self.World.Queries.OwnedBy[self.Owner]
|
||||
.WithTrait<Production>()
|
||||
.Where(x => producerTypes.Contains(x.Actor.Info))
|
||||
.OrderByDescending(x => x.Trait.IsPrimary ? 1 : 0) // prioritize the primary.
|
||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding() ? 1 : 0 ) // prioritize the primary.
|
||||
.ToArray();
|
||||
|
||||
if (producers.Length == 0)
|
||||
@@ -227,7 +227,7 @@ namespace OpenRA.Traits
|
||||
|
||||
if (Paused) return;
|
||||
|
||||
if (player.PlayerActor.traits.Get<PlayerResources>().GetPowerState() != PowerState.Normal)
|
||||
if (player.PlayerActor.Trait<PlayerResources>().GetPowerState() != PowerState.Normal)
|
||||
{
|
||||
if (--slowdown <= 0)
|
||||
slowdown = player.PlayerActor.Info.Traits.Get<ProductionQueueInfo>().LowPowerSlowdown;
|
||||
@@ -236,7 +236,7 @@ namespace OpenRA.Traits
|
||||
}
|
||||
|
||||
var costThisFrame = RemainingCost / RemainingTime;
|
||||
if (costThisFrame != 0 && !player.PlayerActor.traits.Get<PlayerResources>().TakeCash(costThisFrame)) return;
|
||||
if (costThisFrame != 0 && !player.PlayerActor.Trait<PlayerResources>().TakeCash(costThisFrame)) return;
|
||||
RemainingCost -= costThisFrame;
|
||||
RemainingTime -= 1;
|
||||
if (RemainingTime > 0) return;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
var effectivePrereq = prerequisites.Where( a => a.Traits.Get<BuildableInfo>().Owner.Contains( owner.Country.Race ) );
|
||||
var nowHasPrerequisites = effectivePrereq.Any() &&
|
||||
effectivePrereq.All( a => buildings[ a.Name ].Any( b => !b.traits.Get<Building>().Disabled ) );
|
||||
effectivePrereq.All( a => buildings[ a.Name ].Any( b => !b.Trait<Building>().Disabled ) );
|
||||
|
||||
if( nowHasPrerequisites && !hasPrerequisites )
|
||||
watcher.Available();
|
||||
|
||||
77
OpenRA.Game/Traits/PrimaryBuilding.cs
Normal file
77
OpenRA.Game/Traits/PrimaryBuilding.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
class PrimaryBuildingInfo : TraitInfo<PrimaryBuilding> { }
|
||||
|
||||
class PrimaryBuilding : IIssueOrder, IResolveOrder, IOrderCursor, ITags
|
||||
{
|
||||
bool isPrimary = false;
|
||||
public bool IsPrimary { get { return isPrimary; } }
|
||||
|
||||
public IEnumerable<TagType> GetTags()
|
||||
{
|
||||
yield return (isPrimary) ? TagType.Primary : TagType.None;
|
||||
}
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
if (mi.Button == MouseButton.Right && underCursor == self)
|
||||
return new Order("PrimaryProducer", self);
|
||||
return null;
|
||||
}
|
||||
|
||||
public string CursorForOrder(Actor self, Order order)
|
||||
{
|
||||
return (order.OrderString == "PrimaryProducer") ? "deploy" : null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "PrimaryProducer")
|
||||
SetPrimaryProducer(self, !isPrimary);
|
||||
}
|
||||
|
||||
public void SetPrimaryProducer(Actor self, bool state)
|
||||
{
|
||||
if (state == false)
|
||||
{
|
||||
isPrimary = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel existing primaries
|
||||
foreach (var p in self.Info.Traits.Get<ProductionInfo>().Produces)
|
||||
foreach (var b in self.World.Queries.OwnedBy[self.Owner]
|
||||
.WithTrait<PrimaryBuilding>()
|
||||
.Where(x => x.Trait.IsPrimary
|
||||
&& (x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains(p))))
|
||||
b.Trait.SetPrimaryProducer(b.Actor, false);
|
||||
|
||||
isPrimary = true;
|
||||
|
||||
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
|
||||
Sound.PlayToPlayer(self.Owner, eva.PrimaryBuildingSelected);
|
||||
}
|
||||
}
|
||||
|
||||
static class PrimaryExts
|
||||
{
|
||||
public static bool IsPrimaryBuilding(this Actor a)
|
||||
{
|
||||
var pb = a.TraitOrDefault<PrimaryBuilding>();
|
||||
return pb != null && pb.IsPrimary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
@@ -20,13 +18,12 @@ namespace OpenRA.Traits
|
||||
{
|
||||
public readonly float[] SpawnOffsets; // in px relative to CenterLocation
|
||||
public readonly int[] ExitCells; // in cells relative to TopLeft, supports a list for multiple exits
|
||||
public readonly bool EnablePrimary = true;
|
||||
public readonly string[] Produces = { };
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new Production(this); }
|
||||
}
|
||||
|
||||
public class Production : IIssueOrder, IResolveOrder, ITags, IOrderCursor
|
||||
public class Production
|
||||
{
|
||||
public readonly List<Pair<float2, int2>> Spawns = new List<Pair<float2, int2>>();
|
||||
public Production(ProductionInfo info)
|
||||
@@ -43,8 +40,8 @@ namespace OpenRA.Traits
|
||||
|
||||
public void DoProduction(Actor self, Actor newUnit, int2 exit, float2 spawn)
|
||||
{
|
||||
var move = newUnit.traits.Get<IMove>();
|
||||
var facing = newUnit.traits.GetOrDefault<IFacing>();
|
||||
var move = newUnit.Trait<IMove>();
|
||||
var facing = newUnit.TraitOrDefault<IFacing>();
|
||||
|
||||
// Set the physical position of the unit as the exit cell
|
||||
move.SetPosition(newUnit,exit);
|
||||
@@ -61,7 +58,7 @@ namespace OpenRA.Traits
|
||||
|
||||
// For the target line
|
||||
var target = exit;
|
||||
var rp = self.traits.GetOrDefault<RallyPoint>();
|
||||
var rp = self.TraitOrDefault<RallyPoint>();
|
||||
if (rp != null)
|
||||
{
|
||||
target = rp.rallyPoint;
|
||||
@@ -73,13 +70,13 @@ namespace OpenRA.Traits
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
var line = newUnit.traits.GetOrDefault<DrawLineToTarget>();
|
||||
var line = newUnit.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(newUnit, Target.FromCell(target), Color.Green);
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var t in self.traits.WithInterface<INotifyProduction>())
|
||||
foreach (var t in self.TraitsImplementing<INotifyProduction>())
|
||||
t.UnitProduced(self, newUnit, exit);
|
||||
|
||||
Log.Write("debug", "{0} #{1} produced by {2} #{3}", newUnit.Info.Name, newUnit.ActorID, self.Info.Name, self.ActorID);
|
||||
@@ -94,7 +91,7 @@ namespace OpenRA.Traits
|
||||
|
||||
// Todo: remove assumption on Mobile;
|
||||
// required for 3-arg CanEnterCell
|
||||
var mobile = newUnit.traits.Get<Mobile>();
|
||||
var mobile = newUnit.Trait<Mobile>();
|
||||
|
||||
// Pick a spawn/exit point pair
|
||||
// Todo: Reorder in a synced random way
|
||||
@@ -111,56 +108,6 @@ namespace OpenRA.Traits
|
||||
return false;
|
||||
}
|
||||
|
||||
// "primary building" crap - perhaps this should be split?
|
||||
bool isPrimary = false;
|
||||
public bool IsPrimary { get { return isPrimary; } }
|
||||
|
||||
public IEnumerable<TagType> GetTags()
|
||||
{
|
||||
yield return (isPrimary) ? TagType.Primary : TagType.None;
|
||||
}
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
if (mi.Button == MouseButton.Right && underCursor == self && self.Info.Traits.Get<ProductionInfo>().EnablePrimary)
|
||||
return new Order("PrimaryProducer", self);
|
||||
return null;
|
||||
}
|
||||
|
||||
public string CursorForOrder(Actor self, Order order)
|
||||
{
|
||||
return (order.OrderString == "PrimaryProducer") ? "deploy" : null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "PrimaryProducer")
|
||||
SetPrimaryProducer(self, !isPrimary);
|
||||
}
|
||||
|
||||
public void SetPrimaryProducer(Actor self, bool state)
|
||||
{
|
||||
if (state == false)
|
||||
{
|
||||
isPrimary = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel existing primaries
|
||||
foreach (var p in self.Info.Traits.Get<ProductionInfo>().Produces)
|
||||
{
|
||||
foreach (var b in self.World.Queries.OwnedBy[self.Owner]
|
||||
.WithTrait<Production>()
|
||||
.Where(x => x.Trait.IsPrimary
|
||||
&& (x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains(p))))
|
||||
{
|
||||
b.Trait.SetPrimaryProducer(b.Actor, false);
|
||||
}
|
||||
}
|
||||
isPrimary = true;
|
||||
|
||||
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
|
||||
Sound.PlayToPlayer(self.Owner,eva.PrimaryBuildingSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OpenRA.Traits
|
||||
bool UpdateActive(Actor self)
|
||||
{
|
||||
// Check if powered
|
||||
var b = self.traits.Get<Building>();
|
||||
var b = self.Trait<Building>();
|
||||
if (b.Disabled) return false;
|
||||
|
||||
var isJammed = self.World.Queries.WithTrait<JamsRadar>().Any(a => self.Owner != a.Actor.Owner
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Traits
|
||||
RepairableBuildingInfo Info;
|
||||
public RepairableBuilding(Actor self, RepairableBuildingInfo info)
|
||||
{
|
||||
Health = self.traits.Get<Health>();
|
||||
Health = self.Trait<Health>();
|
||||
Info = info;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Traits
|
||||
var costPerHp = (Info.RepairPercent * buildingValue) / Health.MaxHP;
|
||||
var hpToRepair = Math.Min(Info.RepairStep, Health.MaxHP - Health.HP);
|
||||
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
||||
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
||||
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
|
||||
{
|
||||
remainingTicks = 1;
|
||||
return;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Traits
|
||||
if (!self.IsIdle && previousLocation != self.Location)
|
||||
{
|
||||
previousLocation = self.Location;
|
||||
self.World.WorldActor.traits.Get<Shroud>().UpdateActor(self);
|
||||
self.World.WorldActor.Trait<Shroud>().UpdateActor(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace OpenRA.Traits
|
||||
|
||||
void DrawHealthBar(Actor self, float2 xy, float2 Xy)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
if (self.IsDead() || health == null)
|
||||
return;
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace OpenRA.Traits
|
||||
var pipxyBase = basePosition + new float2(-12, -7); // Correct for the offset in the shp file
|
||||
var pipxyOffset = new float2(0, 0); // Correct for offset due to multiple columns/rows
|
||||
|
||||
foreach (var pips in self.traits.WithInterface<IPips>())
|
||||
foreach (var pips in self.TraitsImplementing<IPips>())
|
||||
{
|
||||
foreach (var pip in pips.GetPips(self))
|
||||
{
|
||||
@@ -135,7 +135,7 @@ namespace OpenRA.Traits
|
||||
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file
|
||||
var tagxyOffset = new float2(0, 0); // Correct for offset due to multiple rows
|
||||
|
||||
foreach (var tags in self.traits.WithInterface<ITags>())
|
||||
foreach (var tags in self.TraitsImplementing<ITags>())
|
||||
{
|
||||
foreach (var tag in tags.GetTags())
|
||||
{
|
||||
@@ -154,9 +154,9 @@ namespace OpenRA.Traits
|
||||
|
||||
void DrawUnitPath(Actor self)
|
||||
{
|
||||
if (!Game.world.LocalPlayer.PlayerActor.traits.Get<DeveloperMode>().PathDebug) return;
|
||||
if (!Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
|
||||
|
||||
var mobile = self.traits.GetOrDefault<IMove>();
|
||||
var mobile = self.TraitOrDefault<IMove>();
|
||||
if (mobile != null)
|
||||
{
|
||||
var alt = new float2(0, -mobile.Altitude);
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Traits
|
||||
RemainingTime = TotalTime;
|
||||
Owner = self.Owner;
|
||||
|
||||
self.traits.Get<TechTreeCache>().Add( Info.Prerequisites.Select( a => Rules.Info[ a.ToLowerInvariant() ] ).ToList(), this );
|
||||
self.Trait<TechTreeCache>().Add( Info.Prerequisites.Select( a => Rules.Info[ a.ToLowerInvariant() ] ).ToList(), this );
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
@@ -69,7 +69,7 @@ namespace OpenRA.Traits
|
||||
|
||||
if (IsAvailable && (!Info.RequiresPower || IsPowered()))
|
||||
{
|
||||
if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.traits.Get<DeveloperMode>().FastCharge) RemainingTime = 0;
|
||||
if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.Trait<DeveloperMode>().FastCharge) RemainingTime = 0;
|
||||
if (RemainingTime > 0) --RemainingTime;
|
||||
if (!notifiedCharging)
|
||||
{
|
||||
@@ -96,10 +96,10 @@ namespace OpenRA.Traits
|
||||
.Where(a => Rules.Info[a].Traits.Get<ValuedInfo>().Owner.Contains(Owner.Country.Race));
|
||||
|
||||
if (Info.Prerequisites.Count() == 0)
|
||||
return Owner.PlayerActor.traits.Get<PlayerResources>().GetPowerState() == PowerState.Normal;
|
||||
return Owner.PlayerActor.Trait<PlayerResources>().GetPowerState() == PowerState.Normal;
|
||||
|
||||
return effectivePrereq.Any() &&
|
||||
effectivePrereq.All(a => buildings[a].Any(b => !b.traits.Get<Building>().Disabled));
|
||||
effectivePrereq.All(a => buildings[a].Any(b => !b.Trait<Building>().Disabled));
|
||||
}
|
||||
|
||||
public void FinishActivate()
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
@@ -95,7 +96,7 @@ namespace OpenRA.Traits
|
||||
public interface ISpeedModifier { float GetSpeedModifier(); }
|
||||
public interface IPowerModifier { float GetPowerModifier(); }
|
||||
public interface IFirepowerModifier { float GetFirepowerModifier(); }
|
||||
public interface IPaletteModifier { void AdjustPalette(Bitmap b); }
|
||||
public interface IPaletteModifier { void AdjustPalette(Dictionary<string,Palette> b); }
|
||||
public interface IPips { IEnumerable<PipType> GetPips(Actor self); }
|
||||
public interface ITags { IEnumerable<TagType> GetTags(); }
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
this.info = info;
|
||||
turretFacing = info.InitialFacing;
|
||||
facing = self.traits.GetOrDefault<IFacing>();
|
||||
facing = self.TraitOrDefault<IFacing>();
|
||||
}
|
||||
|
||||
public void Tick( Actor self )
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
@@ -37,9 +37,9 @@ namespace OpenRA.Traits
|
||||
bibSprites = info.BibTypes.Select(x => SpriteSheetBuilder.LoadAllSprites(x)).ToArray();
|
||||
|
||||
self.World.ActorAdded +=
|
||||
a => { if (a.traits.Contains<Bib>()) DoBib(a,true); };
|
||||
a => { if (a.HasTrait<Bib>()) DoBib(a,true); };
|
||||
self.World.ActorRemoved +=
|
||||
a => { if (a.traits.Contains<Bib>()) DoBib(a,false); };
|
||||
a => { if (a.HasTrait<Bib>()) DoBib(a,false); };
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w)
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Traits
|
||||
|
||||
int bib = Array.IndexOf(info.BibWidths,size);
|
||||
if (bib < 0)
|
||||
{
|
||||
{
|
||||
Log.Write("debug", "Cannot bib {0}-wide building {1}", size, b.Info.Name);
|
||||
return;
|
||||
}
|
||||
@@ -72,23 +72,23 @@ namespace OpenRA.Traits
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
var cliprect = Game.viewport.ShroudBounds().HasValue
|
||||
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
|
||||
|
||||
var minx = cliprect.Left;
|
||||
var maxx = cliprect.Right;
|
||||
|
||||
var miny = cliprect.Top;
|
||||
var maxy = cliprect.Bottom;
|
||||
|
||||
for (int x = minx; x < maxx; x++)
|
||||
{
|
||||
var cliprect = Game.viewport.ShroudBounds().HasValue
|
||||
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
|
||||
|
||||
var minx = cliprect.Left;
|
||||
var maxx = cliprect.Right;
|
||||
|
||||
var miny = cliprect.Top;
|
||||
var maxy = cliprect.Bottom;
|
||||
|
||||
for (int x = minx; x < maxx; x++)
|
||||
for (int y = miny; y < maxy; y++)
|
||||
{
|
||||
var t = new int2(x, y);
|
||||
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(t) || tiles[x,y].type == 0) continue;
|
||||
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(bibSprites[tiles[x, y].type - 1][tiles[x, y].image],
|
||||
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(t) || tiles[x,y].type == 0) continue;
|
||||
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(bibSprites[tiles[x, y].type - 1][tiles[x, y].image],
|
||||
Game.CellSize * t, "terrain");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ namespace OpenRA.Traits
|
||||
influence = new Actor[map.MapSize.X, map.MapSize.Y];
|
||||
|
||||
world.ActorAdded +=
|
||||
a => { if (a.traits.Contains<Building>())
|
||||
ChangeInfluence(a, a.traits.Get<Building>(), true); };
|
||||
a => { if (a.HasTrait<Building>())
|
||||
ChangeInfluence(a, a.Trait<Building>(), true); };
|
||||
world.ActorRemoved +=
|
||||
a => { if (a.traits.Contains<Building>())
|
||||
ChangeInfluence(a, a.traits.Get<Building>(), false); };
|
||||
a => { if (a.HasTrait<Building>())
|
||||
ChangeInfluence(a, a.Trait<Building>(), false); };
|
||||
}
|
||||
|
||||
void ChangeInfluence( Actor a, Building building, bool isAdd )
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace OpenRA.Traits
|
||||
this.world = w;
|
||||
content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y];
|
||||
|
||||
resourceTypes = w.WorldActor.traits.WithInterface<ResourceType>().ToArray();
|
||||
resourceTypes = w.WorldActor.TraitsImplementing<ResourceType>().ToArray();
|
||||
foreach (var rt in resourceTypes)
|
||||
rt.info.Sprites = rt.info.SpriteNames.Select(a => SpriteSheetBuilder.LoadAllSprites(a)).ToArray();
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Traits
|
||||
|
||||
void AddActor(Actor a)
|
||||
{
|
||||
if (!a.traits.Contains<RevealsShroud>())
|
||||
if (!a.HasTrait<RevealsShroud>())
|
||||
return;
|
||||
|
||||
if (a.Owner == null || a.Owner.World.LocalPlayer == null
|
||||
@@ -78,7 +78,7 @@ namespace OpenRA.Traits
|
||||
|
||||
var v = new ActorVisibility
|
||||
{
|
||||
range = a.traits.Get<RevealsShroud>().RevealRange,
|
||||
range = a.Trait<RevealsShroud>().RevealRange,
|
||||
vis = GetVisOrigins(a).ToArray()
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace OpenRA.Traits
|
||||
}
|
||||
else
|
||||
{
|
||||
var mobile = a.traits.GetOrDefault<Mobile>();
|
||||
var mobile = a.TraitOrDefault<Mobile>();
|
||||
if (mobile != null)
|
||||
return new[] { mobile.fromCell, mobile.toCell };
|
||||
else
|
||||
@@ -170,6 +170,16 @@ namespace OpenRA.Traits
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public void ExploreAll(World world)
|
||||
{
|
||||
for (int i = map.TopLeft.X; i < map.BottomRight.X; i++)
|
||||
for (int j = map.TopLeft.Y; j < map.BottomRight.Y; j++)
|
||||
exploredCells[i, j] = true;
|
||||
exploredBounds = new Rectangle(world.Map.TopLeft.X,world.Map.TopLeft.Y,world.Map.Width,world.Map.Height);
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public void ResetExploration() // for `hide map` crate
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRA.Traits
|
||||
for (int j = 0; j < world.Map.MapSize.Y; j++)
|
||||
influence[ i, j ] = new List<Actor>();
|
||||
|
||||
world.ActorRemoved += a => Remove( a, a.traits.GetOrDefault<IOccupySpace>() );
|
||||
world.ActorRemoved += a => Remove( a, a.TraitOrDefault<IOccupySpace>() );
|
||||
}
|
||||
|
||||
public void Tick( Actor self )
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Traits
|
||||
for( int y = 0 ; y < self.World.Map.MapSize.Y ; y++ )
|
||||
if( influence[ x, y ] != null )
|
||||
foreach (var a in influence[ x, y ])
|
||||
if (!a.traits.Get<IOccupySpace>().OccupiedCells().Contains( new int2( x, y ) ) )
|
||||
if (!a.Trait<IOccupySpace>().OccupiedCells().Contains( new int2( x, y ) ) )
|
||||
throw new InvalidOperationException( "UIM: Sanity check failed A" );
|
||||
|
||||
foreach( var t in self.World.Queries.WithTraitMultiple<IOccupySpace>() )
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenRA
|
||||
{
|
||||
if (Game.Settings.UnitDebug)
|
||||
{
|
||||
var uim = world.WorldActor.traits.Get<UnitInfluence>();
|
||||
var uim = world.WorldActor.Trait<UnitInfluence>();
|
||||
|
||||
for (var i = world.Map.Bounds.Left; i < world.Map.Bounds.Right; i++)
|
||||
for (var j = world.Map.Bounds.Top; j < world.Map.Bounds.Bottom; j++)
|
||||
@@ -68,7 +68,7 @@ namespace OpenRA
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = world.WorldActor.traits.Get<ResourceLayer>();
|
||||
var res = world.WorldActor.Trait<ResourceLayer>();
|
||||
var isCloseEnough = world.IsCloseEnoughToBase(world.LocalPlayer, name, bi, topLeft);
|
||||
foreach (var t in Footprint.Tiles(name, bi, topLeft))
|
||||
Game.Renderer.SpriteRenderer.DrawSprite((isCloseEnough && world.IsCellBuildable(t, bi.WaterBound) && res.GetResource(t) == null)
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
};
|
||||
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_CHECKBOX_SHROUD").Checked =
|
||||
() => Game.world.LocalPlayer.PlayerActor.traits.Get<DeveloperMode>().DisableShroud;
|
||||
() => Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().DisableShroud;
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_CHECKBOX_SHROUD").OnMouseDown = mi =>
|
||||
{
|
||||
Game.IssueOrder(new Order("DevShroud", Game.world.LocalPlayer.PlayerActor));
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
};
|
||||
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_CHECKBOX_PATHDEBUG").Checked =
|
||||
() => Game.world.LocalPlayer.PlayerActor.traits.Get<DeveloperMode>().PathDebug;
|
||||
() => Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug;
|
||||
devmodeBG.GetWidget("SETTINGS_CHECKBOX_PATHDEBUG").OnMouseDown = mi =>
|
||||
{
|
||||
Game.IssueOrder(new Order("DevPathDebug", Game.world.LocalPlayer.PlayerActor));
|
||||
@@ -71,7 +71,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
};
|
||||
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_BUILD_SPEED").Checked =
|
||||
() => Game.world.LocalPlayer.PlayerActor.traits.Get<DeveloperMode>().FastBuild;
|
||||
() => Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().FastBuild;
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_BUILD_SPEED").OnMouseDown = mi =>
|
||||
{
|
||||
Game.IssueOrder(new Order("DevFastBuild", Game.world.LocalPlayer.PlayerActor));
|
||||
@@ -79,7 +79,7 @@ namespace OpenRA.Widgets.Delegates
|
||||
};
|
||||
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_CHARGE_TIME").Checked =
|
||||
() => Game.world.LocalPlayer.PlayerActor.traits.Get<DeveloperMode>().FastCharge;
|
||||
() => Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().FastCharge;
|
||||
devmodeBG.GetWidget<CheckboxWidget>("SETTINGS_CHARGE_TIME").OnMouseDown = mi =>
|
||||
{
|
||||
Game.IssueOrder(new Order("DevFastCharge", Game.world.LocalPlayer.PlayerActor));
|
||||
|
||||
@@ -20,18 +20,21 @@ namespace OpenRA.Widgets.Delegates
|
||||
public class LobbyDelegate : IWidgetDelegate
|
||||
{
|
||||
Widget Players, LocalPlayerTemplate, RemotePlayerTemplate;
|
||||
|
||||
|
||||
Dictionary<string, string> CountryNames;
|
||||
|
||||
string MapUid;
|
||||
MapStub Map;
|
||||
|
||||
bool SplitPlayerPalette = false;
|
||||
Palette BasePlayerPalette = null;
|
||||
|
||||
public static Color CurrentColorPreview1;
|
||||
public static Color CurrentColorPreview2;
|
||||
|
||||
public LobbyDelegate()
|
||||
{
|
||||
Game.LobbyInfoChanged += UpdateCurrentMap;
|
||||
UpdateCurrentMap();
|
||||
|
||||
CurrentColorPreview1 = Game.Settings.PlayerColor1;
|
||||
CurrentColorPreview2 = Game.Settings.PlayerColor2;
|
||||
|
||||
var r = Widget.RootWidget;
|
||||
var lobby = r.GetWidget("SERVER_LOBBY");
|
||||
@@ -140,23 +143,18 @@ namespace OpenRA.Widgets.Delegates
|
||||
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
|
||||
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
|
||||
|
||||
hueSlider.OnChange += _ => UpdateColorPreview(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
satSlider.OnChange += _ => UpdateColorPreview(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
lumSlider.OnChange += _ => UpdateColorPreview(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
rangeSlider.OnChange += _ => UpdateColorPreview(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
hueSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
satSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
lumSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
rangeSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
|
||||
colorChooser.GetWidget<ButtonWidget>("BUTTON_OK").OnMouseUp = mi =>
|
||||
{
|
||||
colorChooser.IsVisible = () => false;
|
||||
UpdatePlayerColor(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
colorChooser.IsVisible = () => false;
|
||||
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
UpdatePlayerColor(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
return true;
|
||||
};
|
||||
|
||||
// Copy the base palette for the colorpicker
|
||||
var info = Rules.Info["world"].Traits.Get<PlayerColorPaletteInfo>();
|
||||
BasePlayerPalette = Game.world.WorldRenderer.GetPalette(info.BasePalette);
|
||||
SplitPlayerPalette = info.SplitRamp;
|
||||
Game.world.WorldRenderer.AddPalette("colorpicker",BasePlayerPalette);
|
||||
};
|
||||
}
|
||||
|
||||
void UpdatePlayerColor(float hf, float sf, float lf, float r)
|
||||
@@ -172,22 +170,22 @@ namespace OpenRA.Widgets.Delegates
|
||||
|
||||
void UpdateColorPreview(float hf, float sf, float lf, float r)
|
||||
{
|
||||
var c1 = ColorFromHSL(hf, sf, lf);
|
||||
var c2 = ColorFromHSL(hf, sf, r*lf);
|
||||
Game.world.WorldRenderer.UpdatePalette("colorpicker", new Palette(BasePlayerPalette, new PlayerColorRemap(c1, c2, SplitPlayerPalette)));
|
||||
CurrentColorPreview1 = ColorFromHSL(hf, sf, lf);
|
||||
CurrentColorPreview2 = ColorFromHSL(hf, sf, r*lf);
|
||||
Game.viewport.RefreshPalette();
|
||||
}
|
||||
|
||||
Color ColorFromHSL(float h, float s, float l)
|
||||
|
||||
// hk is hue in the range [0,1] instead of [0,360]
|
||||
Color ColorFromHSL(float hk, float s, float l)
|
||||
{
|
||||
// Convert from HSL to RGB
|
||||
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
|
||||
var p = 2 * l - q;
|
||||
var hk = h / 360.0f;
|
||||
|
||||
double[] trgb = { hk + 1 / 3.0f,
|
||||
float[] trgb = { hk + 1 / 3.0f,
|
||||
hk,
|
||||
hk - 1/3.0f };
|
||||
double[] rgb = { 0, 0, 0 };
|
||||
float[] rgb = { 0, 0, 0 };
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
@@ -287,9 +285,9 @@ namespace OpenRA.Widgets.Delegates
|
||||
lumSlider.Offset = Game.LocalClient.Color1.GetBrightness();
|
||||
|
||||
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
|
||||
rangeSlider.Offset = Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness();
|
||||
rangeSlider.Offset = Game.LocalClient.Color1.GetBrightness() == 0 ? 0 : Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness();
|
||||
|
||||
UpdateColorPreview(360*hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
|
||||
colorChooser.IsVisible = () => true;
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Drawing;
|
||||
using OpenRA.Support;
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
||||
@@ -12,75 +16,125 @@ namespace OpenRA.Widgets.Delegates
|
||||
{
|
||||
public class MusicPlayerDelegate : IWidgetDelegate
|
||||
{
|
||||
string CurrentSong = null;
|
||||
public MusicPlayerDelegate()
|
||||
{
|
||||
var bg = Widget.RootWidget.GetWidget("MUSIC_BG");
|
||||
bg.Visible = Game.Settings.MusicPlayer;
|
||||
//bg.Visible = Game.Settings.MusicPlayer;
|
||||
CurrentSong = GetNextSong();
|
||||
|
||||
bg.GetWidget("BUTTON_PLAY").OnMouseUp = mi =>
|
||||
{
|
||||
if (Sound.MusicStopped)
|
||||
Sound.PlayMusic(GetSong());
|
||||
Sound.MusicStopped = false;
|
||||
Sound.MusicPaused = false;
|
||||
if (CurrentSong == null)
|
||||
return true;
|
||||
|
||||
Sound.PlayMusic(Rules.Music[CurrentSong].Filename);
|
||||
bg.GetWidget("BUTTON_PLAY").Visible = false;
|
||||
bg.GetWidget("BUTTON_PAUSE").Visible = true;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
bg.GetWidget("BUTTON_PAUSE").OnMouseUp = mi =>
|
||||
{
|
||||
Sound.MusicPaused = true;
|
||||
{
|
||||
Sound.PauseMusic();
|
||||
bg.GetWidget("BUTTON_PAUSE").Visible = false;
|
||||
bg.GetWidget("BUTTON_PLAY").Visible = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
bg.GetWidget("BUTTON_STOP").OnMouseUp = mi =>
|
||||
{
|
||||
Sound.MusicStopped = true;
|
||||
Sound.StopMusic();
|
||||
bg.GetWidget("BUTTON_PAUSE").Visible = false;
|
||||
bg.GetWidget("BUTTON_PLAY").Visible = true;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
bg.GetWidget("BUTTON_NEXT").OnMouseUp = mi =>
|
||||
{
|
||||
Sound.PlayMusic(GetNextSong());
|
||||
Sound.MusicStopped = false;
|
||||
Sound.MusicPaused = false;
|
||||
bg.GetWidget("BUTTON_PLAY").Visible = false;
|
||||
bg.GetWidget("BUTTON_PAUSE").Visible = true;
|
||||
return true;
|
||||
CurrentSong = GetNextSong();
|
||||
return bg.GetWidget("BUTTON_PLAY").OnMouseUp(mi);
|
||||
};
|
||||
|
||||
bg.GetWidget("BUTTON_PREV").OnMouseUp = mi =>
|
||||
{
|
||||
Sound.PlayMusic(GetPrevSong());
|
||||
Sound.MusicStopped = false;
|
||||
Sound.MusicPaused = false;
|
||||
bg.GetWidget("BUTTON_PLAY").Visible = false;
|
||||
bg.GetWidget("BUTTON_PAUSE").Visible = true;
|
||||
return true;
|
||||
CurrentSong = GetPrevSong();
|
||||
return bg.GetWidget("BUTTON_PLAY").OnMouseUp(mi);
|
||||
};
|
||||
}
|
||||
|
||||
bg.GetWidget<LabelWidget>("TIME").GetText = () => "{0:D2}:{1:D2} / {2:D2}:{3:D2}".F((int)Sound.MusicSeekPosition / 60, (int)Sound.MusicSeekPosition % 60,
|
||||
Rules.Music[CurrentSong].Length / 60, Rules.Music[CurrentSong].Length % 60);
|
||||
|
||||
var ml = bg.GetWidget<ListBoxWidget>("MUSIC_LIST");
|
||||
var itemTemplate = ml.GetWidget<LabelWidget>("MUSIC_TEMPLATE");
|
||||
int offset = itemTemplate.Bounds.Y;
|
||||
|
||||
foreach (var kv in Rules.Music)
|
||||
{
|
||||
var song = kv.Key;
|
||||
if (!FileSystem.Exists(Rules.Music[song].Filename))
|
||||
continue;
|
||||
|
||||
if (CurrentSong == null)
|
||||
CurrentSong = song;
|
||||
|
||||
var template = itemTemplate.Clone() as LabelWidget;
|
||||
template.Id = "SONG_{0}".F(song);
|
||||
template.GetBackground = () => ((song == CurrentSong) ? "dialog2" : null);
|
||||
template.OnMouseDown = mi =>
|
||||
{
|
||||
CurrentSong = song;
|
||||
bg.GetWidget("BUTTON_PLAY").OnMouseUp(mi);
|
||||
return true;
|
||||
};
|
||||
template.Parent = ml;
|
||||
|
||||
template.Bounds = new Rectangle(template.Bounds.X, offset, template.Bounds.Width, template.Bounds.Height);
|
||||
template.IsVisible = () => true;
|
||||
|
||||
template.GetWidget<LabelWidget>("TITLE").GetText = () => " " + Rules.Music[song].Title;
|
||||
template.GetWidget<LabelWidget>("LENGTH").GetText = () => "{0:D2}:{1:D2}".F(Rules.Music[song].Length / 60, Rules.Music[song].Length % 60);
|
||||
|
||||
ml.AddChild(template);
|
||||
|
||||
offset += template.Bounds.Height;
|
||||
ml.ContentHeight += template.Bounds.Height;
|
||||
}
|
||||
}
|
||||
|
||||
string GetNextSong()
|
||||
{
|
||||
if (!Rules.Music.ContainsKey("allmusic")) return null;
|
||||
return Rules.Music["allmusic"].Pool.GetNext();
|
||||
var songs = Rules.Music.Select(a => a.Key)
|
||||
.Where(a => FileSystem.Exists(Rules.Music[a].Filename));
|
||||
|
||||
var nextSong = songs
|
||||
.SkipWhile(m => m != CurrentSong)
|
||||
.Skip(1)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (nextSong == null)
|
||||
nextSong = songs.FirstOrDefault();
|
||||
|
||||
return nextSong;
|
||||
}
|
||||
|
||||
string GetPrevSong()
|
||||
{
|
||||
if (!Rules.Music.ContainsKey("allmusic")) return null;
|
||||
return Rules.Music["allmusic"].Pool.GetPrev();
|
||||
}
|
||||
|
||||
string GetSong()
|
||||
{
|
||||
if (!Rules.Music.ContainsKey("allmusic")) return null;
|
||||
return Rules.Music["allmusic"].Pool.GetCurrent();
|
||||
var songs = Rules.Music.Select(a => a.Key)
|
||||
.Where(a => FileSystem.Exists(Rules.Music[a].Filename))
|
||||
.Reverse();
|
||||
|
||||
var nextSong = songs
|
||||
.SkipWhile(m => m != CurrentSong)
|
||||
.Skip(1)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (nextSong == null)
|
||||
nextSong = songs.FirstOrDefault();
|
||||
|
||||
return nextSong;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,14 +65,6 @@ namespace OpenRA.Widgets.Delegates
|
||||
musicslider.OnChange += x => { Sound.MusicVolume = x; };
|
||||
musicslider.GetOffset = () => { return Sound.MusicVolume; };
|
||||
|
||||
var music = audio.GetWidget<CheckboxWidget>("MUSICPLAYER_CHECKBOX");
|
||||
music.Checked = () => { return Game.Settings.MusicPlayer; };
|
||||
music.OnMouseDown = mi =>
|
||||
{
|
||||
Game.Settings.MusicPlayer ^= true;
|
||||
Widget.RootWidget.GetWidget("MUSIC_BG").Visible = Game.Settings.MusicPlayer;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Display
|
||||
var display = bg.GetWidget("DISPLAY_PANE");
|
||||
@@ -148,14 +140,6 @@ namespace OpenRA.Widgets.Delegates
|
||||
return true;
|
||||
};
|
||||
|
||||
var devmode = debug.GetWidget<CheckboxWidget>("DEV_MODE_ENABLED");
|
||||
devmode.Checked = () => Game.Settings.DeveloperMode;
|
||||
devmode.OnMouseDown = mi =>
|
||||
{
|
||||
Game.Settings.DeveloperMode ^= true;
|
||||
return true;
|
||||
};
|
||||
|
||||
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
|
||||
Game.Settings.Save();
|
||||
Widget.RootWidget.CloseWindow();
|
||||
|
||||
92
OpenRA.Game/Widgets/Delegates/VideoPlayerDelegate.cs
Normal file
92
OpenRA.Game/Widgets/Delegates/VideoPlayerDelegate.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Widgets.Delegates
|
||||
{
|
||||
public class VideoPlayerDelegate : IWidgetDelegate
|
||||
{
|
||||
string Selected;
|
||||
|
||||
public VideoPlayerDelegate()
|
||||
{
|
||||
var bg = Widget.RootWidget.GetWidget("VIDEOPLAYER_MENU");
|
||||
var player = bg.GetWidget<VqaPlayerWidget>("VIDEOPLAYER");
|
||||
|
||||
var pp = bg.GetWidget("BUTTON_PLAYPAUSE");
|
||||
pp.OnMouseUp = mi =>
|
||||
{
|
||||
if (player.Paused)
|
||||
player.Play();
|
||||
else
|
||||
player.Pause();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
pp.GetWidget("PLAY").IsVisible = () => player.Paused;
|
||||
pp.GetWidget("PAUSE").IsVisible = () => !player.Paused;
|
||||
|
||||
bg.GetWidget("BUTTON_STOP").OnMouseUp = mi =>
|
||||
{
|
||||
player.Stop();
|
||||
return true;
|
||||
};
|
||||
|
||||
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
|
||||
player.Stop();
|
||||
Widget.RootWidget.CloseWindow();
|
||||
return true;
|
||||
};
|
||||
|
||||
// Menu Buttons
|
||||
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_VIDEOPLAYER").OnMouseUp = mi => {
|
||||
Widget.RootWidget.OpenWindow("VIDEOPLAYER_MENU");
|
||||
return true;
|
||||
};
|
||||
|
||||
var vl = bg.GetWidget<ListBoxWidget>("VIDEO_LIST");
|
||||
var itemTemplate = vl.GetWidget<LabelWidget>("VIDEO_TEMPLATE");
|
||||
int offset = itemTemplate.Bounds.Y;
|
||||
|
||||
foreach (var kv in Rules.Movies)
|
||||
{
|
||||
var video = kv.Key;
|
||||
var title = kv.Value;
|
||||
if (!FileSystem.Exists(video))
|
||||
continue;
|
||||
|
||||
if (Selected == null)
|
||||
player.Load(Selected = video);
|
||||
|
||||
var template = itemTemplate.Clone() as LabelWidget;
|
||||
template.Id = "VIDEO_{0}".F(video);
|
||||
template.GetText = () => " " + title;
|
||||
template.GetBackground = () => ((video == Selected) ? "dialog2" : null);
|
||||
template.OnMouseDown = mi =>
|
||||
{
|
||||
Selected = video;
|
||||
player.Load(video);
|
||||
return true;
|
||||
};
|
||||
template.Parent = vl;
|
||||
|
||||
template.Bounds = new Rectangle(template.Bounds.X, offset, template.Bounds.Width, template.Bounds.Height);
|
||||
template.IsVisible = () => true;
|
||||
vl.AddChild(template);
|
||||
|
||||
offset += template.Bounds.Height;
|
||||
vl.ContentHeight += template.Bounds.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,12 @@ namespace OpenRA.Widgets
|
||||
}
|
||||
|
||||
public override int2 ChildOrigin { get { return RenderOrigin + new int2(0, (int)ListOffset); } }
|
||||
|
||||
|
||||
public override Rectangle GetEventBounds()
|
||||
{
|
||||
return EventBounds;
|
||||
}
|
||||
|
||||
public override void Tick (World world)
|
||||
{
|
||||
if (UpPressed && ListOffset <= 0) ListOffset += ScrollVelocity;
|
||||
|
||||
131
OpenRA.Game/Widgets/VqaPlayerWidget.cs
Normal file
131
OpenRA.Game/Widgets/VqaPlayerWidget.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
{
|
||||
public class VqaPlayerWidget : Widget
|
||||
{
|
||||
Sprite videoSprite, overlaySprite;
|
||||
VqaReader video = null;
|
||||
string cachedVideo;
|
||||
float invLength;
|
||||
float2 videoOrigin, videoSize;
|
||||
uint[,] overlay;
|
||||
bool stopped;
|
||||
bool paused;
|
||||
|
||||
public bool Paused { get { return paused; } }
|
||||
|
||||
public bool DrawOverlay = true;
|
||||
public void Load(string filename)
|
||||
{
|
||||
if (filename == cachedVideo)
|
||||
return;
|
||||
|
||||
stopped = true;
|
||||
paused = true;
|
||||
Sound.StopVideo();
|
||||
|
||||
cachedVideo = filename;
|
||||
video = new VqaReader(FileSystem.Open(filename));
|
||||
|
||||
invLength = video.Framerate*1f/video.Frames;
|
||||
|
||||
var size = Math.Max(video.Width, video.Height);
|
||||
var textureSize = OpenRA.Graphics.Util.NextPowerOf2(size);
|
||||
videoSprite = new Sprite(new Sheet(new Size(textureSize,textureSize)), new Rectangle( 0, 0, video.Width, video.Height ), TextureChannel.Alpha);
|
||||
videoSprite.sheet.Texture.SetData(video.FrameData);
|
||||
|
||||
var scale = Math.Min(RenderBounds.Width / video.Width, RenderBounds.Height / video.Height);
|
||||
videoOrigin = new float2(RenderBounds.X + (RenderBounds.Width - scale*video.Width)/2, RenderBounds.Y + (RenderBounds.Height - scale*video.Height)/2);
|
||||
videoSize = new float2(video.Width * scale, video.Height * scale);
|
||||
|
||||
if (!DrawOverlay)
|
||||
return;
|
||||
|
||||
overlay = new uint[2*textureSize, 2*textureSize];
|
||||
uint black = (uint)255 << 24;
|
||||
for (var y = 0; y < video.Height; y++)
|
||||
for (var x = 0; x < video.Width; x++)
|
||||
overlay[2*y,x] = black;
|
||||
|
||||
overlaySprite = new Sprite(new Sheet(new Size(2*textureSize,2*textureSize)), new Rectangle( 0, 0, video.Width, 2*video.Height ), TextureChannel.Alpha);
|
||||
overlaySprite.sheet.Texture.SetData(overlay);
|
||||
}
|
||||
|
||||
public override void DrawInner(World world)
|
||||
{
|
||||
if (video == null)
|
||||
return;
|
||||
|
||||
if (!(stopped || paused))
|
||||
{
|
||||
var nextFrame = (int)float2.Lerp(0, video.Frames, Sound.VideoSeekPosition*invLength);
|
||||
if (nextFrame > video.Frames)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
while (nextFrame > video.CurrentFrame)
|
||||
{
|
||||
video.AdvanceFrame();
|
||||
if (nextFrame == video.CurrentFrame)
|
||||
videoSprite.sheet.Texture.SetData(video.FrameData);
|
||||
}
|
||||
}
|
||||
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(videoSprite, videoOrigin, "chrome", videoSize);
|
||||
|
||||
if (DrawOverlay)
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(overlaySprite, videoOrigin, "chrome", videoSize);
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
if (video == null)
|
||||
return;
|
||||
|
||||
if (stopped)
|
||||
Sound.PlayVideo(video.AudioData);
|
||||
else
|
||||
Sound.PlayVideo();
|
||||
|
||||
stopped = paused = false;
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
if (stopped || paused || video == null)
|
||||
return;
|
||||
|
||||
paused = true;
|
||||
Sound.PauseVideo();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (stopped || video == null)
|
||||
return;
|
||||
|
||||
stopped = true;
|
||||
paused = true;
|
||||
Sound.StopVideo();
|
||||
video.Reset();
|
||||
videoSprite.sheet.Texture.SetData(video.FrameData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ namespace OpenRA.Widgets
|
||||
}
|
||||
|
||||
public virtual Rectangle EventBounds { get { return RenderBounds; } }
|
||||
public Rectangle GetEventBounds()
|
||||
public virtual Rectangle GetEventBounds()
|
||||
{
|
||||
return Children
|
||||
.Where(c => c.IsVisible())
|
||||
@@ -318,7 +318,8 @@ namespace OpenRA.Widgets
|
||||
|
||||
public T GetWidget<T>(string id) where T : Widget
|
||||
{
|
||||
return (T)GetWidget(id);
|
||||
var widget = GetWidget(id);
|
||||
return (widget != null)? (T) widget : null;
|
||||
}
|
||||
|
||||
public void CloseWindow()
|
||||
|
||||
@@ -96,9 +96,9 @@ namespace OpenRA.Widgets
|
||||
var done = false;
|
||||
foreach (var o in orders)
|
||||
{
|
||||
foreach (var v in o.Subject.traits.WithInterface<IOrderVoice>())
|
||||
foreach (var v in o.Subject.TraitsImplementing<IOrderVoice>())
|
||||
{
|
||||
if (Sound.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), o.Subject))
|
||||
if (Sound.PlayVoice(v.VoicePhraseForOrder(o.Subject, o), o.Subject, o.Subject.Owner.Country.Race))
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
@@ -174,7 +174,7 @@ namespace OpenRA.Widgets
|
||||
IEnumerable<Actor> SelectActorsInBox(World world, float2 a, float2 b)
|
||||
{
|
||||
return world.FindUnits(a, b)
|
||||
.Where( x => x.traits.Contains<Selectable>() && x.IsVisible() )
|
||||
.Where( x => x.HasTrait<Selectable>() && x.IsVisible() )
|
||||
.GroupBy(x => (x.Owner == world.LocalPlayer) ? x.Info.Traits.Get<SelectableInfo>().Priority : 0)
|
||||
.OrderByDescending(g => g.Key)
|
||||
.Select( g => g.AsEnumerable() )
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace OpenRA
|
||||
|
||||
Timer.Time( "worldActor: {0}" );
|
||||
|
||||
foreach (var wlh in WorldActor.traits.WithInterface<ILoadWorldHook>())
|
||||
foreach (var wlh in WorldActor.TraitsImplementing<ILoadWorldHook>())
|
||||
wlh.WorldLoaded(this);
|
||||
|
||||
PathFinder = new PathFinder(this);
|
||||
@@ -235,8 +235,8 @@ namespace OpenRA
|
||||
return ret;
|
||||
ret = new CachedView<Actor, TraitPair<T>>(
|
||||
set,
|
||||
x => x.traits.Contains<T>(),
|
||||
x => new TraitPair<T> { Actor = x, Trait = x.traits.Get<T>() } );
|
||||
x => x.HasTrait<T>(),
|
||||
x => new TraitPair<T> { Actor = x, Trait = x.Trait<T>() } );
|
||||
hasTrait.Add( ret );
|
||||
return ret;
|
||||
}
|
||||
@@ -248,8 +248,8 @@ namespace OpenRA
|
||||
return ret;
|
||||
ret = new CachedView<Actor, TraitPair<T>>(
|
||||
world.actors,
|
||||
x => x.traits.Contains<T>(),
|
||||
x => x.traits.WithInterface<T>().Select( t => new TraitPair<T> { Actor = x, Trait = t } ) );
|
||||
x => x.HasTrait<T>(),
|
||||
x => x.TraitsImplementing<T>().Select( t => new TraitPair<T> { Actor = x, Trait = t } ) );
|
||||
hasTrait.Add( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace OpenRA
|
||||
|
||||
public static bool IsCellBuildable(this World world, int2 a, bool waterBound, Actor toIgnore)
|
||||
{
|
||||
if (world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(a) != null) return false;
|
||||
if (world.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(a).Any(b => b != toIgnore)) return false;
|
||||
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false;
|
||||
if (world.WorldActor.Trait<UnitInfluence>().GetUnitsAt(a).Any(b => b != toIgnore)) return false;
|
||||
|
||||
if (waterBound)
|
||||
return world.Map.IsInMap(a.X,a.Y) && GetTerrainInfo(world,a).IsWater;
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA
|
||||
{
|
||||
var u = float2.Min(a, b).ToInt2();
|
||||
var v = float2.Max(a, b).ToInt2();
|
||||
return world.WorldActor.traits.Get<SpatialBins>().ActorsInBox(u,v);
|
||||
return world.WorldActor.Trait<SpatialBins>().ActorsInBox(u,v);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnitsInCircle(this World world, float2 a, float r)
|
||||
@@ -95,7 +95,7 @@ namespace OpenRA
|
||||
|
||||
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, int2 topLeft, Actor toIgnore)
|
||||
{
|
||||
var res = world.WorldActor.traits.Get<ResourceLayer>();
|
||||
var res = world.WorldActor.Trait<ResourceLayer>();
|
||||
return Footprint.Tiles(name, building, topLeft).All(
|
||||
t => world.Map.IsInMap(t.X, t.Y) && res.GetResource(t) == null &&
|
||||
world.IsCellBuildable(t, building.WaterBound, toIgnore));
|
||||
@@ -106,11 +106,11 @@ namespace OpenRA
|
||||
if (a.World.LocalPlayer != null && a.World.LocalPlayer.Shroud.Disabled)
|
||||
return true;
|
||||
|
||||
var shroud = a.World.WorldActor.traits.Get<Shroud>();
|
||||
var shroud = a.World.WorldActor.Trait<Shroud>();
|
||||
if (!Shroud.GetVisOrigins(a).Any(o => a.World.Map.IsInMap(o) && shroud.exploredCells[o.X, o.Y])) // covered by shroud
|
||||
return false;
|
||||
|
||||
if (a.traits.WithInterface<IVisibilityModifier>().Any(t => !t.IsVisible(a)))
|
||||
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -131,7 +131,7 @@ namespace OpenRA
|
||||
{
|
||||
for( int x = scanStart.X ; x < scanEnd.X ; x++ )
|
||||
{
|
||||
var at = world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt( new int2( x, y ) );
|
||||
var at = world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt( new int2( x, y ) );
|
||||
if( at != null && at.Owner.Stances[ p ] == Stance.Ally && at.Info.Traits.Get<BuildingInfo>().BaseNormal )
|
||||
nearnessCandidates.Add( new int2( x, y ) );
|
||||
}
|
||||
|
||||
@@ -174,6 +174,7 @@ namespace OpenRA.GlRenderer
|
||||
|
||||
var mods = MakeModifiers(Sdl.SDL_GetModState());
|
||||
Game.HandleModifierKeys(mods);
|
||||
MouseEventArgs pendingMotion = null;
|
||||
|
||||
Sdl.SDL_Event e;
|
||||
while (Sdl.SDL_PollEvent(out e) != 0)
|
||||
@@ -186,6 +187,12 @@ namespace OpenRA.GlRenderer
|
||||
|
||||
case Sdl.SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (pendingMotion != null)
|
||||
{
|
||||
Game.DispatchMouseInput(MouseInputEvent.Move, pendingMotion, mods);
|
||||
pendingMotion = null;
|
||||
}
|
||||
|
||||
var button = MakeButton(e.button.button);
|
||||
lastButtonBits |= button;
|
||||
|
||||
@@ -196,6 +203,12 @@ namespace OpenRA.GlRenderer
|
||||
|
||||
case Sdl.SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
if (pendingMotion != null)
|
||||
{
|
||||
Game.DispatchMouseInput(MouseInputEvent.Move, pendingMotion, mods);
|
||||
pendingMotion = null;
|
||||
}
|
||||
|
||||
var button = MakeButton(e.button.button);
|
||||
lastButtonBits &= ~button;
|
||||
|
||||
@@ -206,9 +219,7 @@ namespace OpenRA.GlRenderer
|
||||
|
||||
case Sdl.SDL_MOUSEMOTION:
|
||||
{
|
||||
Game.DispatchMouseInput(MouseInputEvent.Move,
|
||||
new MouseEventArgs(lastButtonBits, 0, e.motion.x, e.motion.y, 0),
|
||||
mods);
|
||||
pendingMotion = new MouseEventArgs(lastButtonBits, 0, e.motion.x, e.motion.y, 0);
|
||||
} break;
|
||||
|
||||
case Sdl.SDL_KEYDOWN:
|
||||
@@ -242,6 +253,12 @@ namespace OpenRA.GlRenderer
|
||||
}
|
||||
}
|
||||
|
||||
if (pendingMotion != null)
|
||||
{
|
||||
Game.DispatchMouseInput(MouseInputEvent.Move, pendingMotion, mods);
|
||||
pendingMotion = null;
|
||||
}
|
||||
|
||||
CheckGlError();
|
||||
}
|
||||
|
||||
@@ -283,6 +300,7 @@ namespace OpenRA.GlRenderer
|
||||
|
||||
public IVertexBuffer<Vertex> CreateVertexBuffer(int size) { return new VertexBuffer<Vertex>(this, size); }
|
||||
public IIndexBuffer CreateIndexBuffer(int size) { return new IndexBuffer(this, size); }
|
||||
public ITexture CreateTexture() { return new Texture(this); }
|
||||
public ITexture CreateTexture(Bitmap bitmap) { return new Texture(this, bitmap); }
|
||||
public IShader CreateShader(Stream stream) { return new Shader(this, stream); }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -29,6 +30,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
||||
@@ -12,13 +12,21 @@ using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using Tao.OpenGl;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GlRenderer
|
||||
{
|
||||
public class Texture : ITexture
|
||||
{
|
||||
internal int texture;
|
||||
|
||||
|
||||
public Texture(GraphicsDevice dev)
|
||||
{
|
||||
Gl.glGenTextures(1, out texture);
|
||||
GraphicsDevice.CheckGlError();
|
||||
}
|
||||
|
||||
public Texture(GraphicsDevice dev, Bitmap bitmap)
|
||||
{
|
||||
Gl.glGenTextures(1, out texture);
|
||||
@@ -26,6 +34,34 @@ namespace OpenRA.GlRenderer
|
||||
SetData(bitmap);
|
||||
}
|
||||
|
||||
// An array of RGBA
|
||||
public void SetData(uint[,] colors)
|
||||
{
|
||||
int width = colors.GetUpperBound(1) + 1;
|
||||
int height = colors.GetUpperBound(0) + 1;
|
||||
|
||||
if (!IsPowerOf2(width) || !IsPowerOf2(height))
|
||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width,height));
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* ptr = &colors[0,0])
|
||||
{
|
||||
IntPtr intPtr = new IntPtr((void *) ptr);
|
||||
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture);
|
||||
GraphicsDevice.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GraphicsDevice.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
GraphicsDevice.CheckGlError();
|
||||
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, width, height,
|
||||
0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, intPtr);
|
||||
GraphicsDevice.CheckGlError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(Bitmap bitmap)
|
||||
{
|
||||
if (!IsPowerOf2(bitmap.Width) || !IsPowerOf2(bitmap.Height))
|
||||
@@ -41,7 +77,7 @@ namespace OpenRA.GlRenderer
|
||||
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadOnly,
|
||||
PixelFormat.Format32bppArgb);
|
||||
|
||||
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
GraphicsDevice.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace OpenRA.Mods.Cnc
|
||||
public DeadBuildingState(Actor self, DeadBuildingStateInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
rs = self.traits.Get<RenderSimple>();
|
||||
self.traits.Get<Health>().RemoveOnDeath = !rs.anim.HasSequence("dead");
|
||||
rs = self.Trait<RenderSimple>();
|
||||
self.Trait<Health>().RemoveOnDeath = !rs.anim.HasSequence("dead");
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Cnc
|
||||
{
|
||||
if (--poisonTicks <= 0)
|
||||
{
|
||||
var rl = self.World.WorldActor.traits.Get<ResourceLayer>();
|
||||
var rl = self.World.WorldActor.Trait<ResourceLayer>();
|
||||
var r = rl.GetResource(self.Location);
|
||||
|
||||
if (r != null && info.Resources.Contains(r.info.Name))
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.Cnc
|
||||
new AltitudeInit( Rules.Info["c17"].Traits.Get<PlaneInfo>().CruiseAltitude ),
|
||||
});
|
||||
|
||||
var cargo = a.traits.Get<Cargo>();
|
||||
var cargo = a.Trait<Cargo>();
|
||||
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
|
||||
{
|
||||
new OwnerInit( self.Owner ),
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.Mods.RA;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
using OpenRA.Traits;
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2010 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. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.Mods.RA;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA.Mods.Cnc
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Cnc
|
||||
{
|
||||
float2 startDock = harv.CenterLocation;
|
||||
float2 endDock = self.CenterLocation + new float2(-15,8);
|
||||
var harvester = harv.traits.Get<Harvester>();
|
||||
var harvester = harv.Trait<Harvester>();
|
||||
|
||||
harv.QueueActivity( new Turn(112) );
|
||||
harv.QueueActivity( new CallFunc( () =>
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Cnc
|
||||
if (!preventDock)
|
||||
{
|
||||
dockedHarv = harv;
|
||||
self.traits.Get<RenderBuilding>().PlayCustomAnim(self, "active");
|
||||
self.Trait<RenderBuilding>().PlayCustomAnim(self, "active");
|
||||
|
||||
harv.QueueActivity( new Drag(startDock, endDock, 12) );
|
||||
harv.QueueActivity( new CallFunc( () =>
|
||||
@@ -51,16 +51,16 @@ namespace OpenRA.Mods.Cnc
|
||||
harv.QueueActivity( new CallFunc( () => harvester.Visible = true, false ) );
|
||||
harv.QueueActivity( new Drag(endDock, startDock, 12) );
|
||||
harv.QueueActivity( new CallFunc( () => dockedHarv = null, false ) );
|
||||
if (harvester.LastHarvestedCell != int2.Zero)
|
||||
if (harvester.LastHarvestedCell != int2.Zero)
|
||||
{
|
||||
harv.QueueActivity( new Move(harvester.LastHarvestedCell, 5) );
|
||||
if (harv.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask( w =>
|
||||
{
|
||||
var line = harv.traits.GetOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(harv, Target.FromCell(harvester.LastHarvestedCell), Color.Green);
|
||||
});
|
||||
harv.QueueActivity( new Move(harvester.LastHarvestedCell, 5) );
|
||||
if (harv.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask( w =>
|
||||
{
|
||||
var line = harv.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(harv, Target.FromCell(harvester.LastHarvestedCell), Color.Green);
|
||||
});
|
||||
}
|
||||
}
|
||||
harv.QueueActivity( new Harvest() );
|
||||
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Cnc
|
||||
return;
|
||||
|
||||
// invisible harvester makes ceiling cat cry
|
||||
harv.traits.Get<Harvester>().Visible = true;
|
||||
harv.Trait<Harvester>().Visible = true;
|
||||
}
|
||||
|
||||
public void Selling (Actor self) { CancelDock(self, dockedHarv); }
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
public IActivity Tick( Actor self )
|
||||
{
|
||||
var facing = self.traits.Get<IFacing>();
|
||||
var facing = self.Trait<IFacing>();
|
||||
if (!Target.IsValid)
|
||||
return NextActivity;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return new Move( Target, Range ) { NextActivity = this };
|
||||
|
||||
var desiredFacing = Util.GetFacing((targetCell - self.Location).ToFloat2(), 0);
|
||||
var renderUnit = self.traits.GetOrDefault<RenderUnit>();
|
||||
var renderUnit = self.TraitOrDefault<RenderUnit>();
|
||||
var numDirs = (renderUnit != null)
|
||||
? renderUnit.anim.CurrentSequence.Facings : 8;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return new Turn( desiredFacing ) { NextActivity = this };
|
||||
}
|
||||
|
||||
var attack = self.traits.Get<AttackBase>();
|
||||
var attack = self.Trait<AttackBase>();
|
||||
attack.target = Target;
|
||||
attack.DoAttack(self);
|
||||
return this;
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
target.Owner = self.Owner;
|
||||
w.Add(target);
|
||||
|
||||
foreach (var t in target.traits.WithInterface<INotifyCapture>())
|
||||
foreach (var t in target.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(target, self, oldOwner, self.Owner);
|
||||
|
||||
w.Remove(self);
|
||||
|
||||
@@ -25,20 +25,25 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{
|
||||
if( NextActivity != null )
|
||||
return NextActivity;
|
||||
|
||||
var harv = self.Trait<Harvester>();
|
||||
|
||||
if (harv.LinkedProc == null)
|
||||
harv.ChooseNewProc(self, null);
|
||||
|
||||
if (harv.LinkedProc == null)
|
||||
return new Wait(25) { NextActivity = this };
|
||||
|
||||
var proc = harv.LinkedProc;
|
||||
|
||||
var proc = self.traits.Get<Harvester>().LinkedProc;
|
||||
|
||||
if (proc == null)
|
||||
return new Wait(10) { NextActivity = this };
|
||||
|
||||
if( self.Location != proc.Location + proc.traits.Get<IAcceptOre>().DeliverOffset )
|
||||
if( self.Location != proc.Location + proc.Trait<IAcceptOre>().DeliverOffset )
|
||||
{
|
||||
return new Move(proc.Location + proc.traits.Get<IAcceptOre>().DeliverOffset, 0) { NextActivity = this };
|
||||
return new Move(proc.Location + proc.Trait<IAcceptOre>().DeliverOffset, 0) { NextActivity = this };
|
||||
}
|
||||
else if (!isDocking)
|
||||
{
|
||||
isDocking = true;
|
||||
proc.traits.Get<IAcceptOre>().OnDock(self, this);
|
||||
proc.Trait<IAcceptOre>().OnDock(self, this);
|
||||
}
|
||||
return new Wait(10) { NextActivity = this };
|
||||
}
|
||||
|
||||
@@ -28,10 +28,16 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (isCanceled) return NextActivity;
|
||||
if (transport == null || !transport.IsInWorld) return NextActivity;
|
||||
|
||||
var cargo = transport.traits.Get<Cargo>();
|
||||
var cargo = transport.Trait<Cargo>();
|
||||
if (cargo.IsFull(transport))
|
||||
return NextActivity;
|
||||
|
||||
|
||||
|
||||
// Todo: Queue a move order to the transport? need to be
|
||||
// careful about units that can't path to the transport
|
||||
if ((transport.Location - self.Location).Length > 1)
|
||||
return NextActivity;
|
||||
|
||||
cargo.Load(transport, self);
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (d.LengthSquared < 50) /* close enough */
|
||||
return NextActivity;
|
||||
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
|
||||
var desiredFacing = Util.GetFacing(d, aircraft.Facing);
|
||||
if (aircraft.Altitude == cruiseAltitude)
|
||||
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{
|
||||
public static void Fly(Actor self, int desiredAltitude )
|
||||
{
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
var speed = .2f * aircraft.MovementSpeedForCell(self, self.Location);
|
||||
var angle = aircraft.Facing / 128f * Math.PI;
|
||||
self.CenterLocation += speed * -float2.FromAngle((float)angle);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (!Target.IsValid)
|
||||
return NextActivity;
|
||||
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
|
||||
return NextActivity;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if( isHarvesting ) return this;
|
||||
if( NextActivity != null ) return NextActivity;
|
||||
|
||||
var harv = self.traits.Get<Harvester>();
|
||||
var harv = self.Trait<Harvester>();
|
||||
harv.LastHarvestedCell = self.Location;
|
||||
|
||||
if( harv.IsFull )
|
||||
@@ -42,10 +42,10 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
bool HarvestThisTile(Actor self)
|
||||
{
|
||||
var harv = self.traits.Get<Harvester>();
|
||||
var renderUnit = self.traits.Get<RenderUnit>(); /* better have one of these! */
|
||||
var harv = self.Trait<Harvester>();
|
||||
var renderUnit = self.Trait<RenderUnit>(); /* better have one of these! */
|
||||
|
||||
var resource = self.World.WorldActor.traits.Get<ResourceLayer>().Harvest(self.Location);
|
||||
var resource = self.World.WorldActor.Trait<ResourceLayer>().Harvest(self.Location);
|
||||
if (resource == null)
|
||||
return false;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
void FindMoreResource(Actor self)
|
||||
{
|
||||
var res = self.World.WorldActor.traits.Get<ResourceLayer>();
|
||||
var res = self.World.WorldActor.Trait<ResourceLayer>();
|
||||
var harv = self.Info.Traits.Get<HarvesterInfo>();
|
||||
|
||||
self.QueueActivity(new Move(
|
||||
|
||||
@@ -26,14 +26,14 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (!target.IsValid)
|
||||
return NextActivity;
|
||||
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
|
||||
{
|
||||
self.QueueActivity(new HeliReturn());
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
var info = self.Info.Traits.Get<HelicopterInfo>();
|
||||
if (aircraft.Altitude != info.CruiseAltitude)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return this;
|
||||
}
|
||||
|
||||
var range = self.traits.Get<AttackBase>().GetMaximumRange() - 1;
|
||||
var range = self.Trait<AttackBase>().GetMaximumRange() - 1;
|
||||
var dist = target.CenterLocation - self.CenterLocation;
|
||||
|
||||
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
if (!float2.WithinEpsilon(float2.Zero, dist, range * Game.CellSize))
|
||||
self.CenterLocation += (rawSpeed / dist.Length) * dist;
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return NextActivity;
|
||||
|
||||
var info = self.Info.Traits.Get<HelicopterInfo>();
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
|
||||
if (aircraft.Altitude != info.CruiseAltitude)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (isCanceled) return NextActivity;
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
if (aircraft.Altitude == 0)
|
||||
return NextActivity;
|
||||
|
||||
|
||||
@@ -40,11 +40,11 @@ namespace OpenRA.Mods.RA.Activities
|
||||
new HeliLand(true),
|
||||
NextActivity);
|
||||
|
||||
var res = dest.traits.GetOrDefault<Reservable>();
|
||||
var res = dest.TraitOrDefault<Reservable>();
|
||||
if (res != null)
|
||||
self.traits.Get<Helicopter>().reservation = res.Reserve(self);
|
||||
self.Trait<Helicopter>().reservation = res.Reserve(self);
|
||||
|
||||
var pi = dest.traits.Get<Production>();
|
||||
var pi = dest.Trait<Production>();
|
||||
var offset = pi != null ? pi.Spawns.First().First : float2.Zero;
|
||||
|
||||
return Util.SequenceActivities(
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (target == null || target.IsDead()) return NextActivity;
|
||||
if (target.Owner == self.Owner) return NextActivity;
|
||||
|
||||
foreach (var t in target.traits.WithInterface<IAcceptSpy>())
|
||||
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
|
||||
t.OnInfiltrate(target, self);
|
||||
|
||||
self.World.AddFrameEndTask(w => w.Remove(self));
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (d.LengthSquared < 50) /* close enough */
|
||||
return NextActivity;
|
||||
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
|
||||
if (aircraft.Altitude > 0)
|
||||
--aircraft.Altitude;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{
|
||||
if (canceled) return NextActivity;
|
||||
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (!limitedAmmo.HasAmmo())
|
||||
{
|
||||
// rearm & repair at fix, then back out here to refill the minefield some more
|
||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
{ NextActivity = new Rearm() { NextActivity = new Repair(rearmTarget) { NextActivity = this } } };
|
||||
}
|
||||
|
||||
var ml = self.traits.Get<Minelayer>();
|
||||
var ml = self.Trait<Minelayer>();
|
||||
if (ml.minefield.Contains(self.Location) &&
|
||||
ShouldLayMine(self, self.Location))
|
||||
{
|
||||
@@ -64,13 +64,13 @@ namespace OpenRA.Mods.RA.Activities
|
||||
bool ShouldLayMine(Actor self, int2 p)
|
||||
{
|
||||
// if there is no unit (other than me) here, we want to place a mine here
|
||||
return !self.World.WorldActor.traits.Get<UnitInfluence>()
|
||||
return !self.World.WorldActor.Trait<UnitInfluence>()
|
||||
.GetUnitsAt(p).Any(a => a != self);
|
||||
}
|
||||
|
||||
void LayMine(Actor self)
|
||||
{
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (limitedAmmo != null) limitedAmmo.Attacking(self);
|
||||
|
||||
self.World.AddFrameEndTask(
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
this.target = target;
|
||||
initialLocation = self.CenterLocation;
|
||||
|
||||
self.traits.Get<RenderInfantry>().Attacking(self);
|
||||
self.Trait<RenderInfantry>().Attacking(self);
|
||||
Sound.Play("dogg5p.aud", self.CenterLocation);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
if (t >= 1f)
|
||||
{
|
||||
self.traits.WithInterface<IMove>().FirstOrDefault()
|
||||
self.TraitsImplementing<IMove>().FirstOrDefault()
|
||||
.SetPosition(self, Util.CellContaining(target.CenterLocation));
|
||||
|
||||
if (target.IsActor)
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (isCanceled) return NextActivity;
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (limitedAmmo == null) return NextActivity;
|
||||
|
||||
if (--remainingTicks == 0)
|
||||
@@ -33,10 +33,10 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (!limitedAmmo.GiveAmmo()) return NextActivity;
|
||||
|
||||
var hostBuilding = self.World.FindUnits(self.CenterLocation, self.CenterLocation)
|
||||
.FirstOrDefault(a => a.traits.Contains<RenderBuilding>());
|
||||
.FirstOrDefault(a => a.HasTrait<RenderBuilding>());
|
||||
|
||||
if (hostBuilding != null)
|
||||
hostBuilding.traits.Get<RenderBuilding>().PlayCustomAnim(hostBuilding, "active");
|
||||
hostBuilding.Trait<RenderBuilding>().PlayCustomAnim(hostBuilding, "active");
|
||||
|
||||
remainingTicks = ticksPerPip;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
if (isCanceled) return NextActivity;
|
||||
if (remainingTicks == 0)
|
||||
{
|
||||
var health = self.traits.GetOrDefault<Health>();
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
if (health == null) return NextActivity;
|
||||
|
||||
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
var costPerHp = (repairsUnits.URepairPercent * unitCost) / health.MaxHP;
|
||||
var hpToRepair = Math.Min(host.Info.Traits.Get<RepairsUnitsInfo>().URepairStep, health.MaxHP - health.HP);
|
||||
var cost = (int)Math.Ceiling(costPerHp * hpToRepair);
|
||||
if (!self.Owner.PlayerActor.traits.Get<PlayerResources>().TakeCash(cost))
|
||||
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
|
||||
{
|
||||
remainingTicks = 1;
|
||||
return this;
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
return NextActivity;
|
||||
|
||||
if (host != null)
|
||||
host.traits.Get<RenderBuilding>()
|
||||
host.Trait<RenderBuilding>()
|
||||
.PlayCustomAnim(host, "active");
|
||||
|
||||
remainingTicks = (int)(repairsUnits.RepairRate * 60 * 25);
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
if (target == null || target.IsDead()) return NextActivity;
|
||||
var health = target.traits.Get<Health>();
|
||||
var health = target.Trait<Health>();
|
||||
if (health.DamageState == DamageState.Undamaged)
|
||||
return NextActivity;
|
||||
|
||||
|
||||
@@ -40,16 +40,16 @@ namespace OpenRA.Mods.RA.Activities
|
||||
dest = ChooseAirfield(self);
|
||||
}
|
||||
|
||||
var res = dest.traits.GetOrDefault<Reservable>();
|
||||
var res = dest.TraitOrDefault<Reservable>();
|
||||
if (res != null)
|
||||
{
|
||||
var plane = self.traits.Get<Plane>();
|
||||
var plane = self.Trait<Plane>();
|
||||
plane.UnReserve();
|
||||
plane.reservation = res.Reserve(self);
|
||||
}
|
||||
|
||||
var landPos = dest.CenterLocation;
|
||||
var aircraft = self.traits.Get<Aircraft>();
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
|
||||
var speed = .2f * aircraft.MovementSpeedForCell(self, self.Location);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
public IActivity Tick(Actor self)
|
||||
{
|
||||
self.traits.WithInterface<IMove>().FirstOrDefault().SetPosition(self, destination);
|
||||
self.TraitsImplementing<IMove>().FirstOrDefault().SetPosition(self, destination);
|
||||
return NextActivity;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
this.offset = offset;
|
||||
this.sounds = sounds;
|
||||
this.facing = facing;
|
||||
rb = self.traits.GetOrDefault<RenderBuilding>();
|
||||
rb = self.TraitOrDefault<RenderBuilding>();
|
||||
}
|
||||
|
||||
public IActivity NextActivity { get; set; }
|
||||
@@ -59,8 +59,8 @@ namespace OpenRA.Mods.RA.Activities
|
||||
new OwnerInit( self.Owner ),
|
||||
new FacingInit( facing ),
|
||||
};
|
||||
if (self.traits.Contains<Health>())
|
||||
init.Add( new HealthInit( self.traits.Get<Health>().HPFraction ));
|
||||
if (self.HasTrait<Health>())
|
||||
init.Add( new HealthInit( self.Trait<Health>().HPFraction ));
|
||||
|
||||
var a = w.CreateActor( actor, init );
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ namespace OpenRA.Mods.RA.Activities
|
||||
int2? ChooseExitTile(Actor self, Actor cargo)
|
||||
{
|
||||
// is anyone still hogging this tile?
|
||||
if (self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(self.Location).Count() > 1)
|
||||
if (self.World.WorldActor.Trait<UnitInfluence>().GetUnitsAt(self.Location).Count() > 1)
|
||||
return null;
|
||||
|
||||
var mobile = cargo.traits.Get<Mobile>();
|
||||
var mobile = cargo.Trait<Mobile>();
|
||||
|
||||
for (var i = -1; i < 2; i++)
|
||||
for (var j = -1; j < 2; j++)
|
||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
|
||||
// if we're a thing that can turn, turn to the
|
||||
// right facing for the unload animation
|
||||
var facing = self.traits.GetOrDefault<IFacing>();
|
||||
var facing = self.TraitOrDefault<IFacing>();
|
||||
var unloadFacing = self.Info.Traits.Get<CargoInfo>().UnloadFacing;
|
||||
if (facing != null && facing.Facing != unloadFacing)
|
||||
return new Turn(unloadFacing) { NextActivity = this };
|
||||
@@ -52,11 +52,11 @@ namespace OpenRA.Mods.RA.Activities
|
||||
// todo: handle the BS of open/close sequences, which are inconsistent,
|
||||
// for reasons that probably make good sense to the westwood guys.
|
||||
|
||||
var cargo = self.traits.Get<Cargo>();
|
||||
var cargo = self.Trait<Cargo>();
|
||||
if (cargo.IsEmpty(self))
|
||||
return NextActivity;
|
||||
|
||||
var ru = self.traits.GetOrDefault<RenderUnit>();
|
||||
var ru = self.TraitOrDefault<RenderUnit>();
|
||||
if (ru != null)
|
||||
ru.PlayCustomAnimation(self, "unload", null);
|
||||
|
||||
@@ -69,12 +69,12 @@ namespace OpenRA.Mods.RA.Activities
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
w.Add(actor);
|
||||
actor.traits.WithInterface<IMove>().FirstOrDefault().SetPosition(actor, self.Location);
|
||||
actor.TraitsImplementing<IMove>().FirstOrDefault().SetPosition(actor, self.Location);
|
||||
actor.CancelActivity();
|
||||
actor.QueueActivity(new Move(exitTile.Value, 0));
|
||||
if (actor.Owner == self.World.LocalPlayer)
|
||||
{
|
||||
var line = actor.traits.GetOrDefault<DrawLineToTarget>();
|
||||
var line = actor.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTargetSilently(self, Target.FromCell(exitTile.Value), Color.Green);
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public float MovementSpeedForCell(Actor self, int2 cell)
|
||||
{
|
||||
var modifier = self.traits
|
||||
.WithInterface<ISpeedModifier>()
|
||||
var modifier = self
|
||||
.TraitsImplementing<ISpeedModifier>()
|
||||
.Select(t => t.GetSpeedModifier())
|
||||
.Product();
|
||||
return Info.Speed * modifier;
|
||||
|
||||
@@ -23,13 +23,13 @@ namespace OpenRA.Mods.RA
|
||||
public IEnumerable<int2> RadarSignatureCells(Actor self)
|
||||
{
|
||||
if (Space == null)
|
||||
Space = self.traits.Get<IOccupySpace>();
|
||||
Space = self.Trait<IOccupySpace>();
|
||||
return Space.OccupiedCells();
|
||||
}
|
||||
|
||||
public Color RadarSignatureColor(Actor self)
|
||||
{
|
||||
var mod = self.traits.WithInterface<IRadarColorModifier>().FirstOrDefault();
|
||||
var mod = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault();
|
||||
if (mod != null)
|
||||
return mod.RadarColorOverride(self);
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (!target.IsValid) return false;
|
||||
if (Weapons.All(w => w.IsReloading)) return false;
|
||||
if (self.traits.WithInterface<IDisable>().Any(d => d.Disabled)) return false;
|
||||
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -102,8 +102,8 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if( !CanAttack( self ) ) return;
|
||||
|
||||
var move = self.traits.GetOrDefault<IMove>();
|
||||
var facing = self.traits.GetOrDefault<IFacing>();
|
||||
var move = self.TraitOrDefault<IMove>();
|
||||
var facing = self.TraitOrDefault<IFacing>();
|
||||
foreach (var w in Weapons)
|
||||
if (CheckFire(self, move, facing, w))
|
||||
w.FiredShot();
|
||||
@@ -113,7 +113,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (w.FireDelay > 0) return false;
|
||||
|
||||
var limitedAmmo = self.traits.GetOrDefault<LimitedAmmo>();
|
||||
var limitedAmmo = self.TraitOrDefault<LimitedAmmo>();
|
||||
if (limitedAmmo != null && !limitedAmmo.HasAmmo())
|
||||
return false;
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace OpenRA.Mods.RA
|
||||
if (!w.IsValidAgainst(target)) return false;
|
||||
|
||||
var barrel = w.Barrels[w.Burst % w.Barrels.Length];
|
||||
var destMove = target.IsActor ? target.Actor.traits.GetOrDefault<IMove>() : null;
|
||||
var destMove = target.IsActor ? target.Actor.TraitOrDefault<IMove>() : null;
|
||||
|
||||
var args = new ProjectileArgs
|
||||
{
|
||||
@@ -140,7 +140,7 @@ namespace OpenRA.Mods.RA
|
||||
destAltitude = destMove != null ? destMove.Altitude : 0,
|
||||
|
||||
facing = barrel.Facing +
|
||||
(self.traits.Contains<Turreted>() ? self.traits.Get<Turreted>().turretFacing :
|
||||
(self.HasTrait<Turreted>() ? self.Trait<Turreted>().turretFacing :
|
||||
facing != null ? facing.Facing : Util.GetFacing(target.CenterLocation - self.CenterLocation, 0)),
|
||||
};
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var na in self.traits.WithInterface<INotifyAttack>())
|
||||
foreach (var na in self.TraitsImplementing<INotifyAttack>())
|
||||
na.Attacking(self);
|
||||
|
||||
return true;
|
||||
@@ -219,7 +219,7 @@ namespace OpenRA.Mods.RA
|
||||
if (order.TargetActor != null)
|
||||
w.Add(new FlashTarget(order.TargetActor));
|
||||
|
||||
var line = self.traits.GetOrDefault<DrawLineToTarget>();
|
||||
var line = self.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
if (order.TargetActor != null) line.SetTarget(self, Target.FromOrder(order), Color.Red);
|
||||
else line.SetTarget(self, Target.FromOrder(order), Color.Red);
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
if (!target.IsValid) return;
|
||||
|
||||
var facing = self.traits.Get<IFacing>().Facing;
|
||||
var facing = self.Trait<IFacing>().Facing;
|
||||
var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, facing);
|
||||
|
||||
if (Math.Abs(facingToTarget - facing) % 256 < FacingTolerance)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user