Compare commits

...

86 Commits

Author SHA1 Message Date
Chris Forbes
708cdcd855 add CashTick to building refunds 2011-03-19 18:58:04 +13:00
Chris Forbes
0236da0a28 fix up ralint a bit 2011-03-19 18:53:50 +13:00
Chris Forbes
18e1de1d4b prefer to circle over something friendly than leave the map 2011-03-19 18:44:39 +13:00
Chris Forbes
73a34886ec oops 2011-03-19 18:44:38 +13:00
Chris Forbes
2d480c900f patch plane to circle after move 2011-03-19 18:44:37 +13:00
Chris Forbes
0cf022c87a rename FlyCircle -> FlyAttackLoop, for accuracy; new FlyCircleto fly a hold 2011-03-19 18:44:36 +13:00
Paul Chote
dea199400d Fix #630 - Muzzleflashes on cnc apache 2011-03-19 18:40:12 +13:00
Paul Chote
8e079c310a Give Oil Derricks a small sight range 2011-03-19 17:48:56 +13:00
Paul Chote
a5af4e85ce Tweak CashTick and Oil Derricks 2011-03-19 17:48:56 +13:00
Paul Chote
08158a6929 Allow the control group modifier key to be customized. 2011-03-19 17:48:56 +13:00
Paul Chote
6ba6940aad Support the meta key modifier 2011-03-19 17:48:56 +13:00
Chris Forbes
72e0b58912 fix csproj bogosity 2011-03-19 17:28:45 +13:00
Paul Chote
0d2a692d8d Fix bogus prereqs in ra. 2011-03-18 11:27:16 +13:00
Paul Chote
e043f38c00 Whoops, forgot to commit the changelog 2011-03-18 11:01:57 +13:00
alzeih
53f4337129 Don't change mods if the same one is selected in the dropdown 2011-03-18 10:49:29 +13:00
Paul Chote
eb69b697b1 Fix bogus handling of special keyboard characters everywhere else. Textfields now only accept valid characters, support right-delete. 2011-03-18 10:48:12 +13:00
Paul Chote
7d6d488176 Fix #549 - Shift + tab doesn't cycle build tabs backwards. 2011-03-18 09:44:28 +13:00
Paul Chote
c568759e49 Fix #595 - IDisposable crash. 2011-03-17 22:26:28 +13:00
Paul Chote
d05b979e53 Tweak cnc proc cashtick 2011-03-17 22:26:28 +13:00
Paul Chote
86e8c3974f Fix #611 - prereqs handled by traits. Make both cnc power plants valid for prereqs. 2011-03-17 22:26:28 +13:00
Paul Chote
6d1defc53e Use CashTick on harv unloading. 2011-03-17 22:24:17 +13:00
Paul Chote
ffac0221cf CashTick IEffect for Oil Derricks. 2011-03-17 22:24:17 +13:00
Chris Forbes
a3994df925 queries dies 2011-03-17 22:09:10 +13:00
Chris Forbes
caa52b2780 remove CachedView 2011-03-17 22:09:09 +13:00
Chris Forbes
149324ea92 remove most of the crap from queries 2011-03-17 22:09:08 +13:00
Chris Forbes
eba7641125 remove old Sell handler from Building 2011-03-17 22:08:53 +13:00
Chris Forbes
da36ce19e2 fix sellable compile fail 2011-03-17 20:09:43 +13:00
Chris Forbes
7e25947689 yaml changes for sellable 2011-03-17 19:14:20 +13:00
Chris Forbes
4eaa7d5cf2 split out Sellable into its own trait; yaml requires update 2011-03-17 19:14:17 +13:00
Chris Forbes
ff44e34d89 dont be detected by friendly detectors 2011-03-16 20:48:34 +13:00
Chris Forbes
8bef8d5a72 have spies appear a convincing color on radar too 2011-03-16 20:30:23 +13:00
Chris Forbes
048386e6fa add ExperienceInit (MapActor's 'Experience:' key, int) 2011-03-16 19:30:58 +13:00
Chris Forbes
f3dfc422ab fixed #635 2011-03-16 19:16:38 +13:00
Chris Forbes
3b89110202 fix some bogosity in MasterServerPinger (still not right) 2011-03-16 11:02:17 +13:00
Chris Forbes
73d27c822e add IgnoresDisguise; support it in AppearsHostileTo / AppearsFriendlyTo 2011-03-16 09:51:26 +13:00
Chris Forbes
a21deea60b spam the CellInfo messages into the debug log, not the chat 2011-03-15 12:18:08 +13:00
Chris Forbes
981e57bde8 some more overloads etc 2011-03-15 12:18:03 +13:00
Chris Forbes
c313920c7c include the utility in the core target, since the game needs it for package download now 2011-03-15 10:14:56 +13:00
Chris Forbes
cf9e81ea29 fix #645 2011-03-15 09:41:46 +13:00
Chris Forbes
4f79aca484 fix #643 2011-03-15 09:32:25 +13:00
Chris Forbes
5ad196acc3 fix #646 2011-03-15 09:30:24 +13:00
Chris Forbes
e66ebef73c some more bits for .gitignore 2011-03-15 09:29:19 +13:00
Paul Chote
c00d20e3c0 Update changelog 2011-03-13 21:22:13 +13:00
Paul Chote
795101aac9 Grenadiers explode on death 2011-03-13 21:21:16 +13:00
Paul Chote
0dd9a437b8 support power charge bars in cnc 2011-03-13 21:18:39 +13:00
Chris Forbes
febd92341f patched pchote's map 2011-03-13 15:54:33 +13:00
Chris Forbes
1368bc0731 missing project file change 2011-03-13 15:46:43 +13:00
alzeih
f4e4f987be RA - AppearsFriendlyTo and AppearsHostileTo actor extensions 2011-03-13 15:44:27 +13:00
alzeih
cf8cfdc42d SpyToolTip - Display tooltip of disguised unit to other players, and a modified one for the local player. 2011-03-13 14:14:32 +13:00
alzeih
26f1452930 text / text2 / text3 dies 2011-03-13 14:14:32 +13:00
alzeih
544befb553 Move disguise into Spy from RenderSpy 2011-03-13 14:14:32 +13:00
alzeih
b5efc97996 Fix #604 2011-03-13 12:26:37 +13:00
alzeih
22aa1308ce give GameServer some UsefulMods so we have the remote mod version in the ServerBrowser. 2011-03-13 12:26:27 +13:00
Chris Forbes
900e55900a fix boxes tooltip 'Tree' 2011-03-13 12:12:58 +13:00
Chris Forbes
116ef15fdb GotoNextBase dies in a fire; INotifyKeyPress dies 2011-03-13 12:12:57 +13:00
Paul Chote
3c41efea04 Check for GL extensions before we try to use things that may fail. 2011-03-13 02:46:16 +13:00
Paul Chote
c7d25bb991 Fix a crash with null textfields. 2011-03-13 02:32:48 +13:00
Chris Forbes
a33cca57ec fix a crash in perf graph 2011-03-13 02:27:32 +13:00
Chris Forbes
16eefe6280 increase strength of chrono effect 2011-03-13 00:44:31 +13:00
Chris Forbes
c9be0f44f4 spoilers: cursor dies 2011-03-13 00:39:37 +13:00
Chris Forbes
911ecb2ffa add missing copyright header to Mod.cs 2011-03-13 00:00:27 +13:00
Chris Forbes
56a8653bc6 #582 dont use water explosions for impacts ABOVE water 2011-03-12 23:41:28 +13:00
Chris Forbes
f58e9a2a99 do transport unload on 'f' 2011-03-12 23:34:59 +13:00
Chris Forbes
2eec1b2016 dont show yellow selection boxen 2011-03-12 23:34:58 +13:00
Paul Chote
d1dd3a64f8 Fix evw3 crash. 2011-03-12 23:32:41 +13:00
Chris Forbes
82dea40261 provide a way to grab the laggy clients 2011-03-12 22:55:40 +13:00
Chris Forbes
606873a09e fix warnings in Selectable.cs 2011-03-12 22:33:29 +13:00
Chris Forbes
fe90cbdab8 blah 2011-03-12 22:33:28 +13:00
Chris Forbes
8a14662bc1 remove unitinfluence debug, not needed anymore 2011-03-12 22:33:27 +13:00
Chris Forbes
cf6a1583c6 fix bogosity in SupportPowerManager 2011-03-12 22:33:26 +13:00
Chris Forbes
c3728ce674 blah 2011-03-12 22:33:25 +13:00
Chris Forbes
1e3f365cf2 move all the Game.Exts junk either down into FileFormats or into WorldUtils 2011-03-12 22:33:24 +13:00
Paul Chote
f4494d67b2 Kill chrome.xml. 2011-03-12 22:23:46 +13:00
Paul Chote
0cfbeab864 Export chrome.xml to yaml 2011-03-12 21:54:19 +13:00
Paul Chote
0084566478 Standalone radar widget for new sidebar 2011-03-12 18:58:42 +13:00
Paul Chote
631630fbff Custom button widget for new sidebar 2011-03-12 18:58:42 +13:00
Chris Forbes
19b2e3e521 #601 fixed -- dont require explicit port on Direct Connect 2011-03-12 18:52:35 +13:00
Chris Forbes
ed0ae15d49 fix interior boxes 2011-03-09 22:04:54 +13:00
Chris Forbes
fbc7200472 fix #572 crash when switching mods while playing music 2011-03-08 20:24:52 +13:00
Chris Forbes
0770524c05 add support power charge bar 2011-03-08 20:02:02 +13:00
Chris Forbes
6d36272134 #597 fix crash when spawning mapactors if there is no player in the slot. said actors are not spawned now. 2011-03-08 19:40:16 +13:00
Chris Forbes
e9a1c3f477 fix indent; make this work for Cg renderer too 2011-03-08 19:28:57 +13:00
Chris Forbes
16cb275a5f fix rendering of very large maps 2011-03-08 19:24:15 +13:00
Chris Forbes
682cfcd466 wire up BuildAnywhere so it actually works 2011-03-07 20:25:05 +13:00
Chris Forbes
14a2b68b7d add chrome + plumbing for BuildAnywhere devhack 2011-03-07 20:20:44 +13:00
Chris Forbes
7cf07f5765 make forcing evaluation of lazyness explicit 2011-03-07 19:53:39 +13:00
154 changed files with 2194 additions and 1392 deletions

5
.gitignore vendored
View File

@@ -50,3 +50,8 @@ OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.perspectivev3
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.mode1v3
*.config
*.resources
# other crap
Logs/
Replays/
settings.yaml

View File

@@ -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
View File

View File

@@ -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:

View File

@@ -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);
}
}

