Compare commits
86 Commits
playtest-2
...
playtest-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
708cdcd855 | ||
|
|
0236da0a28 | ||
|
|
18e1de1d4b | ||
|
|
73a34886ec | ||
|
|
2d480c900f | ||
|
|
0cf022c87a | ||
|
|
dea199400d | ||
|
|
8e079c310a | ||
|
|
a5af4e85ce | ||
|
|
08158a6929 | ||
|
|
6ba6940aad | ||
|
|
72e0b58912 | ||
|
|
0d2a692d8d | ||
|
|
e043f38c00 | ||
|
|
53f4337129 | ||
|
|
eb69b697b1 | ||
|
|
7d6d488176 | ||
|
|
c568759e49 | ||
|
|
d05b979e53 | ||
|
|
86e8c3974f | ||
|
|
6d1defc53e | ||
|
|
ffac0221cf | ||
|
|
a3994df925 | ||
|
|
caa52b2780 | ||
|
|
149324ea92 | ||
|
|
eba7641125 | ||
|
|
da36ce19e2 | ||
|
|
7e25947689 | ||
|
|
4eaa7d5cf2 | ||
|
|
ff44e34d89 | ||
|
|
8bef8d5a72 | ||
|
|
048386e6fa | ||
|
|
f3dfc422ab | ||
|
|
3b89110202 | ||
|
|
73d27c822e | ||
|
|
a21deea60b | ||
|
|
981e57bde8 | ||
|
|
c313920c7c | ||
|
|
cf9e81ea29 | ||
|
|
4f79aca484 | ||
|
|
5ad196acc3 | ||
|
|
e66ebef73c | ||
|
|
c00d20e3c0 | ||
|
|
795101aac9 | ||
|
|
0dd9a437b8 | ||
|
|
febd92341f | ||
|
|
1368bc0731 | ||
|
|
f4e4f987be | ||
|
|
cf8cfdc42d | ||
|
|
26f1452930 | ||
|
|
544befb553 | ||
|
|
b5efc97996 | ||
|
|
22aa1308ce | ||
|
|
900e55900a | ||
|
|
116ef15fdb | ||
|
|
3c41efea04 | ||
|
|
c7d25bb991 | ||
|
|
a33cca57ec | ||
|
|
16eefe6280 | ||
|
|
c9be0f44f4 | ||
|
|
911ecb2ffa | ||
|
|
56a8653bc6 | ||
|
|
f58e9a2a99 | ||
|
|
2eec1b2016 | ||
|
|
d1dd3a64f8 | ||
|
|
82dea40261 | ||
|
|
606873a09e | ||
|
|
fe90cbdab8 | ||
|
|
8a14662bc1 | ||
|
|
cf6a1583c6 | ||
|
|
c3728ce674 | ||
|
|
1e3f365cf2 | ||
|
|
f4494d67b2 | ||
|
|
0cfbeab864 | ||
|
|
0084566478 | ||
|
|
631630fbff | ||
|
|
19b2e3e521 | ||
|
|
ed0ae15d49 | ||
|
|
fbc7200472 | ||
|
|
0770524c05 | ||
|
|
6d36272134 | ||
|
|
e9a1c3f477 | ||
|
|
16cb275a5f | ||
|
|
682cfcd466 | ||
|
|
14a2b68b7d | ||
|
|
7cf07f5765 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -50,3 +50,8 @@ OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.perspectivev3
|
||||
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.mode1v3
|
||||
*.config
|
||||
*.resources
|
||||
|
||||
# other crap
|
||||
Logs/
|
||||
Replays/
|
||||
settings.yaml
|
||||
|
||||
98
CHANGELOG
98
CHANGELOG
@@ -1,3 +1,100 @@
|
||||
Changes as of playtest-20110318
|
||||
Engine:
|
||||
Display range circles when placing defenses
|
||||
Support a hostile creeps player for viceroids / dinosaurs / ants / etc
|
||||
General refactoring and performance fixes
|
||||
Stop/Scatter/Deploy orders give audio feedback
|
||||
"Allow cheats" option moved into the game lobby, visible to all players
|
||||
"Build anywhere" developer mode option
|
||||
Improved pathfinding when collecting crates or crushing walls.
|
||||
Refactor idle / prone infantry animations
|
||||
Improve missile trail effects
|
||||
Actors without health are not considered as dead
|
||||
Health bars show recent damage as it is inflicted
|
||||
Production structures and special powers show selection bars showing progress
|
||||
Mouseover units to display healthbars etc
|
||||
Fix shroud glitch when units exit transports
|
||||
Fix bots jamming up their production structures
|
||||
Direct connect will assume port 1234 if none is given
|
||||
Chrome image mapping definitions changed from xml to yaml
|
||||
Water explosion animations are not used for airborne explosions over water
|
||||
Fix rendering of very large maps
|
||||
Report GPU memory usage to debug.log
|
||||
Massive improvements in repeated allocation / deallocation of memory
|
||||
Fixed a desync with repairing buildings
|
||||
Fixed a desync with aircraft (it now crashes deterministically instead)
|
||||
Fixed a desync with KOTH maps
|
||||
Fixed a bug where a slot is shown as closed when it contains a bot
|
||||
Fix crash when spawning map actors owned by a nonexisting player
|
||||
Fix crash when changing mod while playing music
|
||||
Fix crash with perf graph
|
||||
Fix crash in replay viewer if replays directory doesn't exist
|
||||
Fix crash when selling civilian buildings
|
||||
Fix crashes caused by blank game title / direct connect server textfields
|
||||
Oil derricks and harvester unloading shows cash indicator
|
||||
Prerequisites system refactoring to allow non-building prerequisites
|
||||
Fix shift+tab not cycling the build tabs
|
||||
Fix bogus keyboard input in text fields
|
||||
Don't change mods if the same one is selected in the dropdown
|
||||
|
||||
C&C:
|
||||
Viceroids! Infantry killed by tiberium or chem warriors may turn into viceroids
|
||||
Fixed death animations
|
||||
Blue tiberium damages infantry
|
||||
Map-placed SAM sites start closed
|
||||
Engineers capturing enemy buildings gives enemy tech
|
||||
Buildings emit minigunners and engineers when sold (no more technicians / civilians)
|
||||
Civilians panic when attacked
|
||||
Fix a rare crash with harvester docking
|
||||
Fix a rare crash with stealth tank
|
||||
New Map: East vs West 3 by pchote
|
||||
Removed Maps: Wargames, Yellowstone II
|
||||
|
||||
RA:
|
||||
Service depots repair units faster
|
||||
Fix crash when telling a minelayer to create an empty minefield
|
||||
Fixed interior tileset boxes
|
||||
New Map: Styrian Mountains by ReFlex
|
||||
New Map: Convergence by Arcturus
|
||||
Updated Map: Seaside by nudalz
|
||||
Longbow ammo increased from 6 to 8, description fixed
|
||||
Hind cost decreased from 1500 to 1000, hp increased from 100 to 150, range decreased from 12 to 10
|
||||
Service depot cost increased to from 700 to 1000
|
||||
Radar dome cost increased from 1000 to 1400
|
||||
Artillery now requires war factor and radar dome, inaccuracy decreased from 80 to 40
|
||||
APC moved from Allies to Soviets, hp increased from 200 to 300, price increased from 800 to 850
|
||||
Medium / Heavy / Mammoth tanks now require service depot to build
|
||||
Heavy tank cost reduced from 1200 to 1150
|
||||
Flame turret rate of fire increased from 45 to 65, fires 2 bursts
|
||||
AA guns, flak trucks can now fire over walls
|
||||
Jeeps can carry a single passenger
|
||||
Base defenses no longer provide ground control
|
||||
Vehicle speed on clear ground increased, speed on ore reduced
|
||||
Grenadiers have a 50% chance of exploding when killed
|
||||
Spys are ignored by enemy units when disguised, tooltips show as disguised unit
|
||||
Fix crates being paradropped inside trees, buildings
|
||||
Production hotkey for flame turret changed to t, tesla coil to u
|
||||
Disguised spys now appear correctly on radar and tooltips
|
||||
Fix GPS behavior when alliances change.
|
||||
|
||||
Editor:
|
||||
New map format (version 5). Maps < Version 4 are no longer supported by the editor or game.
|
||||
Waypoints and MP start locations are now actors
|
||||
Importing C&C/RA maps fixed
|
||||
New png loader to support future tools
|
||||
Editor uses the correct icon under mono
|
||||
Editor only saves non-default values for PlayerReferences in map files
|
||||
Default player colours has been returned to neutral grey.
|
||||
Maps can be loaded from the commandline
|
||||
Option to show actor names
|
||||
Support for veteran / elite actors to be defined in the map yaml
|
||||
|
||||
Packaging:
|
||||
Rename .deb package to use debian naming conventions
|
||||
Improve linux package installation / elevation prompts (uses zenity, require mono >= 2.6.7)
|
||||
Fix package installation crash on windows xp
|
||||
Windowed mode now launches in the center of the screen under Windows
|
||||
|
||||
20110207
|
||||
Engine:
|
||||
Informative drop messages - user is notified of kick vs game has started vs server unavailable
|
||||
@@ -43,7 +140,6 @@
|
||||
Fixed paradrop flare, spyplane from capturing KOTH points
|
||||
New Map: Nuclear Winter (nudalz)
|
||||
New Map: Seaside (nudalz)
|
||||
|
||||
Editor:
|
||||
Ability to switch mods after launch
|
||||
Refactor hardcoded tools into a generic interface
|
||||
|
||||
0
FreeSans.ttf
Executable file → Normal file
0
FreeSans.ttf
Executable file → Normal file
6
Makefile
6
Makefile
@@ -5,9 +5,9 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll third
|
||||
PHONY = core tools package all mods clean distclean
|
||||
|
||||
.SUFFIXES:
|
||||
core: game renderers mod_ra mod_cnc
|
||||
tools: editor ralint seqed filex tsbuild utility
|
||||
package: fixheader core editor utility
|
||||
core: game renderers mod_ra mod_cnc utility
|
||||
tools: editor ralint seqed filex tsbuild
|
||||
package: fixheader core editor
|
||||
mods: mod_ra mod_cnc
|
||||
all: core tools
|
||||
clean:
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Editor
|
||||
@@ -46,11 +46,11 @@ namespace OpenRA.Editor
|
||||
foreach (var path in ModData.FindMapsIn(MapFolderPath))
|
||||
{
|
||||
var map = new Map(path);
|
||||
// Touch the lazy bits to initialize them
|
||||
var foo = map.Actors.Value.Count;
|
||||
foo = map.Smudges.Value.Count;
|
||||
var bar = map.MapResources.Value[0,0];
|
||||
var baz = map.MapTiles.Value[0,0];
|
||||
// Touch the lazy bits to initialize them
|
||||
map.Actors.Force();
|
||||
map.Smudges.Force();
|
||||
map.MapTiles.Force();
|
||||
map.MapResources.Force();
|
||||
map.Save(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,49 @@ namespace OpenRA
|
||||
public static bool Contains(this RectangleF r, int2 p)
|
||||
{
|
||||
return r.Contains(p.ToPointF());
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
||||
{
|
||||
return (k & mod) == mod;
|
||||
}
|
||||
|
||||
public static bool IsValidInput(this KeyInput key)
|
||||
{
|
||||
return char.IsLetter(key.UnicodeChar) || char.IsDigit(key.UnicodeChar) ||
|
||||
char.IsSymbol(key.UnicodeChar) || char.IsSeparator(key.UnicodeChar) ||
|
||||
char.IsPunctuation(key.UnicodeChar);
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd(k, _ => new V());
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
|
||||
{
|
||||
V ret;
|
||||
if (!d.TryGetValue(k, out ret))
|
||||
d.Add(k, ret = createFn(k));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static T Random<T>(this IEnumerable<T> ts, Thirdparty.Random r)
|
||||
{
|
||||
var xs = ts.ToArray();
|
||||
return xs[r.Next(xs.Length)];
|
||||
}
|
||||
|
||||
public static float Product(this IEnumerable<float> xs)
|
||||
{
|
||||
return xs.Aggregate(1f, (a, x) => a * x);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys)
|
||||
{
|
||||
// this is probably a shockingly-slow way to do this, but it's concise.
|
||||
return xs.Except(ys).Concat(ys.Except(xs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.FileFormats.Graphics
|
||||
public interface IIndexBuffer
|
||||
{
|
||||
void Bind();
|
||||
void SetData( ushort[] indices, int length );
|
||||
void SetData( uint[] indices, int length );
|
||||
}
|
||||
|
||||
public interface IShader
|
||||
|
||||
@@ -57,13 +57,14 @@ namespace OpenRA
|
||||
Shift = 1,
|
||||
Alt = 2,
|
||||
Ctrl = 4,
|
||||
Meta = 8,
|
||||
}
|
||||
|
||||
public enum KeyInputEvent { Down, Up };
|
||||
public struct KeyInput
|
||||
{
|
||||
public KeyInputEvent Event;
|
||||
public char KeyChar;
|
||||
public char UnicodeChar;
|
||||
public string KeyName;
|
||||
public Modifiers Modifiers;
|
||||
public int VirtKey;
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
using System;
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -36,7 +36,12 @@ namespace OpenRA.FileFormats
|
||||
p = null;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Force()
|
||||
{
|
||||
var ignored = Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Lazy
|
||||
|
||||
@@ -45,22 +45,4 @@ namespace OpenRA.Collections
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public class CachedView<T,U> : Set<U>
|
||||
{
|
||||
public CachedView( Set<T> set, Func<T, bool> include, Func<T, U> store )
|
||||
: this( set, include, x => new[] { store( x ) } )
|
||||
{
|
||||
}
|
||||
|
||||
public CachedView( Set<T> set, Func<T,bool> include, Func<T,IEnumerable<U>> store )
|
||||
{
|
||||
foreach( var t in set )
|
||||
if( include( t ) )
|
||||
store( t ).Do( x => Add( x ) );
|
||||
|
||||
set.OnAdd += obj => { if( include( obj ) ) store( obj ).Do( x => Add( x ) ); };
|
||||
set.OnRemove += obj => { if( include( obj ) ) store( obj ).Do( x => Remove( x ) ); };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Cursor
|
||||
{
|
||||
CursorSequence sequence;
|
||||
public Cursor(string cursor)
|
||||
{
|
||||
sequence = CursorProvider.GetCursorSequence(cursor);
|
||||
}
|
||||
|
||||
public void Draw(int frame, float2 pos)
|
||||
{
|
||||
sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, Game.modData.Palette.GetPaletteIndex(sequence.Palette));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Exts
|
||||
{
|
||||
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
||||
{
|
||||
return (k & mod) == mod;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys)
|
||||
{
|
||||
// this is probably a shockingly-slow way to do this, but it's concise.
|
||||
return xs.Except(ys).Concat(ys.Except(xs));
|
||||
}
|
||||
|
||||
public static float Product(this IEnumerable<float> xs)
|
||||
{
|
||||
return xs.Aggregate(1f, (a, x) => a * x);
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd(k, _ => new V());
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
|
||||
{
|
||||
V ret;
|
||||
if (!d.TryGetValue(k, out ret))
|
||||
d.Add(k, ret = createFn(k));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static T Random<T>(this IEnumerable<T> ts, Thirdparty.Random r)
|
||||
{
|
||||
var xs = ts.ToArray();
|
||||
return xs[r.Next(xs.Length)];
|
||||
}
|
||||
|
||||
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
||||
e.Do(x =>
|
||||
{
|
||||
var t = sw.ElapsedTime();
|
||||
a(x);
|
||||
var dt = sw.ElapsedTime() - t;
|
||||
if (dt > time)
|
||||
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,9 +266,11 @@ namespace OpenRA
|
||||
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
|
||||
Console.WriteLine("Loading mods: {0}",string.Join(",",mm));
|
||||
Settings.Game.Mods = mm;
|
||||
Settings.Save();
|
||||
|
||||
Sound.Initialize();
|
||||
Settings.Save();
|
||||
|
||||
Sound.StopMusic();
|
||||
Sound.StopVideo();
|
||||
Sound.Initialize();
|
||||
|
||||
modData = new ModData( mm );
|
||||
modData.LoadInitialAssets();
|
||||
|
||||
@@ -82,6 +82,11 @@ namespace OpenRA.GameRules
|
||||
public int SheetSize = 2048;
|
||||
}
|
||||
|
||||
public class KeyboardSettings
|
||||
{
|
||||
public Modifiers ControlGroupModifier = Modifiers.Ctrl;
|
||||
}
|
||||
|
||||
public class Settings
|
||||
{
|
||||
string SettingsFile;
|
||||
@@ -92,7 +97,7 @@ namespace OpenRA.GameRules
|
||||
public GraphicSettings Graphics = new GraphicSettings();
|
||||
public ServerSettings Server = new ServerSettings();
|
||||
public DebugSettings Debug = new DebugSettings();
|
||||
|
||||
public KeyboardSettings Keyboard = new KeyboardSettings();
|
||||
public Dictionary<string, object> Sections;
|
||||
public Settings(string file, Arguments args)
|
||||
{
|
||||
@@ -104,7 +109,8 @@ namespace OpenRA.GameRules
|
||||
{"Sound", Sound},
|
||||
{"Graphics", Graphics},
|
||||
{"Server", Server},
|
||||
{"Debug", Debug}
|
||||
{"Debug", Debug},
|
||||
{"Keyboard",Keyboard}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -11,45 +11,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class ChromeProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, MappedImage>> collections;
|
||||
struct Collection
|
||||
{
|
||||
public string src;
|
||||
public Dictionary<string, MappedImage> regions;
|
||||
}
|
||||
|
||||
static Dictionary<string, Collection> collections;
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||
|
||||
public static void Initialize(params string[] chromeFiles)
|
||||
{
|
||||
collections = new Dictionary<string, Dictionary<string, MappedImage>>();
|
||||
collections = new Dictionary<string, Collection>();
|
||||
cachedSheets = new Dictionary<string, Sheet>();
|
||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||
|
||||
if (chromeFiles.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (var f in chromeFiles)
|
||||
LoadChromeSource(f);
|
||||
var chrome = chromeFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.Merge);
|
||||
|
||||
foreach (var c in chrome)
|
||||
LoadCollection(c.Key, c.Value);
|
||||
}
|
||||
|
||||
public static void Save(string file)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var kv in collections)
|
||||
root.Add(new MiniYamlNode(kv.Key, SaveCollection(kv.Value)));
|
||||
|
||||
root.WriteToFile(file);
|
||||
}
|
||||
|
||||
static MiniYaml SaveCollection(Collection collection)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
foreach (var kv in collection.regions)
|
||||
root.Add(new MiniYamlNode(kv.Key, kv.Value.Save(collection.src)));
|
||||
|
||||
return new MiniYaml(collection.src, root);
|
||||
}
|
||||
|
||||
static void LoadChromeSource(string filename)
|
||||
static void LoadCollection(string name, MiniYaml yaml)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection"))
|
||||
LoadChromeForCollection(eCollection);
|
||||
}
|
||||
|
||||
static void LoadChromeForCollection(XmlElement eCollection)
|
||||
{
|
||||
string elementName = eCollection.GetAttribute("name");
|
||||
string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null);
|
||||
|
||||
var images = eCollection.SelectNodes("./image").OfType<XmlElement>()
|
||||
.Select(e => new MappedImage(defaultSrc, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
collections.Add(elementName, images);
|
||||
Game.modData.LoadScreen.Display();
|
||||
var collection = new Collection()
|
||||
{
|
||||
src = yaml.Value,
|
||||
regions = yaml.Nodes.ToDictionary(n => n.Key, n => new MappedImage(yaml.Value, n.Value))
|
||||
};
|
||||
|
||||
collections.Add(name, collection);
|
||||
}
|
||||
|
||||
public static Sprite GetImage(string collection, string image)
|
||||
@@ -59,21 +79,21 @@ namespace OpenRA.Graphics
|
||||
return cachedSprites[collection][image];
|
||||
|
||||
MappedImage mi;
|
||||
try { mi = collections[collection][image]; }
|
||||
try { mi = collections[collection].regions[image]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Collection `{0}` does not have an image `{1}`".F(collection, image));
|
||||
}
|
||||
|
||||
|
||||
// Cached sheet
|
||||
Sheet sheet;
|
||||
if (cachedSheets.ContainsKey(mi.Src))
|
||||
sheet = cachedSheets[mi.Src];
|
||||
if (cachedSheets.ContainsKey(mi.src))
|
||||
sheet = cachedSheets[mi.src];
|
||||
else
|
||||
{
|
||||
sheet = new Sheet(mi.Src);
|
||||
cachedSheets.Add(mi.Src, sheet);
|
||||
sheet = new Sheet(mi.src);
|
||||
cachedSheets.Add(mi.src, sheet);
|
||||
}
|
||||
|
||||
// Cache the sprite
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class HardwarePalette
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
public const int MaxPalettes = 256;
|
||||
int allocated = 0;
|
||||
|
||||
ITexture texture;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
|
||||
Renderer renderer;
|
||||
|
||||
Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ];
|
||||
ushort[] indices = new ushort[ Renderer.TempBufferSize ];
|
||||
uint[] indices = new uint[ Renderer.TempBufferSize ];
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public LineRenderer( Renderer renderer )
|
||||
|
||||
@@ -11,31 +11,36 @@
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class MappedImage
|
||||
{
|
||||
readonly Rectangle rect;
|
||||
public readonly string Src;
|
||||
public readonly string Name;
|
||||
public readonly Rectangle rect = Rectangle.Empty;
|
||||
public readonly string src;
|
||||
|
||||
public MappedImage(string defaultSrc, XmlElement e)
|
||||
public MappedImage(string defaultSrc, MiniYaml info)
|
||||
{
|
||||
Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc;
|
||||
Name = e.GetAttribute("name");
|
||||
if (Src == null)
|
||||
throw new InvalidDataException("Image src missing");
|
||||
|
||||
rect = new Rectangle(int.Parse(e.GetAttribute("x")),
|
||||
int.Parse(e.GetAttribute("y")),
|
||||
int.Parse(e.GetAttribute("width")),
|
||||
int.Parse(e.GetAttribute("height")));
|
||||
FieldLoader.LoadField(this, "rect", info.Value);
|
||||
FieldLoader.Load(this, info);
|
||||
if (src == null)
|
||||
src = defaultSrc;
|
||||
}
|
||||
|
||||
public Sprite GetImage(Sheet s)
|
||||
{
|
||||
return new Sprite(s, rect, TextureChannel.Alpha);
|
||||
}
|
||||
|
||||
public MiniYaml Save(string defaultSrc)
|
||||
{
|
||||
var root = new List<MiniYamlNode>();
|
||||
if (defaultSrc != src)
|
||||
root.Add(new MiniYamlNode("src", src));
|
||||
|
||||
return new MiniYaml(FieldSaver.FormatValue( this, this.GetType().GetField("rect") ), root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var t in world.Queries.WithTrait<IRadarSignature>())
|
||||
foreach (var t in world.ActorsWithTrait<IRadarSignature>())
|
||||
{
|
||||
if (!world.LocalShroud.IsVisible(t.Actor))
|
||||
continue;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public ITexture PaletteTexture;
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont, TinyFont;
|
||||
public readonly SpriteFont RegularFont, BoldFont, TitleFont, TinyFont, TinyBoldFont;
|
||||
|
||||
internal const int TempBufferSize = 8192;
|
||||
const int TempBufferCount = 8;
|
||||
@@ -59,7 +59,8 @@ namespace OpenRA.Graphics
|
||||
BoldFont = new SpriteFont("FreeSansBold.ttf", 14);
|
||||
TitleFont = new SpriteFont("titles.ttf", 48);
|
||||
TinyFont = new SpriteFont("FreeSans.ttf", 10);
|
||||
|
||||
TinyBoldFont = new SpriteFont("FreeSansBold.ttf", 10);
|
||||
|
||||
for( int i = 0 ; i < TempBufferCount ; i++ )
|
||||
{
|
||||
tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
|
||||
IShader shader;
|
||||
|
||||
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
|
||||
ushort[] indices = new ushort[Renderer.TempBufferSize];
|
||||
uint[] indices = new uint[Renderer.TempBufferSize];
|
||||
Sheet currentSheet = null;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Graphics
|
||||
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
|
||||
ushort[] indices = new ushort[6 * map.Bounds.Height * map.Bounds.Width];
|
||||
uint[] indices = new uint[6 * map.Bounds.Height * map.Bounds.Width];
|
||||
|
||||
terrainSheet = tileMapping[map.MapTiles.Value[map.Bounds.Left, map.Bounds.Top]].sheet;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||
|
||||
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||
public static void FastCreateQuad(Vertex[] vertices, uint[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||
{
|
||||
var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);
|
||||
|
||||
@@ -55,12 +55,12 @@ namespace OpenRA.Graphics
|
||||
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(2), attrib);
|
||||
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(3), attrib);
|
||||
|
||||
indices[ni] = (ushort)(nv);
|
||||
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||
indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2);
|
||||
indices[ni + 4] = (ushort)(nv + 3);
|
||||
r.FastMapTextureCoords(3), attrib);
|
||||
|
||||
indices[ni] = (uint)(nv);
|
||||
indices[ni + 1] = indices[ni + 3] = (uint)(nv + 1);
|
||||
indices[ni + 2] = indices[ni + 5] = (uint)(nv + 2);
|
||||
indices[ni + 4] = (uint)(nv + 3);
|
||||
}
|
||||
|
||||
static readonly int[] channelMasks = { 2, 1, 0, 3 }; // yes, our channel order is nuts.
|
||||
|
||||
@@ -86,8 +86,12 @@ namespace OpenRA.Graphics
|
||||
wr.Draw();
|
||||
|
||||
Widget.DoDraw();
|
||||
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
new Cursor(cursorName).Draw((int)cursorFrame, Viewport.LastMousePos + Location);
|
||||
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
var cursorSequence = CursorProvider.GetCursorSequence(cursorName);
|
||||
|
||||
cursorSequence.GetSprite((int)cursorFrame).DrawAt(
|
||||
Viewport.LastMousePos + Location - cursorSequence.Hotspot,
|
||||
Game.modData.Palette.GetPaletteIndex(cursorSequence.Palette));
|
||||
|
||||
renderer.EndFrame( inputHandler );
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ namespace OpenRA.Graphics
|
||||
|
||||
foreach (var image in SpritesToRender() )
|
||||
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
|
||||
uiOverlay.Draw(this, world);
|
||||
|
||||
// added for contrails
|
||||
foreach (var a in world.Actors)
|
||||
|
||||
@@ -34,12 +34,17 @@ namespace OpenRA.Network
|
||||
frameData.Add( clientId, orders );
|
||||
}
|
||||
|
||||
public bool IsReadyForFrame( int frame )
|
||||
{
|
||||
var frameData = framePackets.GetOrAdd( frame );
|
||||
return ClientsPlayingInFrame( frame )
|
||||
.All( client => frameData.ContainsKey( client ) );
|
||||
}
|
||||
public bool IsReadyForFrame(int frame)
|
||||
{
|
||||
return !ClientsNotReadyForFrame(frame).Any();
|
||||
}
|
||||
|
||||
public IEnumerable<int> ClientsNotReadyForFrame(int frame)
|
||||
{
|
||||
var frameData = framePackets.GetOrAdd(frame);
|
||||
return ClientsPlayingInFrame(frame)
|
||||
.Where(client => !frameData.ContainsKey(client));
|
||||
}
|
||||
|
||||
public IEnumerable<ClientOrder> OrdersForFrame( World world, int frame )
|
||||
{
|
||||
|
||||
@@ -155,7 +155,19 @@ namespace OpenRA.Network
|
||||
public bool IsReadyForNextFrame
|
||||
{
|
||||
get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame( NetFrameNumber ); }
|
||||
}
|
||||
}
|
||||
|
||||
static readonly IEnumerable<Session.Client> NoClients = new Session.Client[] {};
|
||||
public IEnumerable<Session.Client> GetClientsNotReadyForNextFrame
|
||||
{
|
||||
get
|
||||
{
|
||||
return NetFrameNumber >= 1
|
||||
? frameData.ClientsNotReadyForFrame(NetFrameNumber)
|
||||
.Select(a => LobbyInfo.ClientWithIndex(a))
|
||||
: NoClients;
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Network
|
||||
report.Frame = orderManager.NetFrameNumber;
|
||||
report.SyncedRandom = orderManager.world.SharedRandom.Last;
|
||||
report.Traits.Clear();
|
||||
foreach (var a in orderManager.world.Queries.WithTrait<ISync>())
|
||||
foreach (var a in orderManager.world.ActorsWithTrait<ISync>())
|
||||
{
|
||||
var sync = Sync.CalculateSyncHash(a.Trait);
|
||||
if (sync != 0)
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace OpenRA.Network
|
||||
if (target == w.LocalPlayer)
|
||||
w.WorldActor.Trait<Shroud>().UpdatePlayerStance(w, p, oldStance, s);
|
||||
|
||||
foreach (var nsc in w.Queries.WithTrait<INotifyStanceChanged>())
|
||||
foreach (var nsc in w.ActorsWithTrait<INotifyStanceChanged>())
|
||||
nsc.Trait.StanceChanged(nsc.Actor, p, target, oldStance, s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -87,7 +87,6 @@
|
||||
<Compile Include="Widgets\WidgetUtils.cs" />
|
||||
<Compile Include="Effects\DelayedAction.cs" />
|
||||
<Compile Include="Effects\FlashTarget.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="GameRules\ActorInfo.cs" />
|
||||
<Compile Include="GameRules\VoiceInfo.cs" />
|
||||
<Compile Include="Effects\IEffect.cs" />
|
||||
@@ -110,7 +109,6 @@
|
||||
<Compile Include="Traits\World\SpatialBins.cs" />
|
||||
<Compile Include="Traits\World\Country.cs" />
|
||||
<Compile Include="Actor.cs" />
|
||||
<Compile Include="Cursor.cs" />
|
||||
<Compile Include="GameRules\Rules.cs" />
|
||||
<Compile Include="Graphics\Animation.cs" />
|
||||
<Compile Include="Game.cs" />
|
||||
|
||||
@@ -83,9 +83,8 @@ namespace OpenRA.Orders
|
||||
|
||||
public override void Tick(World world)
|
||||
{
|
||||
var hasStructure = world.Queries.OwnedBy[world.LocalPlayer]
|
||||
.WithTrait<T>()
|
||||
.Any();
|
||||
var hasStructure = world.ActorsWithTrait<T>()
|
||||
.Any( a => a.Actor.Owner == world.LocalPlayer );
|
||||
|
||||
if (!hasStructure)
|
||||
world.CancelInputMode();
|
||||
|
||||
@@ -42,43 +42,36 @@ namespace OpenRA
|
||||
public Shroud Shroud { get { return World.LocalShroud; }}
|
||||
public World World { get; private set; }
|
||||
|
||||
public Player(World world, PlayerReference pr, int index)
|
||||
{
|
||||
World = world;
|
||||
|
||||
Index = index;
|
||||
Palette = "player" + index;
|
||||
|
||||
ColorRamp = pr.ColorRamp;
|
||||
ClientIndex = 0; /* it's a map player, "owned" by host */
|
||||
|
||||
PlayerName = InternalName = pr.Name;
|
||||
NonCombatant = pr.NonCombatant;
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => pr.Race == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
|
||||
PlayerRef = pr;
|
||||
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) });
|
||||
}
|
||||
|
||||
public Player(World world, Session.Client client, PlayerReference pr, int index)
|
||||
{
|
||||
World = world;
|
||||
Index = index;
|
||||
Palette = "player" + index;
|
||||
ColorRamp = client.ColorRamp;
|
||||
PlayerName = client.Name;
|
||||
|
||||
InternalName = pr.Name;
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => client != null && client.Country == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
|
||||
ClientIndex = client.Index;
|
||||
PlayerRef = pr;
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
ClientIndex = client.Index;
|
||||
ColorRamp = client.ColorRamp;
|
||||
PlayerName = client.Name;
|
||||
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => client.Country == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientIndex = 0; /* it's a map player, "owned" by host */
|
||||
ColorRamp = pr.ColorRamp;
|
||||
PlayerName = pr.Name;
|
||||
NonCombatant = pr.NonCombatant;
|
||||
|
||||
Country = world.GetCountries()
|
||||
.FirstOrDefault(c => pr.Race == c.Race)
|
||||
?? world.GetCountries().Random(world.SharedRandom);
|
||||
}
|
||||
|
||||
PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) });
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace OpenRA
|
||||
|
||||
public void DoControlGroup(World world, int group, Modifiers mods)
|
||||
{
|
||||
if (mods.HasModifier(Modifiers.Ctrl))
|
||||
if (mods.HasModifier(Game.Settings.Keyboard.ControlGroupModifier))
|
||||
{
|
||||
if (actors.Count == 0)
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
@@ -76,7 +77,13 @@ namespace OpenRA.Server
|
||||
public readonly int State = 0;
|
||||
public readonly int Players = 0;
|
||||
public readonly string Map = null;
|
||||
public readonly string[] Mods = { };
|
||||
public readonly string[] Mods = { };
|
||||
public readonly int TTL = 0;
|
||||
|
||||
public Dictionary<string, string> UsefulMods {
|
||||
get {
|
||||
return Mods.Where(v => v.Contains('@')).ToDictionary(v => v.Split('@')[0], v => v.Split('@')[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace OpenRA.Traits
|
||||
public bool DisableShroud = false;
|
||||
public bool PathDebug = false;
|
||||
public bool UnitInfluenceDebug = false;
|
||||
public bool UnlimitedPower;
|
||||
public bool UnlimitedPower;
|
||||
public bool BuildAnywhere;
|
||||
|
||||
public object Create (ActorInitializer init) { return new DeveloperMode(this); }
|
||||
}
|
||||
@@ -34,17 +35,19 @@ namespace OpenRA.Traits
|
||||
[Sync] public bool DisableShroud;
|
||||
[Sync] public bool PathDebug;
|
||||
[Sync] public bool UnitInfluenceDebug;
|
||||
[Sync] public bool UnlimitedPower;
|
||||
[Sync] public bool UnlimitedPower;
|
||||
[Sync] public bool BuildAnywhere;
|
||||
|
||||
public DeveloperMode(DeveloperModeInfo info)
|
||||
{
|
||||
Info = info;
|
||||
FastBuild = Info.FastBuild;
|
||||
FastCharge = Info.FastCharge;
|
||||
DisableShroud = Info.DisableShroud;
|
||||
PathDebug = Info.PathDebug;
|
||||
FastBuild = info.FastBuild;
|
||||
FastCharge = info.FastCharge;
|
||||
DisableShroud = info.DisableShroud;
|
||||
PathDebug = info.PathDebug;
|
||||
UnitInfluenceDebug = info.UnitInfluenceDebug;
|
||||
UnlimitedPower = info.UnlimitedPower;
|
||||
UnlimitedPower = info.UnlimitedPower;
|
||||
BuildAnywhere = info.BuildAnywhere;
|
||||
}
|
||||
|
||||
public void ResolveOrder (Actor self, Order order)
|
||||
@@ -100,7 +103,12 @@ namespace OpenRA.Traits
|
||||
{
|
||||
UnlimitedPower ^= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case "DevBuildAnywhere":
|
||||
{
|
||||
BuildAnywhere ^= true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,8 @@ namespace OpenRA.Traits
|
||||
{
|
||||
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
|
||||
|
||||
OreCapacity = self.World.Queries.OwnedBy[Owner].WithTrait<IStoreOre>()
|
||||
OreCapacity = self.World.ActorsWithTrait<IStoreOre>()
|
||||
.Where(a => a.Actor.Owner == Owner)
|
||||
.Sum(a => a.Trait.Capacity);
|
||||
|
||||
if (Ore > OreCapacity)
|
||||
|
||||
@@ -59,8 +59,6 @@ namespace OpenRA.Traits
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||
|
||||
DrawHealthBar(self, xy, Xy);
|
||||
DrawExtraBars(self, xy, Xy);
|
||||
|
||||
@@ -64,7 +64,13 @@ namespace OpenRA.Traits
|
||||
public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); }
|
||||
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); }
|
||||
public interface IStoreOre { int Capacity { get; }}
|
||||
|
||||
public interface IToolTip
|
||||
{
|
||||
string Name();
|
||||
Player Owner();
|
||||
Stance Stance();
|
||||
}
|
||||
|
||||
public interface IDisable { bool Disabled { get; } }
|
||||
public interface IExplodeModifier { bool ShouldExplode(Actor self); }
|
||||
public interface INudge { void OnNudge(Actor self, Actor nudger); }
|
||||
@@ -229,7 +235,6 @@ namespace OpenRA.Traits
|
||||
bool TargetableBy(Actor self, Actor byActor);
|
||||
}
|
||||
|
||||
public interface INotifyKeyPress { bool KeyPressed(Actor self, KeyInput e); }
|
||||
public interface INotifyStanceChanged { void StanceChanged(Actor self, Player a, Player b,
|
||||
Stance oldStance, Stance newStance); }
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace OpenRA.Traits
|
||||
}
|
||||
// Is now our ally; add unit vis
|
||||
if (newStance == Stance.Ally)
|
||||
foreach (var a in w.Queries.OwnedBy[player])
|
||||
foreach (var a in w.Actors.Where( a => a.Owner == player ))
|
||||
AddActor(a);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Traits
|
||||
for (var i = 0; i <= bins.GetUpperBound(0); i++)
|
||||
bins[i, j].Clear();
|
||||
|
||||
foreach (var a in self.World.Queries.WithTrait<IHasLocation>())
|
||||
foreach (var a in self.World.ActorsWithTrait<IHasLocation>())
|
||||
{
|
||||
var bounds = a.Actor.GetBounds(true);
|
||||
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class UiOverlay
|
||||
@@ -38,20 +36,6 @@ namespace OpenRA
|
||||
return Game.modData.SheetBuilder.Add(data, new Size(Game.CellSize, Game.CellSize));
|
||||
}
|
||||
|
||||
public void Draw( WorldRenderer wr, World world )
|
||||
{
|
||||
if( world.LocalPlayer == null ) return;
|
||||
if (world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().UnitInfluenceDebug)
|
||||
{
|
||||
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++)
|
||||
if (uim.GetUnitsAt(new int2(i, j)).Any())
|
||||
unitDebug.DrawAt(wr, Game.CellSize * new float2(i, j), "terrain");
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawGrid( WorldRenderer wr, Dictionary<int2, bool> cells )
|
||||
{
|
||||
foreach( var c in cells )
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
if (e.Event == KeyInputEvent.Up) return false;
|
||||
|
||||
if (e.KeyChar == '\r')
|
||||
if (e.KeyName == "return" || e.KeyName == "enter" )
|
||||
{
|
||||
if (composing)
|
||||
{
|
||||
@@ -94,15 +94,15 @@ namespace OpenRA.Widgets
|
||||
|
||||
if (composing)
|
||||
{
|
||||
if (e.KeyChar == '\b' || e.KeyChar == 0x7f)
|
||||
if (e.KeyName == "backspace")
|
||||
{
|
||||
if (content.Length > 0)
|
||||
content = content.Remove(content.Length - 1);
|
||||
return true;
|
||||
}
|
||||
else if (!char.IsControl(e.KeyChar))
|
||||
else if (e.IsValidInput())
|
||||
{
|
||||
content += e.KeyChar;
|
||||
content += e.UnicodeChar.ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.Widgets
|
||||
Game.Renderer.LineRenderer.DrawLine(origin + new float2(100, 0) * basis, origin + new float2(100, 100) * basis, Color.White, Color.White);
|
||||
|
||||
int k = 0;
|
||||
foreach (var item in PerfHistory.items.Values)
|
||||
foreach (var item in PerfHistory.items.Values.ToArray())
|
||||
{
|
||||
int n = 0;
|
||||
item.Samples().Aggregate((a, b) =>
|
||||
|
||||
@@ -64,6 +64,9 @@ namespace OpenRA.Widgets
|
||||
|
||||
public int ClosestCursorPosition(int x)
|
||||
{
|
||||
if (Text == null)
|
||||
return 0;
|
||||
|
||||
var font = (Bold) ? Game.Renderer.BoldFont : Game.Renderer.RegularFont;
|
||||
var textSize = font.Measure(Text);
|
||||
|
||||
@@ -92,10 +95,10 @@ namespace OpenRA.Widgets
|
||||
if (!Focused)
|
||||
return false;
|
||||
|
||||
if (e.KeyChar == '\r' && OnEnterKey())
|
||||
if ((e.KeyName == "return" || e.KeyName == "enter") && OnEnterKey())
|
||||
return true;
|
||||
|
||||
if (e.KeyChar == '\t' && OnTabKey())
|
||||
if (e.KeyName == "tab" && OnTabKey())
|
||||
return true;
|
||||
|
||||
if (e.KeyName == "left")
|
||||
@@ -123,28 +126,29 @@ namespace OpenRA.Widgets
|
||||
return true;
|
||||
}
|
||||
|
||||
TypeChar(e.KeyChar);
|
||||
TypeChar(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void TypeChar(char c)
|
||||
public void TypeChar(KeyInput key)
|
||||
{
|
||||
// backspace
|
||||
if (c == '\b' || c == 0x7f)
|
||||
if (Text == null)
|
||||
Text = "";
|
||||
|
||||
if (key.KeyName == "backspace" && Text.Length > 0 && CursorPosition > 0)
|
||||
{
|
||||
if (Text.Length > 0 && CursorPosition > 0)
|
||||
{
|
||||
Text = Text.Remove(CursorPosition - 1, 1);
|
||||
|
||||
CursorPosition--;
|
||||
}
|
||||
Text = Text.Remove(CursorPosition - 1, 1);
|
||||
CursorPosition--;
|
||||
}
|
||||
else if (!char.IsControl(c))
|
||||
{
|
||||
else if (key.KeyName == "delete" && Text.Length > 0 && CursorPosition < Text.Length - 1)
|
||||
Text = Text.Remove(CursorPosition, 1);
|
||||
|
||||
else if (key.IsValidInput())
|
||||
{
|
||||
if (MaxLength > 0 && Text.Length >= MaxLength)
|
||||
return;
|
||||
|
||||
Text = Text.Insert(CursorPosition, c.ToString());
|
||||
Text = Text.Insert(CursorPosition, key.UnicodeChar.ToString());
|
||||
|
||||
CursorPosition++;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
if (e.Event == KeyInputEvent.Down)
|
||||
{
|
||||
if (e.KeyChar == 27) // Escape
|
||||
if (e.KeyName == "escape")
|
||||
{
|
||||
Stop();
|
||||
return true;
|
||||
|
||||
@@ -31,11 +31,14 @@ namespace OpenRA.Widgets
|
||||
|
||||
public override void DrawInner()
|
||||
{
|
||||
foreach( var u in SelectActorsInBox(world, Game.CellSize * dragStart, Game.CellSize * dragStart ))
|
||||
worldRenderer.DrawRollover( u );
|
||||
|
||||
var selbox = SelectionBox;
|
||||
if (selbox == null) return;
|
||||
var selbox = SelectionBox;
|
||||
if (selbox == null)
|
||||
{
|
||||
foreach (var u in SelectActorsInBox(world, Game.CellSize * dragStart, Game.CellSize * dragStart))
|
||||
worldRenderer.DrawRollover(u);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var a = selbox.Value.First;
|
||||
var b = new float2(selbox.Value.Second.X - a.X, 0);
|
||||
@@ -44,10 +47,10 @@ namespace OpenRA.Widgets
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + b, Color.White, Color.White);
|
||||
Game.Renderer.LineRenderer.DrawLine(a + b, a + b + c, Color.White, Color.White);
|
||||
Game.Renderer.LineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second))
|
||||
worldRenderer.DrawSelectionBox(u, Color.Yellow);
|
||||
Game.Renderer.LineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second))
|
||||
worldRenderer.DrawRollover(u);
|
||||
}
|
||||
|
||||
float2 dragStart, dragEnd;
|
||||
@@ -131,14 +134,12 @@ namespace OpenRA.Widgets
|
||||
|
||||
bool handled = false;
|
||||
|
||||
foreach (var t in world.WorldActor.TraitsImplementing<INotifyKeyPress>())
|
||||
handled = (t.KeyPressed(world.WorldActor, e)) ? true : handled;
|
||||
|
||||
if (handled) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static readonly Actor[] NoActors = {};
|
||||
IEnumerable<Actor> SelectActorsInBox(World world, float2 a, float2 b)
|
||||
{
|
||||
return world.FindUnits(a, b)
|
||||
@@ -146,7 +147,7 @@ namespace OpenRA.Widgets
|
||||
.GroupBy(x => (x.Owner == world.LocalPlayer) ? x.Info.Traits.Get<SelectableInfo>().Priority : 0)
|
||||
.OrderByDescending(g => g.Key)
|
||||
.Select( g => g.AsEnumerable() )
|
||||
.DefaultIfEmpty( new Actor[] {} )
|
||||
.DefaultIfEmpty( NoActors )
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ using OpenRA.Effects;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Orders;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
using OpenRA.Traits;
|
||||
using XRandom = OpenRA.Thirdparty.Random;
|
||||
|
||||
namespace OpenRA
|
||||
@@ -101,8 +100,6 @@ namespace OpenRA
|
||||
WorldActor = CreateActor( "World", new TypeDictionary() );
|
||||
LocalShroud = WorldActor.Trait<Shroud>();
|
||||
|
||||
Queries = new AllQueries(this);
|
||||
|
||||
// Add players
|
||||
foreach (var cmp in WorldActor.TraitsImplementing<ICreatePlayers>())
|
||||
cmp.CreatePlayers(this);
|
||||
@@ -161,7 +158,7 @@ namespace OpenRA
|
||||
if (!DisableTick)
|
||||
{
|
||||
actors.Do( x => x.Tick() );
|
||||
Queries.WithTrait<ITick>().DoTimed( x =>
|
||||
ActorsWithTrait<ITick>().DoTimed( x =>
|
||||
{
|
||||
x.Trait.Tick( x.Actor );
|
||||
}, "[{2}] Trait: {0} ({1:0.000} ms)", Game.Settings.Debug.LongTickThreshold );
|
||||
@@ -203,55 +200,12 @@ namespace OpenRA
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public class AllQueries
|
||||
{
|
||||
readonly World world;
|
||||
|
||||
public readonly Cache<Player, OwnedByCachedView> OwnedBy;
|
||||
|
||||
public AllQueries( World world )
|
||||
{
|
||||
this.world = world;
|
||||
OwnedBy = new Cache<Player, OwnedByCachedView>(p => new OwnedByCachedView(world, world.actors, x => x.Owner == p));
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> WithTrait<T>()
|
||||
{
|
||||
return world.traitDict.ActorsWithTraitMultiple<T>( world );
|
||||
}
|
||||
|
||||
static CachedView<Actor, TraitPair<T>> WithTraitInner<T>( Set<Actor> set, TypeDictionary hasTrait )
|
||||
{
|
||||
var ret = hasTrait.GetOrDefault<CachedView<Actor, TraitPair<T>>>();
|
||||
if( ret != null )
|
||||
return ret;
|
||||
ret = new CachedView<Actor, TraitPair<T>>(
|
||||
set,
|
||||
x => x.HasTrait<T>(),
|
||||
x => new TraitPair<T> { Actor = x, Trait = x.Trait<T>() } );
|
||||
hasTrait.Add( ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public class OwnedByCachedView : CachedView<Actor, Actor>
|
||||
{
|
||||
readonly TypeDictionary hasTrait = new TypeDictionary();
|
||||
|
||||
public OwnedByCachedView( World world, Set<Actor> set, Func<Actor, bool> include )
|
||||
: base( set, include, a => a )
|
||||
{
|
||||
}
|
||||
|
||||
public CachedView<Actor, TraitPair<T>> WithTrait<T>()
|
||||
{
|
||||
return WithTraitInner<T>( this, hasTrait );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AllQueries Queries;
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<T>> ActorsWithTrait<T>()
|
||||
{
|
||||
return traitDict.ActorsWithTraitMultiple<T>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public struct TraitPair<T>
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Support;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using System;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -137,6 +137,20 @@ namespace OpenRA
|
||||
o.Subject, o.Subject.Owner.Country.Race))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
|
||||
e.Do(x =>
|
||||
{
|
||||
var t = sw.ElapsedTime();
|
||||
a(x);
|
||||
var dt = sw.ElapsedTime() - t;
|
||||
if (dt > time)
|
||||
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace OpenRA.Mods.Cnc
|
||||
started = true;
|
||||
}));
|
||||
}
|
||||
|
||||
// THIS IS SHIT
|
||||
|
||||
public void OnVictory(World w)
|
||||
{
|
||||
@@ -54,7 +56,8 @@ namespace OpenRA.Mods.Cnc
|
||||
|
||||
w.WorldActor.CancelActivity();
|
||||
w.WorldActor.QueueActivity(new Wait(125));
|
||||
w.WorldActor.QueueActivity(new CallFunc(() => Scripting.Media.PlayFMVFullscreen(w, "consyard.vqa", () =>
|
||||
w.WorldActor.QueueActivity(new CallFunc(
|
||||
() => Scripting.Media.PlayFMVFullscreen(w, "consyard.vqa", () =>
|
||||
{
|
||||
Sound.StopMusic();
|
||||
Game.Disconnect();
|
||||
@@ -69,7 +72,8 @@ namespace OpenRA.Mods.Cnc
|
||||
|
||||
w.WorldActor.CancelActivity();
|
||||
w.WorldActor.QueueActivity(new Wait(125));
|
||||
w.WorldActor.QueueActivity(new CallFunc(() => Scripting.Media.PlayFMVFullscreen(w, "gameover.vqa", () =>
|
||||
w.WorldActor.QueueActivity(new CallFunc(
|
||||
() => Scripting.Media.PlayFMVFullscreen(w, "gameover.vqa", () =>
|
||||
{
|
||||
Sound.StopMusic();
|
||||
Game.Disconnect();
|
||||
@@ -108,8 +112,8 @@ namespace OpenRA.Mods.Cnc
|
||||
});
|
||||
}
|
||||
// GoodGuy win conditions
|
||||
// BadGuy is dead
|
||||
int badcount = self.World.Queries.OwnedBy[Players["BadGuy"]].Count(a => !a.IsDead());
|
||||
// BadGuy is dead
|
||||
var badcount = self.World.Actors.Count(a => a.Owner == Players["BadGuy"] && !a.IsDead());
|
||||
if (badcount != lastBadCount)
|
||||
{
|
||||
Game.Debug("{0} badguys remain".F(badcount));
|
||||
@@ -119,8 +123,9 @@ namespace OpenRA.Mods.Cnc
|
||||
OnVictory(self.World);
|
||||
}
|
||||
|
||||
//GoodGuy lose conditions
|
||||
if (self.World.Queries.OwnedBy[Players["GoodGuy"]].Count( a => !a.IsDead()) == 0)
|
||||
//GoodGuy lose conditions
|
||||
var goodCount = self.World.Actors.Count(a => a.Owner == Players["GoodGuy"] && !a.IsDead());
|
||||
if (goodCount == 0)
|
||||
OnLose(self.World);
|
||||
|
||||
// GoodGuy reinforcements
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities
|
||||
foreach (var t in target.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(target, self, oldOwner, self.Owner);
|
||||
|
||||
foreach (var t in self.World.Queries.WithTrait<INotifyOtherCaptured>())
|
||||
foreach (var t in self.World.ActorsWithTrait<INotifyOtherCaptured>())
|
||||
t.Trait.OnActorCaptured(t.Actor, target, self, oldOwner, self.Owner);
|
||||
|
||||
self.Destroy();
|
||||
|
||||
48
OpenRA.Mods.RA/ActorExts.cs
Normal file
48
OpenRA.Mods.RA/ActorExts.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
public static class ActorExts
|
||||
{
|
||||
static bool IsDisguisedSpy( this Actor a )
|
||||
{
|
||||
return a.HasTrait<Spy>() && a.Trait<Spy>().Disguised;
|
||||
}
|
||||
|
||||
public static bool AppearsFriendlyTo(this Actor self, Actor toActor)
|
||||
{
|
||||
var stance = toActor.Owner.Stances[ self.Owner ];
|
||||
|
||||
if (self.IsDisguisedSpy() && !toActor.HasTrait<IgnoresDisguise>())
|
||||
if ( toActor.Owner.Stances[self.Trait<Spy>().disguisedAsPlayer] == Stance.Ally)
|
||||
return true;
|
||||
|
||||
return stance == Stance.Ally;
|
||||
}
|
||||
|
||||
public static bool AppearsHostileTo(this Actor self, Actor toActor)
|
||||
{
|
||||
var stance = toActor.Owner.Stances[ self.Owner ];
|
||||
if (stance == Stance.Ally)
|
||||
return false; /* otherwise, we'll hate friendly disguised spies */
|
||||
|
||||
if (self.IsDisguisedSpy() && !toActor.HasTrait<IgnoresDisguise>())
|
||||
if (toActor.Owner.Stances[self.Trait<Spy>().disguisedAsPlayer] == Stance.Enemy)
|
||||
return true;
|
||||
|
||||
return stance == Stance.Enemy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,11 +52,11 @@ namespace OpenRA.Mods.RA.Air
|
||||
}
|
||||
}
|
||||
|
||||
public class FlyCircle : CancelableActivity
|
||||
public class FlyAttackLoop : CancelableActivity
|
||||
{
|
||||
int2 Target;
|
||||
|
||||
public FlyCircle(int2 target) { Target = target; }
|
||||
public FlyAttackLoop(int2 target) { Target = target; }
|
||||
|
||||
public override IActivity Tick(Actor self)
|
||||
{
|
||||
|
||||
43
OpenRA.Mods.RA/Air/FlyCircle.cs
Normal file
43
OpenRA.Mods.RA/Air/FlyCircle.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA.Mods.RA.Air
|
||||
{
|
||||
public class FlyCircle : CancelableActivity
|
||||
{
|
||||
public override IActivity Tick(Actor self)
|
||||
{
|
||||
var cruiseAltitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
|
||||
if (IsCanceled) return NextActivity;
|
||||
|
||||
var aircraft = self.Trait<Aircraft>();
|
||||
|
||||
var desiredFacing = aircraft.Facing + 64; // we can't possibly turn this fast.
|
||||
if (aircraft.Altitude == cruiseAltitude)
|
||||
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
|
||||
|
||||
if (aircraft.Altitude < cruiseAltitude)
|
||||
++aircraft.Altitude;
|
||||
|
||||
FlyUtil.Fly(self, cruiseAltitude);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IEnumerable<float2> GetCurrentPath()
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
static Actor ChooseHelipad(Actor self)
|
||||
{
|
||||
var rearmBuildings = self.Info.Traits.Get<HelicopterInfo>().RearmBuildings;
|
||||
return self.World.Queries.OwnedBy[self.Owner].FirstOrDefault(
|
||||
return self.World.Actors.Where( a => a.Owner == self.Owner ).FirstOrDefault(
|
||||
a => rearmBuildings.Contains(a.Info.Name) &&
|
||||
!Reservable.IsReserved(a));
|
||||
}
|
||||
@@ -39,8 +39,9 @@ namespace OpenRA.Mods.RA.Air
|
||||
NextActivity);
|
||||
|
||||
var res = dest.TraitOrDefault<Reservable>();
|
||||
var heli = self.Trait<Helicopter>();
|
||||
if (res != null)
|
||||
self.Trait<Helicopter>().reservation = res.Reserve(dest, self);
|
||||
heli.reservation = res.Reserve(dest, self, heli);
|
||||
|
||||
var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
|
||||
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
if (Reservable.IsReserved(order.TargetActor)) return;
|
||||
var res = order.TargetActor.TraitOrDefault<Reservable>();
|
||||
if (res != null)
|
||||
reservation = res.Reserve(order.TargetActor, self);
|
||||
reservation = res.Reserve(order.TargetActor, self, this);
|
||||
|
||||
var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
|
||||
var offset = exit != null ? exit.SpawnOffset : int2.Zero;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
{
|
||||
var res = afld.Trait<Reservable>();
|
||||
if (res != null)
|
||||
reservation = res.Reserve(afld, self);
|
||||
reservation = res.Reserve(afld, self, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,8 @@ namespace OpenRA.Mods.RA.Air
|
||||
var target = order.TargetLocation.Clamp(self.World.Map.Bounds);
|
||||
self.SetTargetLine(Target.FromCell(target), Color.Green);
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(Fly.ToCell(target));
|
||||
self.QueueActivity(Fly.ToCell(target));
|
||||
self.QueueActivity(new FlyCircle());
|
||||
}
|
||||
|
||||
else if (order.OrderString == "Enter")
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA.Mods.RA.Air
|
||||
{
|
||||
@@ -32,10 +33,30 @@ namespace OpenRA.Mods.RA.Air
|
||||
self.QueueActivity(new Rearm());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Game.Debug("Plane has nowhere to land; flying away");
|
||||
self.QueueActivity(new FlyOffMap());
|
||||
self.QueueActivity(new RemoveSelf());
|
||||
{
|
||||
// nowhere to land, pick something friendly and circle over it.
|
||||
|
||||
// i'd prefer something we own
|
||||
var someBuilding = self.World.ActorsWithTrait<Building>()
|
||||
.Select( a => a.Actor )
|
||||
.FirstOrDefault(a => a.Owner == self.Owner);
|
||||
|
||||
// failing that, something unlikely to shoot at us
|
||||
if (someBuilding == null)
|
||||
someBuilding = self.World.ActorsWithTrait<Building>()
|
||||
.Select( a => a.Actor )
|
||||
.FirstOrDefault(a => self.Owner.Stances[a.Owner] == Stance.Ally);
|
||||
|
||||
if (someBuilding == null)
|
||||
{
|
||||
// ... going down the garden to eat worms ...
|
||||
self.QueueActivity(new FlyOffMap());
|
||||
self.QueueActivity(new RemoveSelf());
|
||||
return;
|
||||
}
|
||||
|
||||
self.QueueActivity(Fly.ToCell(someBuilding.Location));
|
||||
self.QueueActivity(new FlyCircle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
using OpenRA.Traits.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
|
||||
namespace OpenRA.Mods.RA.Air
|
||||
{
|
||||
@@ -23,12 +24,14 @@ namespace OpenRA.Mods.RA.Air
|
||||
int2 w1, w2, w3; /* tangent points to turn circles */
|
||||
|
||||
public static Actor ChooseAirfield(Actor self)
|
||||
{
|
||||
return self.World.Queries.OwnedBy[self.Owner]
|
||||
.Where(a => self.Info.Traits.Get<PlaneInfo>().RearmBuildings.Contains(a.Info.Name)
|
||||
&& !Reservable.IsReserved(a))
|
||||
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
|
||||
.FirstOrDefault();
|
||||
{
|
||||
return self.World.ActorsWithTrait<Reservable>()
|
||||
.Where(a => a.Actor.Owner == self.Owner)
|
||||
.Where(a => self.Info.Traits.Get<PlaneInfo>().RearmBuildings.Contains(a.Actor.Info.Name)
|
||||
&& !Reservable.IsReserved(a.Actor))
|
||||
.OrderBy(a => (a.Actor.CenterLocation - self.CenterLocation).LengthSquared)
|
||||
.Select(a => a.Actor)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
void Calculate(Actor self)
|
||||
@@ -43,7 +46,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
if (res != null)
|
||||
{
|
||||
plane.UnReserve();
|
||||
plane.reservation = res.Reserve(dest, self);
|
||||
plane.reservation = res.Reserve(dest, self, plane);
|
||||
}
|
||||
|
||||
var landPos = dest.CenterLocation;
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace OpenRA.Mods.RA
|
||||
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
|
||||
return inRange
|
||||
.Where(a => a.Owner != null && self.Owner.Stances[a.Owner] == Stance.Enemy)
|
||||
.Where(a => a.Owner != null && a.AppearsHostileTo(self))
|
||||
.Where(a => !a.HasTrait<AutoTargetIgnore>())
|
||||
.Where(a => HasAnyValidWeapons(Target.FromActor(a)))
|
||||
.OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA
|
||||
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * attack.GetMaximumRange());
|
||||
|
||||
var target = inRange
|
||||
.Where(a => a != self && self.Owner.Stances[a.Owner] == Stance.Ally)
|
||||
.Where(a => a != self && a.AppearsFriendlyTo(self))
|
||||
.Where(a => a.IsInWorld && !a.IsDead())
|
||||
.Where(a => a.HasTrait<Health>() && a.GetDamageState() > DamageState.Undamaged)
|
||||
.Where(a => attack.HasAnyValidWeapons(Target.FromActor(a)))
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA
|
||||
if (!attack.HasAnyValidWeapons(Target.FromActor(e.Attacker))) return;
|
||||
|
||||
// don't retaliate against own units force-firing on us. it's usually not what the player wanted.
|
||||
if (self.Owner.Stances[e.Attacker.Owner] == Stance.Ally) return;
|
||||
if (e.Attacker.AppearsFriendlyTo(self)) return;
|
||||
|
||||
if (e.Damage < 0) return; // don't retaliate against healers
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
public readonly bool Capturable = false;
|
||||
public readonly string Footprint = "x";
|
||||
public readonly int2 Dimensions = new int2(1, 1);
|
||||
public readonly bool Unsellable = false;
|
||||
public readonly int RefundPercent = 50;
|
||||
|
||||
public readonly string[] BuildSounds = {"placbldg.aud", "build5.aud"};
|
||||
public readonly string[] SellSounds = {"cashturn.aud"};
|
||||
@@ -36,6 +34,9 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
|
||||
public bool IsCloseEnoughToBase(World world, Player p, string buildingName, int2 topLeft)
|
||||
{
|
||||
if (p.PlayerActor.Trait<DeveloperMode>().BuildAnywhere)
|
||||
return true;
|
||||
|
||||
var buildingMaxBounds = Dimensions;
|
||||
if( Rules.Info[ buildingName ].Traits.Contains<BibInfo>() )
|
||||
buildingMaxBounds.Y += 1;
|
||||
@@ -62,7 +63,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
}
|
||||
}
|
||||
|
||||
public class Building : INotifyDamage, IResolveOrder, IOccupySpace, INotifyCapture, ISync
|
||||
public class Building : INotifyDamage, IOccupySpace, INotifyCapture, ISync, ITechTreePrerequisite
|
||||
{
|
||||
readonly Actor self;
|
||||
public readonly BuildingInfo Info;
|
||||
@@ -72,7 +73,9 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
PowerManager PlayerPower;
|
||||
|
||||
public int2 PxPosition { get { return ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; } }
|
||||
|
||||
|
||||
public IEnumerable<string> ProvidesPrerequisites { get { yield return self.Info.Name; } }
|
||||
|
||||
public Building(ActorInitializer init, BuildingInfo info)
|
||||
{
|
||||
this.self = init.self;
|
||||
@@ -97,15 +100,6 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
PlayerPower.UpdateActor(self, GetPowerUsage());
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Sell")
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new Sell());
|
||||
}
|
||||
}
|
||||
|
||||
public int2 TopLeft
|
||||
{
|
||||
get { return topLeft; }
|
||||
|
||||
@@ -23,12 +23,10 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
bool disabled = false;
|
||||
int normalPower = 0;
|
||||
PowerManager PowerManager;
|
||||
TechTree TechTree;
|
||||
|
||||
public CanPowerDown(ActorInitializer init)
|
||||
{
|
||||
PowerManager = init.self.Owner.PlayerActor.Trait<PowerManager>();
|
||||
TechTree = init.self.Owner.PlayerActor.Trait<TechTree>();
|
||||
normalPower = init.self.Info.Traits.Get<BuildingInfo>().Power;
|
||||
}
|
||||
public bool Disabled { get { return disabled; } }
|
||||
@@ -42,16 +40,12 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
Sound.PlayToPlayer(self.Owner, disabled ? eva.EnablePower : eva.DisablePower);
|
||||
|
||||
PowerManager.UpdateActor(self, disabled ? 0 : normalPower);
|
||||
|
||||
// Rebuild the tech tree; some support powers require active buildings
|
||||
TechTree.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
PowerManager = newOwner.PlayerActor.Trait<PowerManager>();
|
||||
TechTree = newOwner.PlayerActor.Trait<TechTree>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Mods.RA.Effects;
|
||||
|
||||
namespace OpenRA.Mods.RA.Buildings
|
||||
{
|
||||
@@ -24,17 +25,21 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
void DoSell(Actor self)
|
||||
{
|
||||
var h = self.TraitOrDefault<Health>();
|
||||
var bi = self.Info.Traits.Get<BuildingInfo>();
|
||||
var si = self.Info.Traits.Get<SellableInfo>();
|
||||
var pr = self.Owner.PlayerActor.Trait<PlayerResources>();
|
||||
var csv = self.Info.Traits.GetOrDefault<CustomSellValueInfo>();
|
||||
|
||||
var cost = csv != null ? csv.Value : self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||
|
||||
var refund = (cost * bi.RefundPercent * (h == null ? 1 : h.HP)) / (100 * (h == null ? 1 : h.MaxHP));
|
||||
var refund = (cost * si.RefundPercent * (h == null ? 1 : h.HP)) / (100 * (h == null ? 1 : h.MaxHP));
|
||||
pr.GiveCash(refund);
|
||||
|
||||
foreach (var ns in self.TraitsImplementing<INotifySold>())
|
||||
ns.Sold(self);
|
||||
ns.Sold(self);
|
||||
|
||||
if (self.World.LocalPlayer != null && self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
|
||||
self.World.AddFrameEndTask(w => w.Add(new CashTick(refund, 30, 2, self.CenterLocation, self.Owner.ColorRamp.GetColor(0))));
|
||||
|
||||
self.Destroy();
|
||||
}
|
||||
|
||||
|
||||
34
OpenRA.Mods.RA/Buildings/Sellable.cs
Normal file
34
OpenRA.Mods.RA/Buildings/Sellable.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Orders;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Buildings
|
||||
{
|
||||
class SellableInfo : TraitInfo<Sellable>
|
||||
{
|
||||
public readonly int RefundPercent = 50;
|
||||
}
|
||||
|
||||
class Sellable : IResolveOrder
|
||||
{
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Sell")
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(new Sell());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
|
||||
public void ActorChanged(Actor a)
|
||||
{
|
||||
if (a.Owner == player && a.HasTrait<Building>())
|
||||
if (a.Owner == player && a.HasTrait<ITechTreePrerequisite>())
|
||||
Update();
|
||||
}
|
||||
|
||||
@@ -59,15 +59,13 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||
if (player == null)
|
||||
return ret;
|
||||
|
||||
|
||||
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||
{
|
||||
ret[ b.Info.Name ].Add( b );
|
||||
var tt = b.Info.Traits.GetOrDefault<TooltipInfo>();
|
||||
if( tt != null )
|
||||
foreach( var alt in tt.AlternateName )
|
||||
ret[ alt ].Add( b );
|
||||
}
|
||||
foreach (var b in player.World.ActorsWithTrait<ITechTreePrerequisite>()
|
||||
.Where(a => a.Actor.IsInWorld && !a.Actor.IsDead() && a.Actor.Owner == player))
|
||||
foreach (var p in b.Trait.ProvidesPrerequisites)
|
||||
ret[ p ].Add( b.Actor );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -113,4 +111,26 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
void PrerequisitesAvailable(string key);
|
||||
void PrerequisitesUnavailable(string key);
|
||||
}
|
||||
|
||||
public interface ITechTreePrerequisite
|
||||
{
|
||||
IEnumerable<string> ProvidesPrerequisites {get;}
|
||||
}
|
||||
|
||||
public class ProvidesCustomPrerequisiteInfo : ITraitInfo
|
||||
{
|
||||
public string Prerequisite;
|
||||
public object Create(ActorInitializer init) { return new ProvidesCustomPrerequisite(this);}
|
||||
}
|
||||
|
||||
public class ProvidesCustomPrerequisite : ITechTreePrerequisite
|
||||
{
|
||||
ProvidesCustomPrerequisiteInfo Info;
|
||||
public IEnumerable<string> ProvidesPrerequisites { get { yield return Info.Prerequisite; } }
|
||||
|
||||
public ProvidesCustomPrerequisite(ProvidesCustomPrerequisiteInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
continue; // Cell is empty; continue search
|
||||
|
||||
// Cell contains an actor. Is it the type we want?
|
||||
if (world.Queries.WithTrait<LineBuild>().Any(a => (a.Actor.Info.Name == name && a.Actor.Location.X == cell.X && a.Actor.Location.Y == cell.Y)))
|
||||
if (world.ActorsWithTrait<LineBuild>().Any(a => (a.Actor.Info.Name == name && a.Actor.Location.X == cell.X && a.Actor.Location.Y == cell.Y)))
|
||||
dirs[d] = i; // Cell contains actor of correct type
|
||||
else
|
||||
dirs[d] = -1; // Cell is blocked by another actor type
|
||||
|
||||
@@ -9,27 +9,39 @@
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Mods.RA.Effects;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
class CashTricklerInfo : TraitInfo<CashTrickler>
|
||||
class CashTricklerInfo : ITraitInfo
|
||||
{
|
||||
public readonly int Period = 10;
|
||||
public readonly int Amount = 3;
|
||||
public readonly int Period = 50;
|
||||
public readonly int Amount = 15;
|
||||
public readonly bool ShowTicks = true;
|
||||
public readonly int TickLifetime = 30;
|
||||
public readonly int TickVelocity = 1;
|
||||
|
||||
public object Create (ActorInitializer init) { return new CashTrickler(this); }
|
||||
}
|
||||
|
||||
class CashTrickler : ITick, ISync
|
||||
{
|
||||
[Sync]
|
||||
int ticks;
|
||||
|
||||
CashTricklerInfo Info;
|
||||
public CashTrickler(CashTricklerInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (--ticks < 0)
|
||||
{
|
||||
var info = self.Info.Traits.Get<CashTricklerInfo>();
|
||||
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(info.Amount);
|
||||
ticks = info.Period;
|
||||
self.Owner.PlayerActor.Trait<PlayerResources>().GiveCash(Info.Amount);
|
||||
ticks = Info.Period;
|
||||
if (Info.ShowTicks)
|
||||
self.World.AddFrameEndTask(w => w.Add(new CashTick(Info.Amount, Info.TickLifetime, Info.TickVelocity, self.CenterLocation, self.Owner.ColorRamp.GetColor(0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA
|
||||
Sound.Play("chrotnk1.aud", Game.CellSize * order.TargetLocation.ToFloat2());
|
||||
chargeTick = 25 * self.Info.Traits.Get<ChronoshiftDeployInfo>().ChargeTime;
|
||||
|
||||
foreach (var a in self.World.Queries.WithTrait<ChronoshiftPaletteEffect>())
|
||||
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())
|
||||
a.Trait.Enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public class ChronoshiftPaletteEffect : IPaletteModifier, ITick
|
||||
{
|
||||
const int chronoEffectLength = 20;
|
||||
const int chronoEffectLength = 60;
|
||||
int remainingFrames;
|
||||
|
||||
public void Enable()
|
||||
|
||||
@@ -104,10 +104,14 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public bool IsVisible(Actor self)
|
||||
{
|
||||
if (!Cloaked || self.Owner == self.World.LocalPlayer || self.World.LocalPlayer == null || self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
|
||||
return true;
|
||||
|
||||
return self.World.Queries.WithTrait<DetectCloaked>().Any(a => (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
|
||||
if (!Cloaked || self.Owner == self.World.LocalPlayer ||
|
||||
self.World.LocalPlayer == null ||
|
||||
self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
|
||||
return true;
|
||||
|
||||
return self.World.ActorsWithTrait<DetectCloaked>().Any(a =>
|
||||
a.Actor.Owner.Stances[self.Owner] != Stance.Ally &&
|
||||
(self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<DetectCloakedInfo>().Range);
|
||||
}
|
||||
|
||||
public Color RadarColorOverride(Actor self)
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA
|
||||
if (!world.Map.IsInMap(targetTile))
|
||||
return;
|
||||
|
||||
var isWater = world.GetTerrainInfo(targetTile).IsWater;
|
||||
var isWater = args.destAltitude == 0 && world.GetTerrainInfo(targetTile).IsWater;
|
||||
var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;
|
||||
|
||||
if (explosionType != null)
|
||||
|
||||
@@ -21,13 +21,15 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
|
||||
|
||||
var hasAnything = self.World.Queries.OwnedBy[self.Owner]
|
||||
.WithTrait<MustBeDestroyed>().Any();
|
||||
var hasAnything = self.World.ActorsWithTrait<MustBeDestroyed>()
|
||||
.Any( a => a.Actor.Owner == self.Owner );
|
||||
|
||||
if (!hasAnything && !self.Owner.NonCombatant)
|
||||
Surrender(self);
|
||||
|
||||
var others = self.World.players.Where( p => !p.Value.NonCombatant && p.Value != self.Owner && p.Value.Stances[self.Owner] != Stance.Ally );
|
||||
var others = self.World.players.Where( p => !p.Value.NonCombatant
|
||||
&& p.Value != self.Owner && p.Value.Stances[self.Owner] != Stance.Ally );
|
||||
|
||||
if (others.Count() == 0) return;
|
||||
|
||||
if(others.All(p => p.Value.WinState == WinState.Lost))
|
||||
@@ -45,9 +47,10 @@ namespace OpenRA.Mods.RA
|
||||
if (self.Owner.WinState == WinState.Lost) return;
|
||||
self.Owner.WinState = WinState.Lost;
|
||||
|
||||
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
|
||||
foreach (var a in self.World.Queries.OwnedBy[self.Owner])
|
||||
a.Kill(a);
|
||||
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
|
||||
|
||||
foreach (var a in self.World.Actors.Where(a => a.Owner == self.Owner))
|
||||
a.Kill(a);
|
||||
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.LocalShroud.Disabled = true;
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
|
||||
new AltitudeInit( Rules.Info["badr"].Traits.Get<AircraftInfo>().CruiseAltitude ),
|
||||
});
|
||||
plane.CancelActivity();
|
||||
plane.QueueActivity(new FlyCircle(p));
|
||||
plane.QueueActivity(new FlyAttackLoop(p));
|
||||
plane.Trait<ParaDrop>().SetLZ(p);
|
||||
plane.Trait<Cargo>().Load(plane, crate);
|
||||
});
|
||||
|
||||
@@ -29,8 +29,11 @@ namespace OpenRA.Mods.RA.Crates
|
||||
if (base.GetSelectionShares(collector) == 0)
|
||||
return 0; // there's some other really good reason why we shouldn't give this.
|
||||
|
||||
var hasBase = self.World.Queries.OwnedBy[collector.Owner].WithTrait<BaseBuilding>().Any();
|
||||
return hasBase ? info.SelectionShares : (info as GiveMcvCrateActionInfo).NoBaseSelectionShares;
|
||||
var hasBase = self.World.ActorsWithTrait<BaseBuilding>()
|
||||
.Any(a => a.Actor.Owner == collector.Owner);
|
||||
|
||||
return hasBase ? info.SelectionShares :
|
||||
(info as GiveMcvCrateActionInfo).NoBaseSelectionShares;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA
|
||||
// create the unplayable map players -- neutral, shellmap, scripted, etc.
|
||||
foreach (var kv in w.Map.Players.Where(p => !p.Value.Playable))
|
||||
{
|
||||
var player = new Player(w, kv.Value, mapPlayerIndex--);
|
||||
var player = new Player(w, null, kv.Value, mapPlayerIndex--);
|
||||
w.AddPlayer(player);
|
||||
if (kv.Value.OwnsWorld)
|
||||
w.WorldActor.Owner = player;
|
||||
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
/* todo: pick a random name from the pool */
|
||||
|
||||
var player = new Player(w, w.Map.Players[slot.MapPlayer], playerIndex++);
|
||||
var player = new Player(w, null, w.Map.Players[slot.MapPlayer], playerIndex++);
|
||||
w.AddPlayer(player);
|
||||
|
||||
/* activate the bot option that's selected! */
|
||||
|
||||
50
OpenRA.Mods.RA/Effects/CashTick.cs
Normal file
50
OpenRA.Mods.RA/Effects/CashTick.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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 COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Effects
|
||||
{
|
||||
class CashTick : IEffect
|
||||
{
|
||||
string s;
|
||||
int lifetime;
|
||||
int remaining;
|
||||
int velocity;
|
||||
float2 pos;
|
||||
Color color;
|
||||
|
||||
public CashTick(int value, int lifetime, int velocity, float2 pos, Color color)
|
||||
{
|
||||
this.color = color;
|
||||
this.lifetime = lifetime;
|
||||
this.velocity = velocity;
|
||||
s = "{0}${1}".F(value < 0 ? "-" : "+", value);
|
||||
this.pos = pos - 0.5f*Game.Renderer.TinyBoldFont.Measure(s).ToFloat2();
|
||||
remaining = lifetime;
|
||||
}
|
||||
|
||||
public void Tick(World world)
|
||||
{
|
||||
if (--remaining <= 0)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
pos.Y -= velocity;
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
Game.Renderer.TinyBoldFont.DrawTextWithContrast(s, pos - Game.viewport.Location, color, Color.Black,1);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA.Effects
|
||||
if (altitude <= 0)
|
||||
{
|
||||
// Trigger screen desaturate effect
|
||||
foreach (var a in world.Queries.WithTrait<NukePaletteEffect>())
|
||||
foreach (var a in world.ActorsWithTrait<NukePaletteEffect>())
|
||||
a.Trait.Enable();
|
||||
|
||||
Explode(world);
|
||||
|
||||
@@ -13,7 +13,8 @@ using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Effects;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -23,7 +24,7 @@ namespace OpenRA.Mods.RA
|
||||
public readonly float[] FirepowerModifier = { 1.1f, 1.15f, 1.2f, 1.5f };
|
||||
public readonly float[] ArmorModifier = { 1.1f, 1.2f, 1.3f, 1.5f };
|
||||
public readonly decimal[] SpeedModifier = { 1.1m, 1.15m, 1.2m, 1.5m };
|
||||
public object Create(ActorInitializer init) { return new GainsExperience(init.self, this); }
|
||||
public object Create(ActorInitializer init) { return new GainsExperience(init, this); }
|
||||
}
|
||||
|
||||
public class GainsExperience : IFirepowerModifier, ISpeedModifier, IDamageModifier, IRenderModifier, ISync
|
||||
@@ -33,14 +34,22 @@ namespace OpenRA.Mods.RA
|
||||
readonly GainsExperienceInfo Info;
|
||||
readonly Animation RankAnim;
|
||||
|
||||
public GainsExperience(Actor self, GainsExperienceInfo info)
|
||||
public GainsExperience(ActorInitializer init, GainsExperienceInfo info)
|
||||
{
|
||||
this.self = self;
|
||||
self = init.self;
|
||||
this.Info = info;
|
||||
var cost = self.Info.Traits.Get<ValuedInfo>().Cost;
|
||||
Levels = Info.CostThreshold.Select(t => (int)(t * cost)).ToArray();
|
||||
RankAnim = new Animation("rank");
|
||||
RankAnim.PlayFetchIndex("rank", () => Level - 1);
|
||||
RankAnim.PlayFetchIndex("rank", () => Level - 1);
|
||||
|
||||
if (init.Contains<ExperienceInit>())
|
||||
{
|
||||
Experience = init.Get<ExperienceInit, int>();
|
||||
|
||||
while (Level < Levels.Length && Experience >= Levels[Level])
|
||||
Level++;
|
||||
}
|
||||
}
|
||||
|
||||
[Sync]
|
||||
@@ -49,8 +58,8 @@ namespace OpenRA.Mods.RA
|
||||
int Level = 0;
|
||||
|
||||
public void GiveOneLevel()
|
||||
{
|
||||
if (Level < Levels.Count())
|
||||
{
|
||||
if (Level < Levels.Length)
|
||||
GiveExperience(Levels[Level] - Experience);
|
||||
}
|
||||
|
||||
@@ -58,7 +67,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
Experience += amount;
|
||||
|
||||
while (Level < Levels.Count() && Experience >= Levels[Level])
|
||||
while (Level < Levels.Length && Experience >= Levels[Level])
|
||||
{
|
||||
Level++;
|
||||
|
||||
@@ -102,5 +111,23 @@ namespace OpenRA.Mods.RA
|
||||
yield return new Renderable(RankAnim.Image,
|
||||
new float2(bounds.Right - 6, bounds.Bottom - 8), "effect", (int)self.CenterLocation.Y);
|
||||
}
|
||||
}
|
||||
|
||||
class ExperienceInit : IActorInit<int>
|
||||
{
|
||||
[FieldFromYamlKey]
|
||||
public readonly int value = 0;
|
||||
|
||||
public ExperienceInit() { }
|
||||
|
||||
public ExperienceInit(int init)
|
||||
{
|
||||
value = init;
|
||||
}
|
||||
|
||||
public int Value(World world)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,10 +110,10 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
this.p = p;
|
||||
enabled = true;
|
||||
playerPower = p.PlayerActor.Trait<PowerManager>();
|
||||
builders = new BaseBuilder[] {
|
||||
new BaseBuilder( this, "Building", ChooseBuildingToBuild ),
|
||||
new BaseBuilder( this, "Defense", ChooseDefenseToBuild ) };
|
||||
playerPower = p.PlayerActor.Trait<PowerManager>();
|
||||
builders = new BaseBuilder[] {
|
||||
new BaseBuilder( this, "Building", q => ChooseBuildingToBuild(q, true) ),
|
||||
new BaseBuilder( this, "Defense", q => ChooseBuildingToBuild(q, false) ) };
|
||||
}
|
||||
|
||||
int GetPowerProvidedBy(ActorInfo building)
|
||||
@@ -137,38 +137,23 @@ namespace OpenRA.Mods.RA
|
||||
playerPower.PowerProvided > playerPower.PowerDrained * 1.2;
|
||||
}
|
||||
|
||||
ActorInfo ChooseBuildingToBuild(ProductionQueue queue)
|
||||
ActorInfo ChooseBuildingToBuild(ProductionQueue queue, bool buildPower)
|
||||
{
|
||||
var buildableThings = queue.BuildableItems();
|
||||
|
||||
if (!HasAdequatePower()) /* try to maintain 20% excess power */
|
||||
{
|
||||
{
|
||||
if (!buildPower) return null;
|
||||
|
||||
/* find the best thing we can build which produces power */
|
||||
return buildableThings.Where(a => GetPowerProvidedBy(a) > 0)
|
||||
.OrderByDescending(a => GetPowerProvidedBy(a)).FirstOrDefault();
|
||||
}
|
||||
|
||||
var myBuildings = p.World.Queries.OwnedBy[p].WithTrait<Building>()
|
||||
.Select(a => a.Actor.Info.Name).ToArray();
|
||||
|
||||
|
||||
foreach (var frac in Info.BuildingFractions)
|
||||
if (buildableThings.Any(b => b.Name == frac.Key))
|
||||
if (myBuildings.Count(a => a == frac.Key) < frac.Value * myBuildings.Length)
|
||||
return Rules.Info[frac.Key];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
ActorInfo ChooseDefenseToBuild(ProductionQueue queue)
|
||||
{
|
||||
if (!HasAdequatePower())
|
||||
return null;
|
||||
|
||||
var buildableThings = queue.BuildableItems();
|
||||
|
||||
var myBuildings = p.World.Queries.OwnedBy[p].WithTrait<Building>()
|
||||
.Select(a => a.Actor.Info.Name).ToArray();
|
||||
}
|
||||
|
||||
var myBuildings = p.World
|
||||
.ActorsWithTrait<Building>()
|
||||
.Where( a => a.Actor.Owner == p )
|
||||
.Select(a => a.Actor.Info.Name).ToArray();
|
||||
|
||||
foreach (var frac in Info.BuildingFractions)
|
||||
if (buildableThings.Any(b => b.Name == frac.Key))
|
||||
@@ -287,9 +272,10 @@ namespace OpenRA.Mods.RA
|
||||
attackForce.RemoveAll(a => a.Destroyed);
|
||||
|
||||
// don't select harvesters.
|
||||
var newUnits = self.World.Queries.OwnedBy[p]
|
||||
.Where(a => a.HasTrait<IMove>() && a.Info != Rules.Info["harv"]
|
||||
&& !activeUnits.Contains(a)).ToArray();
|
||||
var newUnits = self.World.ActorsWithTrait<IMove>()
|
||||
.Where(a => a.Actor.Owner == p && a.Actor.Info != Rules.Info["harv"]
|
||||
&& !activeUnits.Contains(a.Actor))
|
||||
.Select(a => a.Actor).ToArray();
|
||||
|
||||
foreach (var a in newUnits)
|
||||
{
|
||||
@@ -323,8 +309,9 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
void SetRallyPointsForNewProductionBuildings(Actor self)
|
||||
{
|
||||
var buildings = self.World.Queries.OwnedBy[p].WithTrait<RallyPoint>()
|
||||
.Where(rp => !IsRallyPointValid(rp.Trait.rallyPoint)).ToArray();
|
||||
var buildings = self.World.ActorsWithTrait<RallyPoint>()
|
||||
.Where(rp => rp.Actor.Owner == p &&
|
||||
!IsRallyPointValid(rp.Trait.rallyPoint)).ToArray();
|
||||
|
||||
if (buildings.Length > 0)
|
||||
BotDebug("Bot {0} needs to find rallypoints for {1} buildings.",
|
||||
@@ -395,9 +382,9 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
void DeployMcv(Actor self)
|
||||
{
|
||||
/* find our mcv and deploy it */
|
||||
var mcv = self.World.Queries.OwnedBy[p]
|
||||
.FirstOrDefault(a => a.Info == Rules.Info["mcv"]);
|
||||
/* find our mcv and deploy it */
|
||||
var mcv = self.World.Actors
|
||||
.FirstOrDefault(a => a.Owner == p && a.Info == Rules.Info["mcv"]);
|
||||
|
||||
if (mcv != null)
|
||||
{
|
||||
@@ -412,7 +399,7 @@ namespace OpenRA.Mods.RA
|
||||
private void BuildRandom(string category)
|
||||
{
|
||||
// Pick a free queue
|
||||
var queue = world.Queries.WithTrait<ProductionQueue>()
|
||||
var queue = world.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == p &&
|
||||
a.Trait.Info.Type == category &&
|
||||
a.Trait.CurrentItem() == null)
|
||||
@@ -460,7 +447,7 @@ namespace OpenRA.Mods.RA
|
||||
public void Tick()
|
||||
{
|
||||
// Pick a free queue
|
||||
var queue = ai.world.Queries.WithTrait<ProductionQueue>()
|
||||
var queue = ai.world.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == ai.p && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait)
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -63,18 +63,19 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
|
||||
Actor ClosestProc(Actor self, Actor ignore)
|
||||
{
|
||||
var refs = self.World.Queries.OwnedBy[self.Owner]
|
||||
.Where(x => x != ignore && x.HasTrait<IAcceptOre>())
|
||||
.ToList();
|
||||
{
|
||||
var refs = self.World.ActorsWithTrait<IAcceptOre>()
|
||||
.Where(x => x.Actor != ignore && x.Actor.Owner == self.Owner)
|
||||
.ToList();
|
||||
var mi = self.Info.Traits.Get<MobileInfo>();
|
||||
var path = self.World.WorldActor.Trait<PathFinder>().FindPath(
|
||||
PathSearch.FromPoints(self.World, mi,
|
||||
refs.Select(r => r.Location + r.Trait<IAcceptOre>().DeliverOffset),
|
||||
PathSearch.FromPoints(self.World, mi,
|
||||
refs.Select(r => r.Actor.Location + r.Trait.DeliverOffset),
|
||||
self.Location, false));
|
||||
path.Reverse();
|
||||
if (path.Count != 0)
|
||||
return refs.FirstOrDefault(x => x.Location + x.Trait<IAcceptOre>().DeliverOffset == path[0]);
|
||||
return refs.Where(x => x.Actor.Location + x.Trait.DeliverOffset == path[0])
|
||||
.Select(a => a.Actor).FirstOrDefault();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
if (cellInfo.GetUpperBound(0) != world.Map.MapSize.X - 1 ||
|
||||
cellInfo.GetUpperBound(1) != world.Map.MapSize.Y - 1)
|
||||
{
|
||||
Game.Debug("Discarding old pooled CellInfo of wrong size.");
|
||||
Log.Write("debug", "Discarding old pooled CellInfo of wrong size.");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@
|
||||
<Compile Include="Activities\Demolish.cs" />
|
||||
<Compile Include="Activities\Enter.cs" />
|
||||
<Compile Include="Activities\EnterTransport.cs" />
|
||||
<Compile Include="Air\FlyCircle.cs" />
|
||||
<Compile Include="Buildings\Sellable.cs" />
|
||||
<Compile Include="Effects\CashTick.cs" />
|
||||
<Compile Include="ProductionBar.cs" />
|
||||
<Compile Include="Render\RenderEditorOnly.cs" />
|
||||
<Compile Include="SmokeTrailWhenDamaged.cs" />
|
||||
@@ -102,6 +105,7 @@
|
||||
<Compile Include="Buildings\TechTree.cs" />
|
||||
<Compile Include="Buildings\Util.cs" />
|
||||
<Compile Include="ProximityCaptor.cs" />
|
||||
<Compile Include="SupportPowers\SupportPowerChargeBar.cs" />
|
||||
<Compile Include="Valued.cs" />
|
||||
<Compile Include="Combat.cs" />
|
||||
<Compile Include="Player\SurrenderOnDisconnect.cs" />
|
||||
@@ -294,7 +298,6 @@
|
||||
<Compile Include="HackyAI.cs" />
|
||||
<Compile Include="RALoadScreen.cs" />
|
||||
<Compile Include="NullLoadScreen.cs" />
|
||||
<Compile Include="World\GotoNextBase.cs" />
|
||||
<Compile Include="World\SmudgeLayer.cs" />
|
||||
<Compile Include="Scripting\Media.cs" />
|
||||
<Compile Include="OpenWidgetAtGameStart.cs" />
|
||||
@@ -327,6 +330,9 @@
|
||||
<Compile Include="Widgets\Delegates\GameInitDelegate.cs" />
|
||||
<Compile Include="AttackWander.cs" />
|
||||
<Compile Include="ScaredyCat.cs" />
|
||||
<Compile Include="Widgets\SidebarButtonWidget.cs" />
|
||||
<Compile Include="Widgets\RadarWidget.cs" />
|
||||
<Compile Include="ActorExts.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace OpenRA.Mods.RA.Orders
|
||||
|
||||
public static bool PlayerIsAllowedToRepair( World world )
|
||||
{
|
||||
return world.Queries.OwnedBy[ world.LocalPlayer ].WithTrait<AllowsBuildingRepair>().Any();
|
||||
return world.ActorsWithTrait<AllowsBuildingRepair>()
|
||||
.Any(a => a.Actor.Owner == world.LocalPlayer);
|
||||
}
|
||||
|
||||
public void RenderAfterWorld( WorldRenderer wr, World world ) { }
|
||||
|
||||
@@ -32,12 +32,9 @@ namespace OpenRA.Mods.RA.Orders
|
||||
{
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Owner == world.LocalPlayer
|
||||
&& a.HasTrait<Building>()
|
||||
&& a.HasTrait<Selectable>()).FirstOrDefault();
|
||||
|
||||
var building = underCursor != null ? underCursor.Info.Traits.Get<BuildingInfo>() : null;
|
||||
|
||||
if (building != null && !building.Unsellable)
|
||||
&& a.HasTrait<Sellable>()).FirstOrDefault();
|
||||
|
||||
if (underCursor != null)
|
||||
yield return new Order("Sell", underCursor, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,16 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Effects;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -25,10 +24,11 @@ namespace OpenRA.Mods.RA
|
||||
public readonly int PipCount = 0;
|
||||
public readonly PipType PipColor = PipType.Red;
|
||||
public readonly int2 DockOffset = new int2 (1, 2);
|
||||
public readonly int Capacity = 0;
|
||||
public readonly int ProcessTick = 25;
|
||||
public readonly int ProcessAmount = 50;
|
||||
public readonly int LowPowerProcessTick = 50;
|
||||
|
||||
public readonly bool ShowTicks = true;
|
||||
public readonly int TickLifetime = 30;
|
||||
public readonly int TickVelocity = 2;
|
||||
public readonly int TickRate = 10;
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new OreRefinery(init.self, this); }
|
||||
}
|
||||
@@ -38,7 +38,10 @@ namespace OpenRA.Mods.RA
|
||||
readonly Actor self;
|
||||
readonly OreRefineryInfo Info;
|
||||
PlayerResources PlayerResources;
|
||||
|
||||
|
||||
int currentDisplayTick = 0;
|
||||
int currentDisplayValue = 0;
|
||||
|
||||
[Sync]
|
||||
public int Ore = 0;
|
||||
|
||||
@@ -58,11 +61,12 @@ namespace OpenRA.Mods.RA
|
||||
this.self = self;
|
||||
Info = info;
|
||||
PlayerResources = self.Owner.PlayerActor.Trait<PlayerResources>();
|
||||
currentDisplayTick = Info.TickRate;
|
||||
}
|
||||
|
||||
public IEnumerable<TraitPair<Harvester>> GetLinkedHarvesters()
|
||||
{
|
||||
return self.World.Queries.WithTrait<Harvester>()
|
||||
return self.World.ActorsWithTrait<Harvester>()
|
||||
.Where(a => a.Trait.LinkedProc == self);
|
||||
}
|
||||
|
||||
@@ -74,6 +78,8 @@ namespace OpenRA.Mods.RA
|
||||
public void GiveOre(int amount)
|
||||
{
|
||||
PlayerResources.GiveOre(amount);
|
||||
if (Info.ShowTicks)
|
||||
currentDisplayValue += amount;
|
||||
}
|
||||
|
||||
void CancelDock(Actor self)
|
||||
@@ -93,6 +99,15 @@ namespace OpenRA.Mods.RA
|
||||
self.Trait<RenderBuilding>().CancelCustomAnim(self);
|
||||
dockedHarv = null;
|
||||
}
|
||||
|
||||
if (Info.ShowTicks && currentDisplayValue > 0 && --currentDisplayTick <= 0)
|
||||
{
|
||||
var temp = currentDisplayValue;
|
||||
if (self.World.LocalPlayer != null && self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
|
||||
self.World.AddFrameEndTask(w => w.Add(new CashTick(temp, Info.TickLifetime, Info.TickVelocity, self.CenterLocation, self.Owner.ColorRamp.GetColor(0))));
|
||||
currentDisplayTick = Info.TickRate;
|
||||
currentDisplayValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Damaged (Actor self, AttackInfo e)
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace OpenRA.Mods.RA
|
||||
[Sync] bool QueueActive = false;
|
||||
public override void Tick( Actor self )
|
||||
{
|
||||
QueueActive = self.World.Queries.OwnedBy[self.Owner].WithTrait<Production>()
|
||||
QueueActive = self.World.ActorsWithTrait<Production>()
|
||||
.Where(x => x.Actor.Owner == self.Owner)
|
||||
.Where(x => x.Trait.Info.Produces.Contains(Info.Type))
|
||||
.Any();
|
||||
|
||||
@@ -49,8 +50,9 @@ namespace OpenRA.Mods.RA
|
||||
protected override bool BuildUnit( string name )
|
||||
{
|
||||
// Find a production structure to build this actor
|
||||
var producers = self.World.Queries.OwnedBy[self.Owner]
|
||||
.WithTrait<Production>()
|
||||
var producers = self.World
|
||||
.ActorsWithTrait<Production>()
|
||||
.Where(x => x.Actor.Owner == self.Owner)
|
||||
.Where(x => x.Trait.Info.Produces.Contains(Info.Type))
|
||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding() ? 1 : 0 ); // prioritize the primary.
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA
|
||||
var prevItems = GetNumBuildables(self.Owner);
|
||||
|
||||
// Find the queue with the target actor
|
||||
var queue = w.Queries.WithTrait<ProductionQueue>()
|
||||
var queue = w.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(p => p.Actor.Owner == self.Owner &&
|
||||
p.Trait.CurrentItem() != null &&
|
||||
p.Trait.CurrentItem().Item == order.TargetString &&
|
||||
@@ -95,7 +95,8 @@ namespace OpenRA.Mods.RA
|
||||
if (bi == null)
|
||||
return;
|
||||
|
||||
var producers = self.World.Queries.OwnedBy[ self.Owner ].WithTrait<Production>()
|
||||
var producers = self.World.ActorsWithTrait<Production>()
|
||||
.Where( x => x.Actor.Owner == self.Owner )
|
||||
.Where( x => x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains( bi.Queue ) )
|
||||
.ToList();
|
||||
var producer = producers.Where( x => x.Actor.IsPrimaryBuilding() ).Concat( producers )
|
||||
@@ -109,7 +110,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (p != p.World.LocalPlayer) return 0; // this only matters for local players.
|
||||
|
||||
return p.World.Queries.WithTrait<ProductionQueue>()
|
||||
return p.World.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == p)
|
||||
.SelectMany(a => a.Trait.BuildableItems()).Distinct().Count();
|
||||
}
|
||||
|
||||
@@ -54,10 +54,12 @@ namespace OpenRA.Mods.RA
|
||||
return;
|
||||
}
|
||||
|
||||
// THIS IS SHIT
|
||||
// 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>()
|
||||
foreach (var b in self.World
|
||||
.ActorsWithTrait<PrimaryBuilding>()
|
||||
.Where(a => a.Actor.Owner == self.Owner)
|
||||
.Where(x => x.Trait.IsPrimary
|
||||
&& (x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains(p))))
|
||||
b.Trait.SetPrimaryProducer(b.Actor, false);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA
|
||||
if (self.TraitsImplementing<IDisable>().Any(d => d.Disabled))
|
||||
return false;
|
||||
|
||||
var isJammed = self.World.Queries.WithTrait<JamsRadar>().Any(a => self.Owner != a.Actor.Owner
|
||||
var isJammed = self.World.ActorsWithTrait<JamsRadar>().Any(a => self.Owner != a.Actor.Owner
|
||||
&& (self.Location - a.Actor.Location).Length < a.Actor.Info.Traits.Get<JamsRadarInfo>().Range);
|
||||
|
||||
return !isJammed;
|
||||
|
||||
@@ -20,59 +20,33 @@ namespace OpenRA.Mods.RA.Render
|
||||
public override object Create(ActorInitializer init) { return new RenderSpy(init.self, this); }
|
||||
}
|
||||
|
||||
class RenderSpy : RenderInfantryProne, IRenderModifier, IIssueOrder, IResolveOrder, IOrderVoice
|
||||
class RenderSpy : RenderInfantryProne, IRenderModifier
|
||||
{
|
||||
Player disguisedAsPlayer;
|
||||
string disguisedAsSprite;
|
||||
|
||||
public RenderSpy(Actor self, RenderSpyInfo info) : base(self, info) { }
|
||||
Spy spy;
|
||||
|
||||
public RenderSpy(Actor self, RenderSpyInfo info) : base(self, info)
|
||||
{
|
||||
spy = self.Trait<Spy>();
|
||||
disguisedAsSprite = spy.disguisedAsSprite;
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
|
||||
{
|
||||
return disguisedAsPlayer != null ? r.Select(a => a.WithPalette(disguisedAsPlayer.Palette)) : r;
|
||||
return spy.disguisedAsPlayer != null ? r.Select(a => a.WithPalette(spy.disguisedAsPlayer.Palette)) : r;
|
||||
}
|
||||
|
||||
public override void Tick(Actor self)
|
||||
{
|
||||
base.Tick(self);
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Disguise")
|
||||
if (spy.disguisedAsSprite != disguisedAsSprite)
|
||||
{
|
||||
var target = order.TargetActor == self ? null : order.TargetActor;
|
||||
if (target != null && target.IsInWorld)
|
||||
{
|
||||
disguisedAsPlayer = target.Owner;
|
||||
disguisedAsSprite = target.Trait<RenderSimple>().GetImage(target);
|
||||
disguisedAsSprite = spy.disguisedAsSprite;
|
||||
if (disguisedAsSprite != null)
|
||||
anim.ChangeImage(disguisedAsSprite, "stand");
|
||||
}
|
||||
else
|
||||
{
|
||||
disguisedAsPlayer = null;
|
||||
disguisedAsSprite = null;
|
||||
anim.ChangeImage(GetImage(self), "stand");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders
|
||||
{
|
||||
get { yield return new UnitTraitOrderTargeter<RenderInfantry>( "Disguise", 5, "ability", true, true ); }
|
||||
}
|
||||
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
|
||||
{
|
||||
if( order.OrderID == "Disguise" )
|
||||
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
{
|
||||
return order.OrderString == "Disguise" ? "Attack" : null;
|
||||
base.Tick(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -30,9 +31,10 @@ namespace OpenRA.Mods.RA
|
||||
centerLocation,
|
||||
ai.Traits.Get<AttackBaseInfo>().GetMaximumRange());
|
||||
|
||||
foreach (var a in w.Queries.OwnedBy[w.LocalPlayer].WithTrait<RenderRangeCircle>())
|
||||
if (a.Actor.Info.Traits.Get<RenderRangeCircleInfo>().RangeCircleType == RangeCircleType)
|
||||
a.Trait.RenderBeforeWorld(wr, a.Actor);
|
||||
foreach (var a in w.ActorsWithTrait<RenderRangeCircle>())
|
||||
if (a.Actor.Owner == a.Actor.World.LocalPlayer)
|
||||
if (a.Actor.Info.Traits.Get<RenderRangeCircleInfo>().RangeCircleType == RangeCircleType)
|
||||
a.Trait.RenderBeforeWorld(wr, a.Actor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@
|
||||
|
||||
using System;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
class ReservableInfo : TraitInfo<Reservable> {}
|
||||
|
||||
public class Reservable : ITick
|
||||
public class Reservable : ITick, INotifyDamage, INotifyCapture, INotifySold
|
||||
{
|
||||
Actor reservedFor;
|
||||
Aircraft herp;
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
@@ -28,15 +30,16 @@ namespace OpenRA.Mods.RA
|
||||
reservedFor = null; /* not likely to arrive now. */
|
||||
}
|
||||
|
||||
public IDisposable Reserve(Actor self, Actor forActor)
|
||||
public IDisposable Reserve(Actor self, Actor forActor, Aircraft derp)
|
||||
{
|
||||
reservedFor = forActor;
|
||||
reservedFor = forActor;
|
||||
herp = derp;
|
||||
|
||||
// NOTE: we really dont care about the GC eating DisposableActions that apply to a world *other* than
|
||||
// the one we're playing in.
|
||||
|
||||
return new DisposableAction(
|
||||
() => reservedFor = null,
|
||||
() => {reservedFor = null; herp = null;},
|
||||
() => Game.RunAfterTick(
|
||||
() => { if (Game.IsCurrentWorld( self.World )) throw new InvalidOperationException(
|
||||
"Attempted to finalize an undisposed DisposableAction. {0} ({1}) reserved {2} ({3})"
|
||||
@@ -48,5 +51,24 @@ namespace OpenRA.Mods.RA
|
||||
var res = a.TraitOrDefault<Reservable>();
|
||||
return res != null && res.reservedFor != null;
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
{
|
||||
if (herp != null && e.DamageStateChanged && e.DamageState == DamageState.Dead)
|
||||
herp.UnReserve();
|
||||
}
|
||||
|
||||
public void OnCapture (Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
if (herp != null)
|
||||
herp.UnReserve();
|
||||
}
|
||||
|
||||
public void Selling (Actor self) { Sold(self); }
|
||||
public void Sold (Actor self)
|
||||
{
|
||||
if (herp != null)
|
||||
herp.UnReserve();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Scripting
|
||||
chronosphere.Trait<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
|
||||
|
||||
// Trigger screen desaturate effect
|
||||
foreach (var a in world.Queries.WithTrait<ChronoshiftPaletteEffect>())
|
||||
foreach (var a in world.ActorsWithTrait<ChronoshiftPaletteEffect>())
|
||||
a.Trait.Enable();
|
||||
|
||||
Sound.Play("chrono2.aud", units.First().First.CenterLocation);
|
||||
|
||||
@@ -37,16 +37,16 @@ namespace OpenRA.Mods.RA.Server
|
||||
public void LobbyInfoSynced(S server) { PingMasterServer(server); }
|
||||
public void GameStarted(S server) { PingMasterServer(server); }
|
||||
|
||||
static int lastPing = 0;
|
||||
int lastPing = 0;
|
||||
// Todo: use the settings passed to the server instead
|
||||
static bool isInternetServer = Game.Settings.Server.AdvertiseOnline;
|
||||
static string masterServerUrl = Game.Settings.Server.MasterServer;
|
||||
static int externalPort = Game.Settings.Server.ExternalPort;
|
||||
static bool isInitialPing = true;
|
||||
bool isInternetServer = Game.Settings.Server.AdvertiseOnline;
|
||||
string masterServerUrl = Game.Settings.Server.MasterServer;
|
||||
int externalPort = Game.Settings.Server.ExternalPort;
|
||||
bool isInitialPing = true;
|
||||
|
||||
static volatile bool isBusy;
|
||||
static Queue<string> masterServerMessages = new Queue<string>();
|
||||
public static void PingMasterServer(S server)
|
||||
volatile bool isBusy;
|
||||
Queue<string> masterServerMessages = new Queue<string>();
|
||||
public void PingMasterServer(S server)
|
||||
{
|
||||
if (isBusy || !isInternetServer) return;
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
@@ -22,7 +23,12 @@ namespace OpenRA.Mods.RA
|
||||
public void WorldLoaded(World world)
|
||||
{
|
||||
foreach (var actorReference in world.Map.Actors.Value)
|
||||
{
|
||||
{
|
||||
// if there is no real player associated, dont spawn it.
|
||||
var ownerName = actorReference.Value.InitDict.Get<OwnerInit>().PlayerName;
|
||||
if (!world.players.Values.Any(p => p.InternalName == ownerName))
|
||||
continue;
|
||||
|
||||
var initDict = actorReference.Value.InitDict;
|
||||
initDict.Add(new SkipMakeAnimsInit());
|
||||
Actors[actorReference.Key] = world.CreateActor(actorReference.Value.Type, initDict);
|
||||
|
||||
@@ -9,28 +9,93 @@
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Orders;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
class SpyToolTipInfo : TooltipInfo, ITraitPrerequisite<SpyInfo>
|
||||
{
|
||||
public override object Create (ActorInitializer init) { return new SpyToolTip(init.self, this); }
|
||||
}
|
||||
|
||||
class SpyToolTip : IToolTip
|
||||
{
|
||||
Actor self;
|
||||
TooltipInfo Info;
|
||||
Spy spy;
|
||||
|
||||
public string Name()
|
||||
{
|
||||
if (spy.Disguised)
|
||||
{
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
return "{0} ({1})".F(Info.Name, spy.disguisedAsName);
|
||||
return spy.disguisedAsName;
|
||||
}
|
||||
return Info.Name;
|
||||
}
|
||||
|
||||
public Player Owner()
|
||||
{
|
||||
if (spy.Disguised)
|
||||
{
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
return self.Owner;
|
||||
return spy.disguisedAsPlayer;
|
||||
}
|
||||
return self.Owner;
|
||||
}
|
||||
|
||||
public Stance Stance()
|
||||
{
|
||||
if (spy.Disguised)
|
||||
{
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
return self.World.LocalPlayer.Stances[self.Owner];
|
||||
return self.World.LocalPlayer.Stances[spy.disguisedAsPlayer];
|
||||
}
|
||||
return self.World.LocalPlayer.Stances[self.Owner];
|
||||
}
|
||||
|
||||
public SpyToolTip( Actor self, TooltipInfo info )
|
||||
{
|
||||
this.self = self;
|
||||
Info = info;
|
||||
spy = self.Trait<Spy>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SpyInfo : TraitInfo<Spy> { }
|
||||
|
||||
class Spy : IIssueOrder, IResolveOrder
|
||||
class Spy : IIssueOrder, IResolveOrder, IOrderVoice, IRadarColorModifier
|
||||
{
|
||||
public Player disguisedAsPlayer;
|
||||
public string disguisedAsSprite, disguisedAsName;
|
||||
|
||||
public bool Disguised { get { return disguisedAsPlayer != null; } }
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders
|
||||
{
|
||||
get { yield return new UnitTraitOrderTargeter<IAcceptSpy>( "SpyInfiltrate", 5, "enter", true, false ); }
|
||||
get
|
||||
{
|
||||
yield return new UnitTraitOrderTargeter<IAcceptSpy>( "SpyInfiltrate", 5, "enter", true, false );
|
||||
yield return new UnitTraitOrderTargeter<RenderInfantry>( "Disguise", 5, "ability", true, true );
|
||||
}
|
||||
}
|
||||
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
|
||||
{
|
||||
if( order.OrderID == "SpyInfiltrate" )
|
||||
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
|
||||
|
||||
if( order.OrderID == "Disguise" )
|
||||
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -44,6 +109,41 @@ namespace OpenRA.Mods.RA
|
||||
self.QueueActivity(new Enter(order.TargetActor));
|
||||
self.QueueActivity(new Infiltrate(order.TargetActor));
|
||||
}
|
||||
if (order.OrderString == "Disguise")
|
||||
{
|
||||
var target = order.TargetActor == self ? null : order.TargetActor;
|
||||
|
||||
if (target != null && target.IsInWorld)
|
||||
{
|
||||
var tooltip = target.TraitsImplementing<IToolTip>().FirstOrDefault();
|
||||
disguisedAsName = tooltip.Name();
|
||||
disguisedAsPlayer = tooltip.Owner();
|
||||
disguisedAsSprite = target.Trait<RenderSimple>().GetImage(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
disguisedAsName = null;
|
||||
disguisedAsPlayer = null;
|
||||
disguisedAsSprite = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
{
|
||||
return order.OrderString == "Disguise" ? "Attack" : null;
|
||||
}
|
||||
|
||||
public Color RadarColorOverride(Actor self)
|
||||
{
|
||||
if (!Disguised || self.World.LocalPlayer == null ||
|
||||
self.Owner.Stances[self.World.LocalPlayer] == Stance.Ally)
|
||||
return self.Owner.ColorRamp.GetColor(0);
|
||||
|
||||
return disguisedAsPlayer.ColorRamp.GetColor(0);
|
||||
}
|
||||
}
|
||||
|
||||
class IgnoresDisguiseInfo : TraitInfo<IgnoresDisguise> {}
|
||||
class IgnoresDisguise {}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,9 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (p == Self.Owner || (p.Stances[Self.Owner] == Stance.Ally && Self.Owner.Stances[p] == Stance.Ally))
|
||||
{
|
||||
total += Self.World.Queries.OwnedBy[p].Where(a => a.HasTrait<StrategicPoint>() && a.TraitOrDefault<StrategicPoint>().Critical == critical).Count();
|
||||
total += Self.World.ActorsWithTrait<StrategicPoint>()
|
||||
.Where(a => a.Actor.Owner == p)
|
||||
.Count(a => a.Trait.Critical == critical);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA
|
||||
self.Trait<RenderBuilding>().PlayCustomAnim(self, "active");
|
||||
|
||||
// Trigger screen desaturate effect
|
||||
foreach (var a in self.World.Queries.WithTrait<ChronoshiftPaletteEffect>())
|
||||
foreach (var a in self.World.ActorsWithTrait<ChronoshiftPaletteEffect>())
|
||||
a.Trait.Enable();
|
||||
|
||||
Sound.Play("chrono2.aud", Game.CellSize * order.TargetLocation);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user