View File

@@ -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));
}
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -36,7 +36,12 @@ namespace OpenRA.FileFormats
p = null;
return value;
}
}
}
public void Force()
{
var ignored = Value;
}
}
public static class Lazy

View File

@@ -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 ) ); };
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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);
});
}
}
}

View File

@@ -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();

View File

@@ -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}
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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 ) );

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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 );
}

View File

@@ -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)

View File

@@ -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 )
{

View File

@@ -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()
{

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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" />

View File

@@ -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();

View File

@@ -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) });
}

View File

@@ -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;

View File

@@ -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]);
}
}
}
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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); }
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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 )

View File

@@ -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;
}

View File

@@ -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) =>

View File

@@ -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++;
}

View File

@@ -108,7 +108,7 @@ namespace OpenRA.Widgets
{
if (e.Event == KeyInputEvent.Down)
{
if (e.KeyChar == 27) // Escape
if (e.KeyName == "escape")
{
Stop();
return true;

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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);
});
}
}
}

View File

@@ -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

View File

@@ -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();

View 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;
}
}
}

View File

@@ -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)
{

View 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;
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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")

View File

@@ -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());
}
}
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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)))

View File

@@ -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

View File

@@ -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; }

View File

@@ -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>();
}
}
}

View File

@@ -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();
}

View 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());
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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))));
}
}
}

View File

@@ -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();
}
}

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);
});

View File

@@ -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;
}
}
}

View File

@@ -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! */

View 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;
}
}
}

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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">

View File

@@ -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 ) { }

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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.

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 {}
}

View File

@@ -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;

View File

@@ -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