Compare commits

..

178 Commits

Author SHA1 Message Date
Chris Forbes
ae29941d52 fix bogus target lines being drawn to 0,0 2010-10-08 21:04:31 +13:00
Caleb Anderson
e224fadbeb bandage to fix dogs not killing infantry in certain cases 2010-10-08 19:56:27 +13:00
Bob
1cccef5434 use a getter for Aircraft.Location 2010-10-08 19:54:56 +13:00
Bob
319da4c5ae add IHasLocation 2010-10-08 19:54:52 +13:00
Bob
94fc260293 remove setters on Mobile.{from,to}Cell. use SetLocation instead 2010-10-08 19:54:49 +13:00
Chris Forbes
e39917ca19 trim bbox for ftrk 2010-10-08 19:09:18 +13:00
Chris Forbes
318f496bf9 #202 fixed 2010-10-08 19:03:01 +13:00
Chris Forbes
ed8a155249 if c17 gets confused, just fly away 2010-10-08 18:57:14 +13:00
Chris Forbes
40ac5f7b6e FallsToEarth for cnc helis too 2010-10-08 18:45:52 +13:00
Chris Forbes
517754027e 8Inch and SubMissile minimum ranges temporarily disabled, until combat bugs are fixed 2010-10-08 18:33:38 +13:00
Caleb Anderson
ef4f478e10 Strip newlines from scrolling text. Frame-friendly update of scrolling text 2010-10-08 18:29:20 +13:00
Chris Forbes
92c30b89f8 FACT hp 1000 -> 1500 2010-10-08 18:26:25 +13:00
Chris Forbes
7331a9c4fb prevent aircraft shooting while landed 2010-10-08 18:25:26 +13:00
Chris Forbes
d2b9e150f1 add FallsToEarth for helicopters dying 2010-10-08 18:24:08 +13:00
Chris Forbes
8ba329f1be reduce cost of CA 3200 -> 2400 2010-10-08 18:03:34 +13:00
Chris Forbes
8868eab247 nerf hind chaingun from [x2] 40@3 to 20@10 2010-10-08 18:03:13 +13:00
Caleb Anderson
f12889e684 Sensible scroll cursor positions for cnc. RA seems to be totally different, didn't touch atm 2010-10-08 17:39:00 +13:00
Caleb Anderson
5c095bc174 more politic default motd text for cnc 2010-10-08 17:38:55 +13:00
Caleb Anderson
0c24a08436 sane default scroll speed 2010-10-08 17:38:48 +13:00
Chris Forbes
9762b540b0 fix bogus reverse-enter-transport (in ResolveOrder this time) 2010-10-08 17:38:07 +13:00
Paul Chote
fd34f2ba99 Fix #225 and some other uses of a.IsInWorld / a.IsDead() 2010-10-08 10:56:50 +13:00
Paul Chote
ad6481c8e8 Change master server url. Won't work until dns is set correctly. 2010-10-07 22:46:44 +13:00
Paul Chote
7426d47cd5 Fix some compile warnings 2010-10-07 22:46:44 +13:00
pdovy
761f62292f missing files from previous commit 2010-10-07 22:46:44 +13:00
unknown
63b8555bc9 Fix bug that prevented ground units from attacking landed aircraft. 2010-10-07 22:46:44 +13:00
Bob
3209da4a4a fixed PlaceBuilding and Chronosphere ordergenerators 2010-10-07 22:07:13 +13:00
Bob
aebef4f1c8 rename IIssueOrder2 -> IIssueOrder 2010-10-07 22:07:13 +13:00
Bob
d3244184c1 implement order targeter for everything else 2010-10-07 22:07:13 +13:00
Bob
39e62354a8 implement order targeter for passenger 2010-10-07 22:07:12 +13:00
Bob
f525c3808e implement order targeter for cargo 2010-10-07 22:07:12 +13:00
Bob
87a0b52ce5 more order targeters 2010-10-07 22:07:12 +13:00
Bob
4bc9e01516 use new orders system in various traits 2010-10-07 22:07:12 +13:00
Bob
711d05da98 use IIssueOrder2 in AttackBase 2010-10-07 22:07:12 +13:00
Bob
3d805ff40d added IIssueOrder2. most orders are broken, but Minelayer is fixed 2010-10-07 22:07:12 +13:00
Bob
0cd140849b fix some support powers 2010-10-07 22:07:12 +13:00
Bob
d6110b9ef0 add Sync.AssertUnsynced. use it in OrderGenerator.set 2010-10-07 22:07:12 +13:00
Bob
26d1db778e push the check-synchash-doesn't-change pattern into a utility fn. furthur reduce the number of uses on Game.world 2010-10-07 22:07:11 +13:00
Bob
f41aa474aa remove more uses of Game.world 2010-10-07 22:07:11 +13:00
Paul Chote
0002e80a19 Use new deps package, built on mono 2.8. Enable new sgen garbage collector. 2010-10-07 22:05:43 +13:00
Chris Forbes
759a52d86e fix build failure from bad merge in prev 2010-10-07 18:24:40 +13:00
max621
44fe0396bb Added shift+right click on build menu cancels 5 orders. Added ctrl+shift+right click on build menu cancels all orders 2010-10-07 18:23:26 +13:00
rasco
dd6d8d916e hackyAI 2010-10-07 07:42:40 +13:00
Chris Forbes
5af8f5e2d9 bots choose random colors 2010-10-07 07:41:14 +13:00
Caleb Anderson
c85503811c Clamp, scroll, scrollspeed, sliders
Reduced clamp duplication
Fixed scrolling speed issue
Modified scrollspeed slider to use a range
Fixed scrollspeed, volume, and sound sliders not showing current setting.
2010-10-06 20:53:56 +13:00
Chris Forbes
ab431fe9ee fix crash on warhead=null 2010-10-06 20:17:03 +13:00
Chris Forbes
7ec9958d47 hackyai should only attack humans 2010-10-06 20:04:36 +13:00
rasco
cfc74a6dee HackyAI: builds defense now. rally points are rechosen so units are more scattered in the base. builds only e1-3 and 1-3tnks. 2010-10-06 19:14:29 +13:00
Chris Forbes
cecdd73e08 destroy ore in all smudged cells 2010-10-06 18:37:32 +13:00
Chris Forbes
381e080b11 tweak nuke timing back 2010-10-06 18:32:33 +13:00
Chris Forbes
c6a047cb1a fix silent nukes 2010-10-06 18:29:05 +13:00
Chris Forbes
4c51733e04 actually add the cratenuke warhead 2010-10-06 18:25:07 +13:00
Chris Forbes
8f613b80e8 ban cloak crate on infantry 2010-10-06 18:16:09 +13:00
Chris Forbes
10de282daa add mechanism to exclude particular actor types from picking up any crate 2010-10-06 18:13:29 +13:00
Chris Forbes
915e123956 add minimum ranges for mig/yak/ca/msub/hind/v2rl/arty 2010-10-06 18:05:31 +13:00
Chris Forbes
8cb7a7b8ce add support for WeaponInfo.MinRange 2010-10-06 17:41:52 +13:00
Chris Forbes
ce5cf93077 prevent infantry going prone due to tib damage 2010-10-06 17:37:23 +13:00
Chris Forbes
1390bb7428 ra: reduce parabombs charge to 1min 2010-10-06 17:32:04 +13:00
Chris Forbes
3c5b136216 ra: reduce nuke charge time 13min -> 9 min 2010-10-06 17:29:45 +13:00
Chris Forbes
66785e606a ra: brik hp 1500 => 1000 2010-10-06 17:23:12 +13:00
Chris Forbes
e2239fa50c #215 obli misses moving units fixed 2010-10-06 17:22:11 +13:00
Chris Forbes
7f7712aa64 #203 dogs eating walls fixed 2010-10-06 17:20:20 +13:00
Chris Forbes
b1605e115a #206 badr/badr.bomber appear in tooltips 2010-10-06 17:15:52 +13:00
Chris Forbes
69b2da86be RA: +20% 4tnk HP 2010-10-06 17:13:39 +13:00
Chris Forbes
18e965e5aa fix desync on destroying ore storage buildings 2010-10-06 10:59:46 +13:00
Chris Forbes
24f0c28f56 fix massive player/client confusion after people drop 2010-10-06 10:59:45 +13:00
Paul Chote
25af51b4ac Prevent a race condition 2010-10-05 19:00:36 +13:00
Paul Chote
ecd7064cc3 Add an example mod that adds a soviet supply truck 2010-10-05 18:48:00 +13:00
Chris Forbes
477a21e782 fix 'minv/minp' showing up in tooltips 2010-10-05 17:58:30 +13:00
Chris Forbes
899d9af62b CNC: +25% HP on FACT/MCV 2010-10-05 17:58:29 +13:00
Paul Chote
17eca983ef Fix wall sell exploit 2010-10-05 17:56:30 +13:00
max621
2fc219ecd5 Fixed auto attack not working properly due to code expecting 'Idle' activity but most units use 'IdleAnimation' in RA mod 2010-10-05 17:45:29 +13:00
Chris Forbes
49a645cd2d fix ubuntu-64 support (Tao.FreeType was quite bogus.) 2010-10-05 17:42:13 +13:00
Matthew
7cb8da411d Updated git url to point to new upstream location. 2010-10-05 17:42:13 +13:00
Matthew
4bcdf3cf11 Netcode discussion from Etherpad. 2010-10-05 17:36:03 +13:00
Matthew
1b525ff809 Export FTP server and added username/password to VERSION file upload. 2010-10-05 17:36:03 +13:00
Caleb Anderson
cdec3fce26 Don't tell all players about my yaks 2010-10-05 17:25:30 +13:00
Caleb Anderson
7bdf6a953f New slider Range parameter. Palette modifications. Potential crash fix. Clamp function.
Range parameter added to slider. Supports returning a range of values
rather than just 0-1. Allows you to not have to post process the offset.
Modified palette selector to not have full range, which was causing
blown out units.
Introduced exension method Clamp<T>(min, max)
Fixed crash deserializing out of bound color value using above
extension.
2010-10-05 17:25:25 +13:00
Chris Forbes
06b20c8ba5 fix blatant wrongness in parallel builds 2010-10-02 20:55:43 +13:00
Paul Chote
9b484b53ec Show mod info in server browser 2010-10-02 20:37:25 +13:00
Paul Chote
9620b4ed46 Add mod metadata, and filter valid mods on startup. 2010-10-02 20:37:22 +13:00
Caleb Anderson
d8908c44d0 Nicer default ticker text 2010-10-02 01:13:55 -05:00
Caleb Anderson
cfe705531a Async motd grab. Client and server version in MasterServerQuery 2010-10-02 01:13:53 -05:00
Caleb Anderson
9a2fd38ab6 MOTD ticker. ScrollingText Widget 2010-10-02 01:13:51 -05:00
Chris Forbes
911e7f62de fix retardedly putting everyone in slot 0. 2010-10-02 18:33:29 +13:00
Chris Forbes
403b81bdc9 apply the balance stick to BIKE 2010-10-02 15:49:42 +13:00
Chris Forbes
a0714b00b3 a bit of cleanup 2010-10-02 15:49:42 +13:00
Chris Forbes
d5239ee77a add tib and spawns to new map 2010-10-02 15:49:41 +13:00
Chris Forbes
03ec97f302 unfinished 2v2 cnc map 2010-10-02 15:49:41 +13:00
Chris Forbes
3255f95ee9 ffs, more paths 2010-10-02 15:35:48 +13:00
Chris Forbes
4c8fd5e73d oops 2010-10-02 15:30:16 +13:00
Chris Forbes
7179ef0f45 fix packaging script 2010-10-02 15:19:14 +13:00
Alli
6d5918b11d Remove compiler warnings 2010-10-02 14:30:54 +13:00
Matthew Bowra-Dean
81c484d1c9 Fixed debian package prereqs 2010-10-02 13:28:22 +13:00
Chris Forbes
de1044c24c hack around imagelist deserialization being completely busted across platforms 2010-10-02 13:22:54 +13:00
Paul Chote
e4c31939d9 Save all settings to settings.yaml, not just non-defaults. 2010-10-02 12:15:15 +13:00
Paul Chote
7f48d6796e Fix scroll ticks 2010-10-02 12:01:11 +13:00
Matthew Bowra-Dean
4fd77aec8e Only add 'Latest:' text if query succeeds. 2010-10-02 11:39:56 +13:00
Matthew Bowra-Dean
92fece01de Added latest version information underneath current version in main menu. 2010-10-02 11:39:54 +13:00
geckosoft
d8d987f844 Fixed Settings menu issue (overlapping text) 2010-10-02 11:38:42 +13:00
unknown
de429a4c62 Added new setting : Scroll Speed (added to cnc & ra) 2010-10-02 11:38:39 +13:00
Chris Forbes
c0ca35a4ff fix AI jam in cnc 2010-10-02 11:33:50 +13:00
Chris Forbes
1bff8559fb pull HasAdequatePower out into a function 2010-10-02 11:33:47 +13:00
Chris Forbes
de98274165 fix #184 crashes while placing minefield 2010-10-02 11:33:04 +13:00
Chris Forbes
59e2228b2a shader fallback path for cg-2.1, which misinterprets 'latest' 2010-10-02 11:32:14 +13:00
geckosoft
96d1408d45 Fixed crash bug #197 2010-10-02 11:31:55 +13:00
Paul Chote
ff45ae2d16 Fix direct connect in cnc 2010-10-02 11:31:19 +13:00
Chris Forbes
47950c9113 Revert "remove setters on Mobile.{from,to}Cell. use SetLocation instead"
This reverts commit 911db3feb1.
2010-09-28 07:45:14 +13:00
Chris Forbes
f402ec7898 Revert "add IHasLocation"
This reverts commit 699b4b1154.
2010-09-28 07:43:49 +13:00
Chris Forbes
a3c0448e15 fix broken mac packaging script 2010-09-27 21:44:23 +13:00
Bob
699b4b1154 add IHasLocation 2010-09-26 18:17:23 +12:00
Bob
911db3feb1 remove setters on Mobile.{from,to}Cell. use SetLocation instead 2010-09-26 16:46:22 +12:00
Paul Chote
c790db8e84 Fix and bulletproof osx packaging script; cleanup some obsolete .gitignore entries 2010-09-26 10:18:22 +13:00
Bob
d6dd392028 use Invariant culture for float parsing (workaround a mono bug) 2010-09-26 09:11:26 +12:00
Bob
636b2a8ea7 fix Direct Connect window 2010-09-25 19:26:02 +12:00
Chris Forbes
959d3f8bd7 fix crash in giving a harv DeliverOre order after its proc has died, but it hasnt noticed yet 2010-09-25 07:34:51 +12:00
Matthew
193cb929f1 Fixing error with Windows package script launching 2010-09-24 22:12:26 +12:00
Chris Forbes
f93e270fe4 reduce v2 range and damage slightly 2010-09-24 21:49:26 +12:00
Chris Forbes
f19953c39a nerf ftrk heavily vs most ground, and reduce hp from 300 to 120 2010-09-24 21:44:57 +12:00
Matthew
59d5ce1bc8 +x permissions for checkout-and-build.sh 2010-09-24 20:42:29 +12:00
Matthew
43cf7cd074 Yet another packaging script. 2010-09-24 20:42:26 +12:00
Chris Forbes
aba76f4b50 don't look up resource type every cell for ore, too 2010-09-24 20:40:56 +12:00
Bob
8021fc3b20 Deduplicate shroud rendering code 2010-09-24 18:11:11 +12:00
Bob
7bf4cb85fa fix perf in ShroudRenderer 2010-09-24 18:11:08 +12:00
Bob
6dd03bb339 bugfix in ResourceLayer 2010-09-24 18:11:06 +12:00
Bob
14e517cab5 Autoflush renderer. Sprite.DrawAt convenience function. 2010-09-24 18:11:03 +12:00
Bob
cdcfeb6276 render perf improvement: BufferSubData, and don't use the same buffer back-to-back 2010-09-24 18:11:00 +12:00
Matthew
c77c63a380 Fix #130.
Windows installer now checks version of OpenAL32.dll and downloads and updates if necessary.
2010-09-24 16:40:55 +12:00
Matthew
9921fe8fad Linux package parallelisation. 2010-09-24 16:40:55 +12:00
Matthew
f848c5d7d4 Parallel building of packages. 2010-09-24 16:40:55 +12:00
Matthew
62c47e3b12 Reordered packaging platforms due to popular demand. 2010-09-24 16:40:55 +12:00
Matthew
094986d066 Tag prefixes change upload location for packages. 2010-09-24 16:40:55 +12:00
Chris Forbes
d87e02ab41 more tweaks, make DD a detector again (wtf?) 2010-09-23 22:23:39 +12:00
Chris Forbes
3f415a8fdf tweak torps more 2010-09-23 22:09:56 +12:00
Chris Forbes
846371cf3e homing torps, bubble trail 2010-09-23 22:09:56 +12:00
Chris Forbes
45c77e64ee fix various desyncs when using cheats 2010-09-23 22:09:55 +12:00
Bob
66493031c8 fix crash with idle units and pathdebug 2010-09-23 21:06:44 +12:00
Bob
384b26db60 fix fieldloader bug caused by foreach language-bug 2010-09-23 17:24:06 +12:00
Bob
d66dbeb312 removing unused stuff from TraitsInterfaces 2010-09-23 15:43:34 +12:00
Chris Forbes
ba9611f544 un-FP Building.cs power stuff 2010-09-22 21:43:04 +12:00
Chris Forbes
b6e56560d4 fix a crash in RepairIndicator with a dead building 2010-09-22 20:48:45 +12:00
Chris Forbes
1f047d439f back out editor icon hack -- it breaks the packaged editor on windows 2010-09-22 19:26:09 +12:00
Chris Forbes
5233ae4770 remove spam from Util.GetFacing 2010-09-22 19:21:22 +12:00
Chris Forbes
562e07264a remove lots of debug spam 2010-09-22 19:19:18 +12:00
Chris Forbes
4dab4ed73f reenable crates 2010-09-22 19:15:45 +12:00
Chris Forbes
a97ddffa53 fix cnc movement (argh) 2010-09-22 19:00:07 +12:00
Bob
8e589e3c16 fix infantry anims 2010-09-22 13:32:58 +12:00
Bob
96f72ce842 new map in ra_perf 2010-09-22 13:08:02 +12:00
Bob
d8de477edb fix IdleAnimation. add IsAttacking to AttackBase 2010-09-22 12:21:49 +12:00
Bob
694fb6831a fix target line on Move that has not yet calculated path 2010-09-22 12:03:45 +12:00
Bob
c16a515224 make more activities cancelable. remove many uses of CurrentActivity is T 2010-09-22 11:53:58 +12:00
Bob
e2eae7973b removing warning 2010-09-22 11:18:47 +12:00
Bob
9e3c938706 removing cancelable from Move. remove unnecessary qualified names from Production 2010-09-22 10:46:54 +12:00
Bob
ef665df2e9 refactor activity queueing 2010-09-22 10:13:13 +12:00
Bob
271a3eea8d fix harv 2010-09-22 08:49:56 +12:00
Bob
2f6315b816 make the pathfinder use integers 2010-09-22 08:04:52 +12:00
Bob
ac8d408ba7 allow queuing non-buildings while the queue is ready 2010-09-22 08:02:20 +12:00
Bob
0fdd49c96a MovePart becomes an Activity 2010-09-22 08:02:17 +12:00
Bob
e390cf8ab0 fix real-ra map importer when map isn't in game root 2010-09-22 08:02:15 +12:00
Bob
64d700cd70 make c&c work too 2010-09-22 08:02:12 +12:00
Bob
d3db9d3710 yes, i do want += 2010-09-22 08:02:09 +12:00
Bob
9eb05a43f9 show perf widget 2010-09-22 08:02:06 +12:00
Bob
3165ec5359 create widgets on demand 2010-09-22 08:02:03 +12:00
Bob
f4699132d6 made OpenWindow and CloseWindow static 2010-09-22 08:02:00 +12:00
Bob
086bdfb4bd new object creation logic 2010-09-22 08:01:57 +12:00
Chris Forbes
61fd12c7da oops; prev didnt run 2010-09-22 07:19:18 +12:00
Chris Forbes
9979209c34 more useful debug, less debug 2010-09-21 22:42:31 +12:00
Chris Forbes
b0c06d4cd9 force consistent conversion to float in a few places 2010-09-21 22:08:40 +12:00
Chris Forbes
3a617f8934 sync the last path generated, to try and catch this MUCH earlier 2010-09-21 21:43:16 +12:00
Chris Forbes
b35a7d9f8d stacktrace on set_Facing too 2010-09-21 21:06:37 +12:00
Chris Forbes
67fa079658 more debug 2010-09-21 21:05:28 +12:00
Chris Forbes
c9edbd8a80 report the tick in debug 2010-09-21 18:10:05 +12:00
Chris Forbes
4b49bf03dc reset local tick # at gamestart 2010-09-21 18:05:54 +12:00
Chris Forbes
6cfad6f2ab stacktrace in SetLocation 2010-09-20 22:52:28 +12:00
Chris Forbes
c0c4e7299b log changes to synced parameters in Mobile 2010-09-20 22:07:16 +12:00
Bob
afda1647fd moved more traits from engine into mods 2010-09-20 21:17:50 +12:00
Bob
aff6889995 moved traits from engine into mod 2010-09-20 20:58:42 +12:00
Bob
65515d54af fix crash where harv and linked proc get destroyed by the same bullet 2010-09-20 20:58:39 +12:00
Chris Forbes
c5b7c43d23 add pathspam in debug 2010-09-20 19:06:43 +12:00
265 changed files with 5923 additions and 4207 deletions

11
.gitignore vendored
View File

@@ -12,20 +12,11 @@ mods/*/*.dll
# Red Alert binary files
mods/*/packages/*.[mM][iI][xX]
# Crap generated by OpenRa
sheet-*.png
log.txt
*.rep
#binary stuff
/*.dll
*.pdb
*.mdb
*.exe
OpenRA
OpenRA.app
*.vqa
# backup files by various editors
*~
@@ -33,10 +24,8 @@ OpenRA.app
# dependency DLLs (different for every platform!)
cg.dll
cgGL.dll
glfw.dll
/OpenRa.Gl.dll
settings.ini
#monodevelop
*.pidb

View File

@@ -36,9 +36,6 @@ namespace OpenRA.Editor
Rules.LoadRules(Game.modData.Manifest, new Map());
surface1.AfterChange += MakeDirty;
string path = Directory.GetCurrentDirectory();
Icon = new Icon(path + Path.DirectorySeparatorChar + "OpenRA.Editor" + Path.DirectorySeparatorChar + "OpenRA.Editor.Icon.ico");
}
void MakeDirty() { dirty = true; }
@@ -349,9 +346,11 @@ namespace OpenRA.Editor
void ImportLegacyMapClicked(object sender, EventArgs e)
{
var currentDirectory = Directory.GetCurrentDirectory();
using (var ofd = new OpenFileDialog { Filter = "Legacy maps (*.ini;*.mpr)|*.ini;*.mpr" })
if (DialogResult.OK == ofd.ShowDialog())
{
Directory.SetCurrentDirectory( currentDirectory );
/* massive hack: we should be able to call NewMap() with the imported Map object,
* but something's not right internally in it, unless loaded via the real maploader */

View File

@@ -17,6 +17,7 @@ using OpenRA;
using OpenRA.FileFormats;
using OpenRA.Traits;
using System.Drawing;
using System.Globalization;
namespace OpenRA.Editor
{
@@ -401,7 +402,7 @@ namespace OpenRA.Editor
{
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new OwnerInit(parts[0]),
new HealthInit(float.Parse(parts[2])/256),
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
new ActorStanceInit(stance),
};

View File

@@ -52,11 +52,13 @@
this.txtTitle = new System.Windows.Forms.TextBox();
this.lblMapName = new System.Windows.Forms.Label();
this.lblMinimap = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pbMinimap)).BeginInit();
this.pnlBottom.SuspendLayout();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// MapList
@@ -85,9 +87,9 @@
//
// MapIconsList
//
this.MapIconsList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("MapIconsList.ImageStream")));
this.MapIconsList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
this.MapIconsList.ImageSize = new System.Drawing.Size(24, 24);
this.MapIconsList.TransparentColor = System.Drawing.Color.Transparent;
this.MapIconsList.Images.SetKeyName(0, "mapicon");
//
// btnCancel
//
@@ -141,6 +143,7 @@
//
// pnlBottom
//
this.pnlBottom.Controls.Add(this.pictureBox1);
this.pnlBottom.Controls.Add(this.txtPathOut);
this.pnlBottom.Controls.Add(this.lblPathOut);
this.pnlBottom.Controls.Add(this.lblPath);
@@ -301,6 +304,16 @@
this.lblMinimap.TabIndex = 6;
this.lblMinimap.Text = "Map preview:";
//
// pictureBox1
//
this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
this.pictureBox1.Location = new System.Drawing.Point(336, -9);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(54, 35);
this.pictureBox1.TabIndex = 7;
this.pictureBox1.TabStop = false;
this.pictureBox1.Visible = false;
//
// MapSelect
//
this.AcceptButton = this.btnOk;
@@ -327,6 +340,7 @@
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.Panel2.PerformLayout();
this.splitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
@@ -356,5 +370,6 @@
public System.Windows.Forms.Label lblPathOut;
public System.Windows.Forms.Label lblPath;
public System.Windows.Forms.TextBox txtPathOut;
private System.Windows.Forms.PictureBox pictureBox1;
}
}

View File

@@ -1,13 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using OpenRA.FileFormats;
using System.Windows.Forms;
using System.IO;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.Graphics;
namespace OpenRA.Editor
@@ -19,11 +13,11 @@ namespace OpenRA.Editor
public MapSelect()
{
InitializeComponent();
MapIconsList.Images.Add(pictureBox1.Image);
}
private void MapSelect_Load(object sender, EventArgs e)
void MapSelect_Load(object sender, EventArgs e)
{
DirectoryInfo directory = new DirectoryInfo(MapFolderPath);
DirectoryInfo[] directories = directory.GetDirectories();
MapList.Items.Clear();
@@ -33,20 +27,14 @@ namespace OpenRA.Editor
ListViewItem map1 = new ListViewItem(subDirectory.Name);
map1.ImageIndex = 0;
MapList.Items.Add(map1);
}
if (txtNew.Text == "unnamed")
{
//dumb indian code
}
else
{
// hack
if (txtNew.Text != "unnamed")
MapList.Items[0].Selected = true;
}
}
private void MapList_SelectedIndexChanged(object sender, EventArgs e)
void MapList_SelectedIndexChanged(object sender, EventArgs e)
{
if (MapList.SelectedItems.Count == 1)
{
@@ -69,7 +57,7 @@ namespace OpenRA.Editor
}
}
private void txtPathOut_TextChanged(object sender, EventArgs e)
void txtPathOut_TextChanged(object sender, EventArgs e)
{
MapFolderPath = txtPathOut.Text;
}

View File

@@ -120,73 +120,58 @@
<metadata name="MapIconsList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="MapIconsList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABW
DgAAAk1TRnQBSQFMAwEBAAEoAQABKAEAARgBAAEYAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABYAMA
ARgDAAEBAQABIAYAASQhAAEBAx8BLAM/AW8DSQGJAzYBWQMYASIDAQECDAADHQEqA0gBhQNCAXYDDwEU
AwEBAgMNARIDMwFSA0MBdwNRAacDDwEU/wAwAAEBAwMBBAM0BFQBwgFlAVMBUgH0AV4CWAHYA0oBjQMW
AR4DAgEDAwABAQMCAQMDGgElA00BlAEIAQkBJgH9A1ABpAM1AVcDQQFzA1MBugJDAVMB4wJTAVQBsgMA
AQH/ADAAAQEDDAEQA0IBdAFVAVQBUQHYAZkBiAGBAf8BoAGMAYUB/wF8AXABZQH4AzoBYQMKAQ4DCgEN
Ax0BKgM/AW0DVAG7ARkCGgH5AQABBQG/Af8BFwEbAUcB+QE5AUYBSwHrAQABBQFEAf8CCAFOAf0DDQER
/wAxAAMDAQQDHQEpA1ABpAFdAVMBUQHtAZsBiwGDAf8BnAGMAYQB/wGWAYQBdwH/AVsBWgFYAdgDMwFT
AzQBVANPAZ0CUwFSAdMCTAFOAfMBMAGeAbsB/wEUAXMBqwH/ARQBdQG/Af8BEAFmAbYB/wEXAY0BwgH/
AUgBYQFpAeEDAQEC/wAwAAEBAwkBDAMwAUwBVgJVAcMBewFqAWAB+gGoAZkBjwH/AZMBhAF3Af8BjAF3
AXAB/wGHAXEBbAH/A1YBvgNTAbwBTAFIAUYB5QF2AVsBUgH6AYMBbQFlAf8BUQFIAUcB/wEOAUsBpAH/
AQMBGgG4Af8BDQFRAZUB/wEZAZUBwAH/AUABagGBAesDMwFSAw0BEgMCAQP/ACUAAwEBAgMYASEDSwGP
A1EB3AGbAY4BhQH9AaEBkQGJAf8BhwFzAWsB/wGBAW4BZQH/AXUBZwFgAf8BUwFKAUMB/QFHAT4BOwH8
AZYBhgF5Af8BowGSAYoB/wFTAUoBUwH/AQMBGAHzAf8BEgFgAaYB/wEVAXYBlQH/AS8B/QH+Af8BBwEy
AZQB/wEVAXoByAH/AgABVAH/A00BlAMZASP/ACUAAwYBCAMtAUYDUwG8AWoBZQFiAfQBqgGbAZEB/wGJ
AXQBbQH/AYwBdwFuAf8BmgGJAYEB/wGLAXcBbwH/AXUBZQFeAf8BhgFxAWkB/wGVAYYBegH/AUEBPAFK
Af8BEwEfAYgB/wEKAREBrgH/ARwBegGVAf8BKgHfAeIB/wEOAVMBdwH/AQkBOQG8Af8BGQGBAaoB/wEK
ARIBqQH/ASABJQFSAfcDUQGg/wAlAAMQARUDQQFyA08B1gGTAYQBcgH9AZoBiQGDAf8BjwGAAXMB/wGW
AYYBeAH/AZ8BjQGEAf8BlgGFAXkB/wGUAYQBdwH/AZQBgwF3Af8BlwGHAYAB/wFqAV8BXAH/AWMBVwFW
Af8BYAFVAVMB/wFTAVcBWAH/ASIBYwGaAf8BDQFLAZ0B/wEgAY4BsAH/AUwBnAGvAf8BaAGaAa4B/wE7
AUsBWgH+A1ABn/8AJQADGAEiA00BlQF8AXUBbwH8AagBmAGOAf8BkQGBAXUB/wGNAXcBcAH/AZoBiQGB
Af8BkwGDAXYB/wGZAYgBgQH/AZwBiwGDAf8BlQGGAXgB/wGWAYYBeQH/AaABjwGHAf8BlgGFAXgB/wF2
AW8BbAH/AUwBbQGBAf8BHgE7AV0B/wEdAZ4BhAH/AVMBlwGpAf8BhgHFAd8B/wGIAb4B1wH/AUUBXwFi
AfsDQQFz/wAlAAMYASIDTQGVAZ0BjwGGAf8BmwGLAYMB/wGGAXEBagH/AYUBbwFoAf8BiAFzAWwB/wGJ
AXQBbAH/AZABdwFvAf8BlQGEAXcB/wGWAYUBeAH/AZ8BjwGGAf8BmQGLAYQB/wFtAYABhgH/AVYBkwGw
Af8BWgGmAccB/wFMAYMBpAH/AQUBFgGgAf8BYwGaAbAB/wGCAb8B2QH/AXEBrQHIAf8BXQFpAXIB3gMq
AUD/ACEAAwMBBAMmATgDUAGjAZoBjAGEAf8BpwGWAY4B/wGXAYYBegH/AZQBggF2Af8BlAGDAXcB/wGW
AYUBeAH/AZIBeQFyAf8BjwF5AXIB/wGVAYQBeAH/AY8BdgFrAf8BcAGAAYcB/wFaAZcBswH/AU8BmgHC
Af8BZQG1AdQB/wFlAaQBvgH/AR4BKgE1Af8BeAG6AdMB/wGAAbsB1QH/AYEBvwHaAf8BVQFWAVkBtQMP
ART/ACEAAwoBDQNBAXMDUgHPAasBmgGRAf8BmgGJAYIB/wGOAXgBcQH/AZEBgQF1Af8BlQGEAXcB/wGY
AYgBgAH/AYsBdQFuAf8BkQF6AXMB/wF4AW4BagH/AW8BrwHIAf8BWQGoAc0B/wFZAasBzAH/AVUBpgHJ
Af8BdQHDAeAB/wF6AcIB3wH/AYMBwAHbAf8BggHBAd0B/wFvAa4ByAH/AYsBvwHbAf8DSAGGAwUBB/8A
IQADHgErA1EBoAFSAVABTQHtAYMBbwFoAf8BgwFuAWcB/wGBAWwBZQH/AYEBbQFmAf8BiAFzAWsB/wGH
AXIBawH/AZQBhAF4Af8BhQF2AXMB/wFUAWwBgwH/AU0BhAGmAf8BZgGwAdAB/wFdAaoBywH/AWEBsQHR
Af8BdgG/Ad0B/wGFAcgB4wH/AYEBxAHfAf8BiAHHAeIB/wF3AbYB0QH/AW0BngG2Af8DPgFrAwIBA/8A
IQADOAFcA1UByAFrAlwB+AGRAYABdAH/AZgBiAGAAf8BlQGEAXgB/wGNAXcBcAH/AZUBhAF4Af8BmAGH
AYAB/wGTAYMBdwH/AWgBgAGLAf8BVgGQAbEB/wE3AUoBagH/AWMBqQHKAf8BYAGuAc8B/wFhAawBzAH/
AXYBvwHcAf8BiQHMAecB/wGDAcYB4gH/AYUBxQHgAf8BhwHDAd4B/wFIAYMBmwH/AzwBaAMEAQX/ACEA
A0kBiQFXAVYBVQHiAaQBkwGKAf8BrAGcAZMB/wGlAZUBjAH/AZYBhgF5Af8BkAF5AXQB/wGZAYgBgQH/
AaIBkQGJAf8BbgFdAVUB/wFkAZUBqwH/AWgBtQHVAf8BcgHBAd0B/wF0AbsB2wH/AV4BrAHOAf8BXwGt
AcwB/wF4AcMB4AH/AYgBywHmAf8BhQHGAeQB/wGDAcYB4gH/AYcBvwHdAf8BQwFVAWkB7gMbASb/ACUA
A08BpQFiAlgB7wGjAZMBigH/AZgBhwGAAf8BnwGOAYYB/wGdAYwBhAH/AZABeQFzAf8BiAFyAWsB/wGI
AXYBbwH/AWoBhQGPAf8BaAGwAdAB/wFvAbwB2gH/AWYBtgHWAf8BXwGxAdAB/wFdAa8B0AH/AXEBvQHa
Af8BcAG7AdoB/wGAAcQB3wH/AY8BzQHpAf8BigHJAeUB/wFbAZcBrAH9A0QBeQMAAQH/ACUAA1MBsQFs
Al8B8wGjAZIBigH/AZUBgwF4Af8BlAGCAXcB/wGUAYUBdwH/AYQBiwGNAf8BWwFzAYYB/wFcAYcBnQH/
AWEBrwHSAf8BbwG7AdoB/wF3AcEB3gH/AWwBuQHXAf8BYQGzAdIB/wFpAbkB1gH/AYABxQHhAf8BeAHC
Ad8B/wGAAcUB4QH/AYUBxAHhAf8BiQHGAeIB/wFSAXMBhAHzAzEBTv8AKQADUQHHAXsBcQFnAfgBqwGb
AZIB/wGQAYABdQH/AYQBbwFmAf8BcgGaAasB/wFiAasBzwH/AWQBsgHTAf8BbQG8AdoB/wFrAbgB1QH/
AXEBvgHbAf8BdgG/Ad0B/wFwAb4B2wH/AWgBuQHWAf8BgAHHAeEB/wGJAcsB5AH/AYoBzAHnAf8BjQHR
AewB/wGFAckB5gH/AW0BswHUAf8DTgGYAzABTAMAAQEDAAEB/wAhAAM+AWwBYgFfAV4ByQGJAYIBfAH1
AaQBkwGLAf8BhgGeAakB/wFnAa8B0gH/AXgBxAHgAf8BdgHCAd4B/wF2AcIB3gH/AXEBvwHbAf8BcwG8
AdoB/wFyAbsB2AH/AXQBuwHZAf8BdAG/Ad0B/wFhAZ0BwwH/AUEBYwGUAf8BbQGnAcgB/wGHAcQB4AH/
AYgBzQHpAf8BXwFxAXkB4AMsAUQDBwEJAwQBBgMAAQH/ACEAAwQBBQMZASMDNAFUA0oBiQFYAlsBwQFh
AXIBeQHiAW4BlwGoAfUBfQG0Ac8B/gGAAcUB4gH/AXIBvAHaAf8BcQG8AdoB/wFwAbsB2AH/AXUBvAHZ
Af8BjgHPAesB/wFtAa8B0gH/AU8BdQGkAf8BbAGrAc0B/wFuAa8BzwH/AY8BygHnAf8BWAFjAWYB0QMi
ATH/AD0AAwEBAgMJAQwDGgElA0IBdgFSAVwBZQHqAYEBxAHgAf4BigHHAeQB/wF5AcAB3QH/AYoBxgHi
Af8BlgHUAe4B/wF5AbgB1wH/AWEBoQHIAf8BaQGmAcwB/wFZAZIBvwH/AX8BwwHdAf4CRgFHAYEDAwEE
/wBJAAMCAQMDEAEWAzIBUANKAY0DUAGdA1IBoQFmAXUBewHgAXIBrwHFAf0BYAGXAb4B/wFgAZQBwAH/
AW8BqAHOAf8BQAF5AaoB/wM1AVYDAAEB/wBVAAMCAQMDBgEIAwoBDQMoAT0DQAFxAU8CUQGcAVsBYgFo
AdYBZQF/AZMB8gFKAX0BoQH8AyABL/8AcAABAQMIAQsDJAE2A0YBgQMDAQT/ADEAAUIBTQE+BwABPgMA
ASgDAAFgAwABGAMAAQEBAAEBBQABIAEBFgAD/wEAAeABOAEBCQABwAEAAQEJAAHAAQABAwkAAcABAAED
CQABgAsAAYALAAGACwABgAsAAYALAAGAPQABAQsAAQELAAEDIwABBwkAAfABAAEHCQAB/gEAAQcJAAH/
AcABDwkAAf8B/gEPCQAL
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAArjSURBVFhHrVcJUFRXFmVpkE0Wg0ZEMoIBl8RodGSMmVES
R0NiChVxCyIIAmFfhe6maeh9AZodZHFpUFQWcQmKisiuLKLEKFFEcIuljtZMYmI5Uc/c14EZYyapmpq8
qlP/9/+/373v3HPu+19P7/cf+jSlEWHCOEuzZfNn2Yvo3Pj3D/PTjCwYAwtgyeFwFk163Tos2tvtWJZw
zeUjmYFP6vL9fhw31vRPI8/9LnmMrtCWZhtPcJ7hbC/W8DwfnS0LR0t5NKoFazHcqsaprE3YGbMQLrYW
W/7fBAxogjGEd5wcXuPK4jxa60qD75VrfIbKMrYMD7VlPX/Ul49rp8RoyPbFIaEnhpuU6NRGoVa2HKuX
zEj/X8vAVmlIsDY2Nna2sjBd+ee5b7Yq4tfgfm8a7pxNw60OFa6e4uFmhxr/uFSIexfz0VsZh7PaIJzb
F42u8hAcV2/ANz3KF8Hub52kucb+Fv+jAccbm5quWOfxYX5y6Mcnq/IDh1oreX/vOcx9drdbjTudUgye
Tsb1piT0H4/DACUw0JiEh33ZePhlFi7UxOCLtI1o2x6IW2cUqM/egLtdediV9MnjSTYm60bE+Ys8rMzN
zd1c3/vLgVRV3lN1XjkqyzNoNaEUjIvrLXwMtQsw1JqEy/UxuHg0DJcp+KXj8bh0IobOucSGDA8vpqE6
+VNINixBU0kQbp5JJ8jxDSXdeyAE5arlAxTZ/BfRra2tS8Tqwh9L9tQhq6gSabm7odLkoP8oF90V/rjR
LsRgExc32oS40ZFCiQgw2Mgj+gW42pBI4OPSsUh6Jgn1mX4ojXJH865IXDzCx50uDe6fV+P8oQQ4Tx6r
pOATmVteKgdjXu/Mhk1h328rO4TMwn3gp2YhmquEX7gAfYfjcb4qGH0HQ3D5WAiunU7ApfpofH0ymhIS
UwkSqQRb6VoYvm6IZvXG7W4VBVbjwQU1/tanIQZkGDqtwOmSjzHXxXaLsZnZpy85QpdAnfunax/mllRD
ma2FQJyHxORMJAqzwBVpUJgtRLF8E7bxlqKjzA991QEYaIijgFwMt6VggJK60hCFr46F4sqprbjbLaf6
S0icIh1rwy1i3OvNQff+GEgj3r87/c1JLIGfjX1LP/F6KJDlIy1vN4SyQohVRdAU7IVIXQxuSiZ8/OOw
JYyP8EiqfV04Lh2JoHIwMSbiwoFgtO1ah97aTSTMKGIjDl/WhONWl5jKlYrbZ9OJGRWVIg/+axf8SK5a
8WoC5fPm//l2qqIIOaVVECm3QZG5C7L0HZCklYJLTCQKNUiWFYAnykJYRDRaywNxrTGRyhKNKyciiIEY
dFd743z1ZioT6eJkHK41kXDbRFSKbHzTpcJwsxoHc71fTLGzyBix+L/zUFlaWX+VTcFZ4NzSamQXV1Lw
EggkeeBRAsnSfKgyy6DKKcNnxEahIgRfHg5B/7EoDDYn4ma7FD0VAThfG4Cemi3EDI90IKWVq3GbHHKz
nUpCbrh6QokEr5mPTEw4773MQij9aPZY5fNYrC6hEhRAnrkTjJEkcS5ieWokS/IhUZdCrtlJbGQiIjQQ
/YeD0VMVhoTVbmgs8iVBctG11xtdlUHkDGpQpIN7velUAhmG2+W43spclI6K9JWY6TyxlGKOGxWjG53s
5HBMBpZ7+iI6UY44vhoiVTH4ohxCLoTyArqu1OlBll6CZHE20mI9EOjuis3L5uFCbTh6D4Wgu8offYeC
qSRccgcPD/qyMEiBb55VYahFgSuNckhjlr2YaGMqH2ntOiKmEAQGBgbnNviGPg2LFSM4UoiAUD78ghLo
yEVojBhRiQqEx0nAI5sKiBH/z+OgVfuic7c/Lh+NwZndfughDfQdCtL1hKFmEW51ymn1EjpSAh1ytFCL
Pl+nhKebY8XLTYn16DWEgzY2ttdzyI6yjB06+uP4acRANokvhzRRjBR5oe4aN4WupeYgNCIWZ2vj0b17
I/UKf3Tt34jOis9otTyyILmkORUDTRKyqxj9DSI07Y0k26Yhes38Roo3YVQH7OVhGiGR0K7O0epEqCRB
shKwRIQkQrZqMelAIM6ncihII9uQSCXZEi2HSMjDXvVqXKSGdTLbg6z6OVkwGcfLQvHB4jkYbJMS/UL0
1aeSM6So1Hg/oljTR93AupEVYSXhGE+soZa8X+cIlgALzFhg5/HJ6YhIzACXVs9EKiHRMmckSfMQGx0G
rXIldU4/dJSvJx3EoSDZC7OszHByTxTOfZGEq00y9B3lo70iElamhp4Ujy1eN8wIrEOd0BRW6DpiWEwq
giKSdYiIl5IOUskRKh39AmKECZNP7Mg0O6Ci59Pzd4O/NQK7FBvQULyGOmMUpBsX4KqjGTL5qzHQIqJy
iNG6Px5dtYlY7jqhmeKxvUE32C7FGKiP58uf5W6v0ekgPkmNrYIMor4YqcoinQBFdGQrl2ZsB4/cwBJR
Zml/+k0sxcQnQZzgDWHIIni9NQHSHU5IS15EPSEN11ok6G9UQs1dh/lvv/GdkZHR3NEETOhkIUE7zvb1
wRRFwYv0vD3UBTORJCEdSHMhydgFCXVHVnuWEGvZrDewjqmzKbHDNjHmFl5KBlasWokiFwtop5nhyL6p
2JO/CN2HBdSgMpHJ88GH82c8s7b4T1vmUPA3CFxCp19QzBPdtpxdRqon2kkDKRSYXeOJcyBUFMI7IJ70
kYsEgRLTXGbgrzNnwmWqC2Y4OsLZZjx43El4ggXI1zohy24MAFd4u9tj8YLpmD71DTiMtwGHY1A7ygB7
52N29CLULV7qeT+HnFCoPairu87/RC9rTjE8JYJoY/p4lR8lVQAp7Rc+/pHY7OKE61NN8a21MbQpfwC+
m4fbQ7MQNdcCfWMMsTPWDi2yyRgyNkDhOGPYGhpeo97jP5oAcwJjYQ4hk3DOyzvwn9v3HtUJjHXAzSFc
RHHlCAznIyAsCZa2k56u3xT2gtHPmGHCdXtnHh47mKBqjS1K5Q7ITrCjlf8RqXPM0bDUCr3bp2C9nj70
DDinKMYSwmujCbAjY4G9ZrN3tyMLP/D4IT1vP/J21CBeoKaa55MTUhAeK8J7i91v0DMdxqZmgw7Oc74N
iFQ8T5YX6ZzisWI9Uiebo8rKCOcsjLAv1Z72BydUxE5ElcTuKf2P9RunEeGzmD8bTIzsI0I7wc7xdgyf
NiayWVoueZ1qz7zPT8l5McnBqZieYZsYO/a4zF7yaKWP4HlASMKLj9xX4WrXWzhdMxUFlkaI1tPDAZE9
Htc4wWuhOas5Y/oXgUezYDdZdmK2N6zzCfuB1V1GFkulNswT5cFllms73f+QMIWwjCDjGJnUW1rbfu2z
wvXJk85pUH5gieNJdugvd8QV7RSc0TjgiMwevkvH3np1xa/+ZplZE9jecNh14UcPmO8VmnLyfzGr/feU
mB/dY7VjybItdSZhrb6+fvEYY6PuMWOMn7ZbGeILfQNYmnN+mO1o/OBdCw74HAMsMjR8NjL/r+Yx+p3H
XhjKZs93uxMZr4Z/uOb54qWf3bGf4pw3EpC1UPYsS3g0EU9K4uBsI86zYHPOY3MOp4zuRRLyDfT1O941
Mrzvb86Bob4h+0r6zcEmdiFICA2vvT55kLFBYOJhnYt9or06TOmCJ7HTbGxgADpndmaJMU29QxAQKvTo
vhnHkN1nX12/OlgCNoT3CZsIvgRWc9ao2IT/bTD3+BID7N1/zisBWCKOBB/CagKf8PboJP8CoUmu3yhA
ga8AAAAASUVORK5CYII=
</value>
</data>
</root>

View File

@@ -439,10 +439,6 @@ namespace OpenRA.Editor
float OffsetY = t.Centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
float width = t.Bitmap.Width * Zoom;
float height = t.Bitmap.Height * Zoom;
RectangleF sourceRect = new RectangleF(0, 0, t.Bitmap.Width, t.Bitmap.Height);
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
g.DrawRectangle(CordonPen,
DrawX, DrawY,
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);

22
OpenRA.FileFormats/Exts.cs Normal file → Executable file
View File

@@ -73,5 +73,27 @@ namespace OpenRA
{
return mi.GetCustomAttributes(typeof(T), true).Length != 0;
}
public static T[] GetCustomAttributes<T>( this MemberInfo mi, bool inherit )
where T : class
{
return (T[])mi.GetCustomAttributes( typeof( T ), inherit );
}
public static T[] GetCustomAttributes<T>( this ParameterInfo mi )
where T : class
{
return (T[])mi.GetCustomAttributes( typeof( T ), true );
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0)
return min;
else if (val.CompareTo(max) > 0)
return max;
else
return val;
}
}
}

21
OpenRA.FileFormats/FieldLoader.cs Normal file → Executable file
View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Globalization;
namespace OpenRA.FileFormats
{
@@ -99,7 +100,7 @@ namespace OpenRA.FileFormats
else if (fieldType == typeof(float))
{
float res;
if (float.TryParse(x.Replace("%",""), out res))
if (float.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
return res * (x.Contains( '%' ) ? 0.01f : 1f);
return InvalidValueAction(x,fieldType, field);
}
@@ -111,9 +112,9 @@ namespace OpenRA.FileFormats
{
var parts = x.Split(',');
if (parts.Length == 3)
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]));
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255));
if (parts.Length == 4)
return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255));
return InvalidValueAction(x,fieldType, field);
}
@@ -177,11 +178,12 @@ namespace OpenRA.FileFormats
{
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
foreach( var field in type.GetFields() )
foreach( var ff in type.GetFields() )
{
var load = (LoadAttribute[])field.GetCustomAttributes( typeof( LoadAttribute ), false );
var loadUsing = (LoadUsingAttribute[])field.GetCustomAttributes( typeof( LoadUsingAttribute ), false );
var fromYamlKey = (FieldFromYamlKeyAttribute[])field.GetCustomAttributes( typeof( FieldFromYamlKeyAttribute ), false );
var field = ff;
var load = field.GetCustomAttributes<LoadAttribute>( false );
var loadUsing = field.GetCustomAttributes<LoadUsingAttribute>( false );
var fromYamlKey = field.GetCustomAttributes<FieldFromYamlKeyAttribute>( false );
if( loadUsing.Length != 0 )
ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
else if( fromYamlKey.Length != 0 )
@@ -262,7 +264,10 @@ namespace OpenRA.FileFormats
if (f.FieldType == typeof(Color))
{
var c = (Color)v;
return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B);
return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255),
((int)c.R).Clamp(0, 255),
((int)c.G).Clamp(0, 255),
((int)c.B).Clamp(0, 255));
}
return f.FieldType.IsArray

View File

@@ -52,13 +52,13 @@ namespace OpenRA.FileFormats.Graphics
public interface IVertexBuffer<T>
{
void Bind();
void SetData( T[] vertices );
void SetData( T[] vertices, int length );
}
public interface IIndexBuffer
{
void Bind();
void SetData( ushort[] indices );
void SetData( ushort[] indices, int length );
}
public interface IShader

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</ProjectGuid>
<OutputType>Library</OutputType>

View File

@@ -25,6 +25,7 @@ namespace OpenRA
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); }
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
@@ -59,5 +60,15 @@ namespace OpenRA
{
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
}
public static int Lerp( int a, int b, int mul, int div )
{
return a + ( b - a ) * mul / div;
}
public static int2 Lerp( int2 a, int2 b, int mul, int div )
{
return a + ( b - a ) * mul / div;
}
}
}

View File

@@ -26,7 +26,8 @@ namespace OpenRA
public readonly World World;
public readonly uint ActorID;
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
public float2 CenterLocation { get { return Trait<IHasLocation>().PxPosition; } }
[Sync]
public Player Owner;
@@ -52,9 +53,6 @@ namespace OpenRA
AddTrait(trait.Create(init));
}
if( CenterLocation == float2.Zero && HasTrait<IOccupySpace>() )
CenterLocation = Traits.Util.CenterOfCell(Location);
Size = Lazy.New(() =>
{
var si = Info.Traits.GetOrDefault<SelectableInfo>();
@@ -99,8 +97,6 @@ namespace OpenRA
get { return currentActivity == null || currentActivity is Idle; }
}
public float2 CenterLocation;
OpenRA.FileFormats.Lazy<float2> Size;
public IEnumerable<Renderable> Render()
@@ -110,23 +106,6 @@ namespace OpenRA
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
}
public Order Order( int2 xy, MouseInput mi, Actor underCursor )
{
if (Owner != World.LocalPlayer)
return null;
if (!World.Map.IsInMap(xy.X, xy.Y))
return null;
if (Destroyed)
return null;
return TraitsImplementing<IIssueOrder>()
.OrderByDescending( x => x.OrderPriority( this, xy, mi, underCursor ) )
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
.FirstOrDefault( x => x != null );
}
public RectangleF GetBounds(bool useAltitude)
{
var si = Info.Traits.GetOrDefault<SelectableInfo>();
@@ -151,16 +130,9 @@ namespace OpenRA
public void QueueActivity( IActivity nextActivity )
{
if( currentActivity == null )
{
currentActivity = nextActivity;
return;
}
var act = currentActivity;
while( act.NextActivity != null )
{
act = act.NextActivity;
}
act.NextActivity = nextActivity;
else
currentActivity.Queue( nextActivity );
}
public void CancelActivity()

View File

@@ -22,7 +22,7 @@ namespace OpenRA
public void Draw(int frame, float2 pos)
{
Game.Renderer.SpriteRenderer.DrawSprite(sequence.GetSprite(frame), pos - sequence.Hotspot, sequence.Palette);
sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, sequence.Palette);
}
}
}

20
OpenRA.Game/Exts.cs Normal file → Executable file
View File

@@ -34,17 +34,17 @@ namespace OpenRA
return xs.Aggregate(1f, (a, x) => a * x);
}
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
where V : new()
{
return d.GetOrAdd( k, _ => new V() );
return d.GetOrAdd(k, _ => new V());
}
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
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 ) );
if (!d.TryGetValue(k, out ret))
d.Add(k, ret = createFn(k));
return ret;
}
@@ -54,18 +54,18 @@ namespace OpenRA
return xs[r.Next(xs.Length)];
}
public static void DoTimed<T>( this IEnumerable<T> e, Action<T> a, string text, double time )
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
{
var sw = new Stopwatch();
e.Do( x =>
e.Do(x =>
{
var t = sw.ElapsedTime();
a( x );
a(x);
var dt = sw.ElapsedTime() - t;
if( dt > time )
if (dt > time)
Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
} );
});
}
}
}

View File

@@ -47,7 +47,6 @@ namespace OpenRA
var map = modData.PrepareMap(uid);
viewport = new Viewport(new float2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
world = new World(modData.Manifest, map);
}
@@ -101,7 +100,7 @@ namespace OpenRA
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
static void Tick()
static void Tick( World world, OrderManager orderManager, Viewport viewPort )
{
if (orderManager.Connection.ConnectionState != lastConnectionState)
{
@@ -126,6 +125,8 @@ namespace OpenRA
{
++LocalTick;
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
if (isNetTick) orderManager.Tick(world);
world.OrderGenerator.Tick(world);
@@ -157,7 +158,7 @@ namespace OpenRA
internal static event Action LobbyInfoChanged = () => { };
internal static void SyncLobbyInfo(string data)
internal static void SyncLobbyInfo( World world, string data)
{
LobbyInfo = Session.Deserialize(data);
@@ -177,17 +178,20 @@ namespace OpenRA
LobbyInfoChanged();
}
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
public static void IssueOrder( Order o ) { orderManager.IssueOrder( o ); } /* avoid exposing the OM to mod code */
public static event Action AfterGameStart = () => {};
public static event Action BeforeGameStart = () => {};
internal static void StartGame(string map)
{
world = null;
BeforeGameStart();
LoadMap(map);
if (orderManager.GameStarted) return;
Widget.SelectedWidget = null;
Widget.SelectedWidget = null;
LocalTick = 0;
orderManager.StartGame();
viewport.RefreshPalette();
@@ -196,23 +200,20 @@ namespace OpenRA
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
{
if (world == null)
return;
int sync = world.SyncHash();
var initialWorld = world;
var world = Game.world;
if (world == null) return;
var mi = new MouseInput
Sync.CheckSyncUnchanged( world, () =>
{
Button = (MouseButton)(int)e.Button,
Event = ev,
Location = new int2(e.Location),
Modifiers = modifierKeys,
};
Widget.HandleInput(world, mi);
if (sync != world.SyncHash() && world == initialWorld)
throw new InvalidOperationException("Desync in DispatchMouseInput");
var mi = new MouseInput
{
Button = (MouseButton)(int)e.Button,
Event = ev,
Location = new int2( e.Location ),
Modifiers = modifierKeys,
};
Widget.HandleInput( world, mi );
} );
}
public static bool IsHost
@@ -227,16 +228,13 @@ namespace OpenRA
public static void HandleKeyEvent(KeyInput e)
{
if (world == null)
return;
int sync = world.SyncHash();
if (Widget.HandleKeyPress(e))
return;
var world = Game.world;
if( world == null ) return;
if (sync != Game.world.SyncHash())
throw new InvalidOperationException("Desync in OnKeyPress");
Sync.CheckSyncUnchanged( world, () =>
{
Widget.HandleKeyPress( e );
} );
}
static Modifiers modifiers;
@@ -263,7 +261,14 @@ namespace OpenRA
Renderer.SheetSize = Settings.Game.SheetSize;
Renderer = new Renderer();
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods;
Console.WriteLine("Available mods:");
foreach(var mod in ModData.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
// Discard any invalid mods
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods.Where(m => ModData.AllMods.ContainsKey(m)).ToArray();
Console.WriteLine("Loading mods: {0}",string.Join(",",LobbyInfo.GlobalSettings.Mods));
modData = new ModData( LobbyInfo.GlobalSettings.Mods );
Sound.Initialize();
@@ -275,6 +280,36 @@ namespace OpenRA
JoinLocal();
StartGame(modData.Manifest.ShellmapUid);
Game.BeforeGameStart += () => Widget.OpenWindow("INGAME_ROOT");
Game.ConnectionStateChanged += () =>
{
Widget.CloseWindow();
switch( Game.orderManager.Connection.ConnectionState )
{
case ConnectionState.PreConnecting:
Widget.OpenWindow("MAINMENU_BG");
break;
case ConnectionState.Connecting:
Widget.OpenWindow("CONNECTING_BG");
break;
case ConnectionState.NotConnected:
Widget.OpenWindow("CONNECTION_FAILED_BG");
break;
case ConnectionState.Connected:
var lobby = Widget.OpenWindow("SERVER_LOBBY");
lobby.GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true;
lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true;
lobby.GetWidget("DISCONNECT_BUTTON").Visible = true;
//r.GetWidget("INGAME_ROOT").GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
break;
}
};
modData.WidgetLoader.LoadWidget( Widget.RootWidget, "PERF_BG" );
Widget.OpenWindow("MAINMENU_BG");
ResetTimer();
}
@@ -283,7 +318,7 @@ namespace OpenRA
internal static void Run()
{
while (!quit)
{
{
Tick( world, orderManager, viewport );
Application.DoEvents();
}
@@ -306,8 +341,8 @@ namespace OpenRA
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods;
JoinLocal();
StartGame(shellmap);
Widget.RootWidget.CloseWindow();
Widget.CloseWindow();
Widget.OpenWindow("MAINMENU_BG");
}

View File

@@ -8,13 +8,13 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
using System;
namespace OpenRA.GameRules
{
@@ -24,7 +24,7 @@ namespace OpenRA.GameRules
public int ListenPort = 1234;
public int ExternalPort = 1234;
public bool AdvertiseOnline = true;
public string MasterServer = "http://open-ra.org/master/";
public string MasterServer = "http://master.open-ra.org/";
public bool AllowCheats = false;
}
@@ -69,6 +69,7 @@ namespace OpenRA.GameRules
// Behaviour settings
public bool ViewportEdgeScroll = true;
public bool InverseDragScroll = false;
public float ViewportEdgeScrollStep = 10f;
// Internal game settings
public int Timestep = 40;
@@ -133,16 +134,11 @@ namespace OpenRA.GameRules
{
var root = new List<MiniYamlNode>();
foreach( var kv in Sections )
root.Add( new MiniYamlNode( kv.Key, SectionYaml( kv.Value ) ) );
root.Add( new MiniYamlNode( kv.Key, FieldSaver.Save(kv.Value) ) );
root.WriteToFile(SettingsFile);
}
MiniYaml SectionYaml(object section)
{
return FieldSaver.SaveDifferences(section, Activator.CreateInstance(section.GetType()));
}
void LoadSectionYaml(MiniYaml yaml, object section)
{
object defaults = Activator.CreateInstance(section.GetType());

View File

@@ -32,6 +32,7 @@ namespace OpenRA.GameRules
[FieldLoader.Load] public readonly int Damage = 0; // how much (raw) damage to deal
[FieldLoader.Load] public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
[FieldLoader.Load] public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
[FieldLoader.Load] public readonly bool PreventProne = false; // whether we should prevent prone response in infantry.
public float EffectivenessAgainst(Actor self)
{
@@ -92,6 +93,7 @@ namespace OpenRA.GameRules
[FieldLoader.Load] public readonly bool Underwater = false;
[FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" };
[FieldLoader.Load] public readonly int BurstDelay = 5;
[FieldLoader.Load] public readonly float MinRange = 0;
[FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile;
[FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads;

View File

@@ -13,45 +13,46 @@ using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics
{
public class LineRenderer
public class LineRenderer : Renderer.IBatchRenderer
{
Renderer renderer;
IVertexBuffer<Vertex> vertexBuffer;
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
const int linesPerBatch = 1024;
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
ushort[] indices = new ushort[ 2 * linesPerBatch ];
int lines = 0;
Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ];
ushort[] indices = new ushort[ Renderer.TempBufferSize ];
int nv = 0, ni = 0;
public LineRenderer( Renderer renderer )
{
this.renderer = renderer;
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
}
public void Flush()
{
if( lines > 0 )
if( ni > 0 )
{
renderer.LineShader.Render( () =>
{
vertexBuffer.SetData( vertices );
indexBuffer.SetData( indices );
renderer.DrawBatch( vertexBuffer, indexBuffer,
var vb = renderer.GetTempVertexBuffer();
var ib = renderer.GetTempIndexBuffer();
vb.SetData( vertices, nv );
ib.SetData( indices, ni );
renderer.DrawBatch( vb, ib,
nv, ni / 2, PrimitiveType.LineList );
} );
nv = 0; ni = 0;
lines = 0;
}
}
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
{
Renderer.CurrentBatchRenderer = this;
if( ni + 2 > Renderer.TempBufferSize )
Flush();
if( nv + 2 > Renderer.TempBufferSize )
Flush();
indices[ ni++ ] = (ushort)nv;
vertices[ nv++ ] = new Vertex( start,
@@ -63,9 +64,6 @@ namespace OpenRA.Graphics
vertices[ nv++ ] = new Vertex( end,
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
if( ++lines >= linesPerBatch )
Flush();
}
public void FillRect( RectangleF r, Color color )

View File

@@ -16,6 +16,7 @@ using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
using OpenRA.Support;
using System.Windows.Forms;
using System.Collections.Generic;
namespace OpenRA.Graphics
{
@@ -23,10 +24,10 @@ namespace OpenRA.Graphics
{
internal static int SheetSize;
public IShader SpriteShader { get; private set; } /* note: shared shader params */
public IShader LineShader { get; private set; }
public IShader RgbaSpriteShader { get; private set; }
public IShader WorldSpriteShader { get; private set; }
internal IShader SpriteShader { get; private set; } /* note: shared shader params */
internal IShader LineShader { get; private set; }
internal IShader RgbaSpriteShader { get; private set; }
internal IShader WorldSpriteShader { get; private set; }
public SpriteRenderer SpriteRenderer { get; private set; }
public SpriteRenderer RgbaSpriteRenderer { get; private set; }
@@ -37,6 +38,12 @@ namespace OpenRA.Graphics
public readonly SpriteFont RegularFont, BoldFont, TitleFont;
internal const int TempBufferSize = 8192;
const int TempBufferCount = 8;
Queue<IVertexBuffer<Vertex>> tempBuffersV = new Queue<IVertexBuffer<Vertex>>();
Queue<IIndexBuffer> tempBuffersI = new Queue<IIndexBuffer>();
public Renderer()
{
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
@@ -52,9 +59,15 @@ namespace OpenRA.Graphics
RegularFont = new SpriteFont("FreeSans.ttf", 14);
BoldFont = new SpriteFont("FreeSansBold.ttf", 14);
TitleFont = new SpriteFont("titles.ttf", 48);
for( int i = 0 ; i < TempBufferCount ; i++ )
{
tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
tempBuffersI.Enqueue( device.CreateIndexBuffer( TempBufferSize ) );
}
}
public IGraphicsDevice Device { get { return device; } }
internal IGraphicsDevice Device { get { return device; } }
public void BeginFrame(float2 scroll)
{
@@ -81,6 +94,7 @@ namespace OpenRA.Graphics
public void EndFrame()
{
Flush();
device.End();
device.Present();
}
@@ -111,15 +125,9 @@ namespace OpenRA.Graphics
public void Flush()
{
WorldSpriteRenderer.Flush();
RgbaSpriteRenderer.Flush();
LineRenderer.Flush();
CurrentBatchRenderer = null;
}
static IGraphicsDevice device;
public static Size Resolution { get { return device.WindowSize; } }
@@ -154,5 +162,49 @@ namespace OpenRA.Graphics
}
throw new NotImplementedException();
}
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
{
var ret = tempBuffersV.Dequeue();
tempBuffersV.Enqueue( ret );
return ret;
}
internal IIndexBuffer GetTempIndexBuffer()
{
var ret = tempBuffersI.Dequeue();
tempBuffersI.Enqueue( ret );
return ret;
}
public interface IBatchRenderer
{
void Flush();
}
static IBatchRenderer currentBatchRenderer;
public static IBatchRenderer CurrentBatchRenderer
{
get { return currentBatchRenderer; }
set
{
if( currentBatchRenderer == value ) return;
if( currentBatchRenderer != null )
currentBatchRenderer.Flush();
currentBatchRenderer = value;
}
}
public void EnableScissor(int left, int top, int width, int height)
{
Flush();
Device.EnableScissor( left, top, width, height );
}
public void DisableScissor()
{
Flush();
Device.DisableScissor();
}
}
}

View File

@@ -49,6 +49,26 @@ namespace OpenRA.Graphics
{
return uvhax[ k ];
}
public void DrawAt( float2 location, string palette )
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, palette, this.size );
}
public void DrawAt( float2 location, int paletteIndex )
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size );
}
public void DrawAt(float2 location, string palette, float2 size)
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, palette, size );
}
public void DrawAt( float2 location, int paletteIndex, float2 size )
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, size );
}
}
public enum TextureChannel

View File

@@ -80,17 +80,20 @@ namespace OpenRA.Graphics
GlyphInfo CreateGlyph(Pair<char,Color> c)
{
var index = FT.FT_Get_Char_Index(face, (uint)c.First);
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
if (0 != FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER))
throw new InvalidOperationException( "FT_Load_Glyph failed." );
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
var s = builder.Allocate(
new Size(_glyph.metrics.width.ToInt32() >> 6,
_glyph.metrics.height.ToInt32() >> 6));
var g = new GlyphInfo
{
Sprite = s,
Advance = _glyph.metrics.horiAdvance / 64f,
Advance = _glyph.metrics.horiAdvance.ToInt32() / 64f,
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
};

View File

@@ -12,28 +12,20 @@ using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics
{
public class SpriteRenderer
public class SpriteRenderer : Renderer.IBatchRenderer
{
IVertexBuffer<Vertex> vertexBuffer;
IIndexBuffer indexBuffer;
Renderer renderer;
IShader shader;
const int spritesPerBatch = 1024;
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
ushort[] indices = new ushort[6 * spritesPerBatch];
Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
ushort[] indices = new ushort[Renderer.TempBufferSize];
Sheet currentSheet = null;
int sprites = 0;
int nv = 0, ni = 0;
public SpriteRenderer(Renderer renderer, IShader shader)
{
this.renderer = renderer;
this.shader = shader;
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
}
public SpriteRenderer(Renderer renderer)
@@ -41,14 +33,16 @@ namespace OpenRA.Graphics
public void Flush()
{
if (sprites > 0)
if (ni > 0)
{
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
shader.Render(() =>
{
vertexBuffer.SetData(vertices);
indexBuffer.SetData(indices);
renderer.DrawBatch(vertexBuffer, indexBuffer,
var vb = renderer.GetTempVertexBuffer();
var ib = renderer.GetTempIndexBuffer();
vb.SetData(vertices, nv);
ib.SetData(indices, ni);
renderer.DrawBatch(vb, ib,
new Range<int>(0, nv),
new Range<int>(0, ni),
PrimitiveType.TriangleList,
@@ -57,7 +51,6 @@ namespace OpenRA.Graphics
nv = 0; ni = 0;
currentSheet = null;
sprites = 0;
}
}
@@ -73,14 +66,19 @@ namespace OpenRA.Graphics
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
{
Renderer.CurrentBatchRenderer = this;
if (s.sheet != currentSheet)
Flush();
if( nv + 4 > Renderer.TempBufferSize )
Flush();
if( ni + 6 > Renderer.TempBufferSize )
Flush();
currentSheet = s.sheet;
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size);
nv += 4; ni += 6;
if (++sprites >= spritesPerBatch)
Flush();
}

View File

@@ -56,10 +56,10 @@ namespace OpenRA.Graphics
}
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer( vertices.Length );
vertexBuffer.SetData( vertices );
vertexBuffer.SetData( vertices, nv );
indexBuffer = Game.Renderer.Device.CreateIndexBuffer( indices.Length );
indexBuffer.SetData( indices );
indexBuffer.SetData( indices, ni );
}
public void Draw( Viewport viewport )

View File

@@ -107,10 +107,6 @@ namespace OpenRA.Graphics
var c = new Cursor(cursorName);
c.Draw((int)cursorFrame, Viewport.LastMousePos + Location);
renderer.RgbaSpriteRenderer.Flush();
renderer.SpriteRenderer.Flush();
renderer.WorldSpriteRenderer.Flush();
renderer.EndFrame();
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Graphics
{
readonly World world;
internal readonly TerrainRenderer terrainRenderer;
internal readonly UiOverlay uiOverlay;
public readonly UiOverlay uiOverlay;
internal readonly HardwarePalette palette;
internal WorldRenderer(World world)
@@ -90,20 +90,16 @@ namespace OpenRA.Graphics
public void Draw()
{
var bounds = GetBoundsRect();
Game.Renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
terrainRenderer.Draw(Game.viewport);
if (world.OrderGenerator != null)
world.OrderGenerator.RenderBeforeWorld(world);
Game.Renderer.SpriteRenderer.Flush();
Game.Renderer.LineRenderer.Flush();
foreach (var image in worldSprites)
Game.Renderer.SpriteRenderer.DrawSprite(image.Sprite, image.Pos, image.Palette);
foreach( var image in worldSprites )
image.Sprite.DrawAt( image.Pos, this.GetPaletteIndex( image.Palette ) );
uiOverlay.Draw(world);
Game.Renderer.SpriteRenderer.Flush();
if (world.OrderGenerator != null)
world.OrderGenerator.RenderAfterWorld(world);
@@ -111,11 +107,7 @@ namespace OpenRA.Graphics
if (world.LocalPlayer != null)
world.LocalPlayer.Shroud.Draw();
Game.Renderer.SpriteRenderer.Flush();
Game.Renderer.Device.DisableScissor();
Game.Renderer.LineRenderer.Flush();
Game.Renderer.DisableScissor();
}
void DrawBox(RectangleF r, Color color)

View File

@@ -19,15 +19,45 @@ namespace OpenRA
{
public class ModData
{
public static readonly Dictionary<string,Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public static Dictionary<string,Mod> ValidateMods(string[] mods)
{
var ret = new Dictionary<string,Mod>();
foreach (var m in mods)
{
if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"))
continue;
var yaml = new MiniYaml( null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"));
if (!yaml.NodesDict.ContainsKey("Metadata"))
{
System.Console.WriteLine("Invalid mod: "+m);
continue;
}
ret.Add(m,FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]));
}
return ret;
}
public class Mod
{
public string Title;
public string Description;
public string Version;
}
public readonly Manifest Manifest;
public readonly ObjectCreator ObjectCreator;
public readonly SheetBuilder SheetBuilder;
public readonly CursorSheetBuilder CursorSheetBuilder;
public readonly Dictionary<string, MapStub> AvailableMaps;
public readonly WidgetLoader WidgetLoader;
public ILoadScreen LoadScreen = null;
public ModData( params string[] mods )
{
{
Manifest = new Manifest( mods );
ObjectCreator = new ObjectCreator( Manifest );
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen);
@@ -39,6 +69,7 @@ namespace OpenRA
SheetBuilder = new SheetBuilder( TextureChannel.Red );
CursorSheetBuilder = new CursorSheetBuilder( this );
AvailableMaps = FindMaps( mods );
WidgetLoader = new WidgetLoader( this );
}
// TODO: Do this nicer

View File

@@ -187,9 +187,9 @@ namespace OpenRA
return new Order("PauseProduction", subject, new int2( pause ? 1 : 0, 0 ), item);
}
public static Order CancelProduction(Actor subject, string item)
public static Order CancelProduction(Actor subject, string item, int count)
{
return new Order("CancelProduction", subject, item);
return new Order("CancelProduction", subject, new int2( count, 0 ), item);
}
}
}

View File

@@ -21,10 +21,10 @@ namespace OpenRA.Network
return Game.LobbyInfo.Clients.FirstOrDefault(c => c.Index == id);
}
static Player FindPlayerByClientId(int id)
static Player FindPlayerByClientId( this World world, int id)
{
/* todo: find the interactive player. */
return Game.world.players.Values.FirstOrDefault(p => p.ClientIndex == id);
return world.players.Values.FirstOrDefault(p => p.ClientIndex == id);
}
public static void ProcessOrder( World world, int clientId, Order order )
@@ -43,7 +43,7 @@ namespace OpenRA.Network
var client = FindClientById(clientId);
if (client != null)
{
var player = FindPlayerByClientId(clientId);
var player = world.FindPlayerByClientId(clientId);
if (player != null && player.WinState == WinState.Lost)
Game.AddChatLine(client.Color1, client.Name + " (Dead)", order.TargetString);
else
@@ -56,7 +56,7 @@ namespace OpenRA.Network
var client = FindClientById(clientId);
if (client != null)
{
var player = FindPlayerByClientId(clientId);
var player = world.FindPlayerByClientId(clientId);
var display = (world.GameHasStarted) ?
player != null && (world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost) :
@@ -78,7 +78,7 @@ namespace OpenRA.Network
}
case "SyncInfo":
{
Game.SyncLobbyInfo(order.TargetString);
Game.SyncLobbyInfo( world, order.TargetString);
break;
}
case "SetStance":

View File

@@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.FileFormats;
using System.Collections.Generic;
namespace OpenRA
{
@@ -30,19 +31,61 @@ namespace OpenRA
public static Action<string> MissingTypeAction =
s => { throw new InvalidOperationException("Cannot locate type: {0}".F(s)); };
public T CreateObject<T>(string classname)
public T CreateObject<T>(string className)
{
foreach (var mod in ModAssemblies)
{
var fullTypeName = mod.Second + "." + classname;
var obj = mod.First.CreateInstance(fullTypeName);
if (obj != null)
return (T)obj;
}
return CreateObject<T>( className, new Dictionary<string, object>() );
}
MissingTypeAction(classname);
public T CreateObject<T>( string className, Dictionary<string, object> args )
{
foreach( var mod in ModAssemblies )
{
var type = mod.First.GetType( mod.Second + "." + className, false );
if( type == null ) continue;
var ctors = type.GetConstructors().Where( x => x.HasAttribute<UseCtorAttribute>() ).ToList();
if( ctors.Count == 0 )
return (T)CreateBasic( type );
else if( ctors.Count == 1 )
return (T)CreateUsingArgs( ctors[ 0 ], args );
else
throw new InvalidOperationException( "ObjectCreator: UseCtor on multiple constructors; invalid." );
}
MissingTypeAction(className);
return default(T);
}
public object CreateBasic( Type type )
{
return type.GetConstructor( new Type[ 0 ] ).Invoke( new object[ 0 ] );
}
public object CreateUsingArgs( ConstructorInfo ctor, Dictionary<string, object> args )
{
var p = ctor.GetParameters();
var a = new object[ p.Length ];
for( int i = 0 ; i < p.Length ; i++ )
{
var attrs = p[ i ].GetCustomAttributes<ParamAttribute>();
if( attrs.Length != 1 ) throw new InvalidOperationException( "ObjectCreator: argument in [UseCtor] doesn't have [Param]" );
a[ i ] = args[ attrs[ 0 ].ParamName ];
}
return ctor.Invoke( a );
}
[AttributeUsage( AttributeTargets.Parameter )]
public class ParamAttribute : Attribute
{
public string ParamName { get; private set; }
public ParamAttribute( string paramName )
{
ParamName = paramName;
}
}
[AttributeUsage( AttributeTargets.Constructor )]
public class UseCtorAttribute : Attribute
{
}
}
}

View File

@@ -1,9 +1,9 @@
<?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>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
<OutputType>WinExe</OutputType>
@@ -75,7 +75,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Effects\RepairIndicator.cs" />
<Compile Include="GameRules\WeaponInfo.cs" />
<Compile Include="Group.cs" />
<Compile Include="Orders\GenericSelectTarget.cs" />
@@ -135,7 +134,6 @@
<Compile Include="Traits\Activities\RemoveSelf.cs" />
<Compile Include="Traits\Activities\Sell.cs" />
<Compile Include="Orders\IOrderGenerator.cs" />
<Compile Include="Orders\PlaceBuildingOrderGenerator.cs" />
<Compile Include="Player.cs" />
<Compile Include="Graphics\Sheet.cs" />
<Compile Include="PathFinder.cs" />
@@ -155,23 +153,15 @@
<Compile Include="Graphics\TerrainRenderer.cs" />
<Compile Include="Traits\Activities\Move.cs" />
<Compile Include="Traits\Activities\Turn.cs" />
<Compile Include="Traits\Buildable.cs" />
<Compile Include="Traits\Building.cs" />
<Compile Include="Traits\World\BuildingInfluence.cs" />
<Compile Include="Traits\Player\PlaceBuilding.cs" />
<Compile Include="Traits\World\PlayerColorPalette.cs" />
<Compile Include="Traits\World\ResourceLayer.cs" />
<Compile Include="Traits\World\ResourceType.cs" />
<Compile Include="Traits\SupportPower.cs" />
<Compile Include="Traits\ProvidesRadar.cs" />
<Compile Include="Traits\Selectable.cs" />
<Compile Include="Traits\Player\ProductionQueue.cs" />
<Compile Include="Traits\Mobile.cs" />
<Compile Include="Traits\Production.cs" />
<Compile Include="Traits\RallyPoint.cs" />
<Compile Include="Traits\Render\RenderSimple.cs" />
<Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\Turreted.cs" />
<Compile Include="Traits\World\UnitInfluence.cs" />
<Compile Include="Network\UnitOrders.cs" />
<Compile Include="Traits\Util.cs" />
@@ -191,8 +181,6 @@
<Compile Include="Widgets\BackgroundWidget.cs" />
<Compile Include="Widgets\LabelWidget.cs" />
<Compile Include="Widgets\CheckboxWidget.cs" />
<Compile Include="Traits\World\BibLayer.cs" />
<Compile Include="Traits\World\SmudgeLayer.cs" />
<Compile Include="Widgets\Delegates\MusicPlayerDelegate.cs" />
<Compile Include="Widgets\PerfGraphWidget.cs" />
<Compile Include="Widgets\Delegates\PerfDebugDelegate.cs" />
@@ -200,7 +188,6 @@
<Compile Include="Widgets\ColorBlockWidget.cs" />
<Compile Include="GameRules\MusicInfo.cs" />
<Compile Include="Widgets\ImageWidget.cs" />
<Compile Include="Traits\SharesCell.cs" />
<Compile Include="Widgets\TextFieldWidget.cs" />
<Compile Include="Widgets\ChatDisplayWidget.cs" />
<Compile Include="Widgets\Delegates\MapChooserDelegate.cs" />
@@ -215,18 +202,15 @@
<Compile Include="Traits\RevealsShroud.cs" />
<Compile Include="Traits\Targetable.cs" />
<Compile Include="Traits\Health.cs" />
<Compile Include="Traits\RepairableBuilding.cs" />
<Compile Include="Traits\Activities\Drag.cs" />
<Compile Include="Widgets\VqaPlayerWidget.cs" />
<Compile Include="Widgets\Delegates\VideoPlayerDelegate.cs" />
<Compile Include="Traits\MPStartLocations.cs" />
<Compile Include="GameRules\Settings.cs" />
<Compile Include="Support\Arguments.cs" />
<Compile Include="Traits\ActorStance.cs" />
<Compile Include="Traits\Armor.cs" />
<Compile Include="Graphics\CursorProvider.cs" />
<Compile Include="Traits\Player\TechTree.cs" />
<Compile Include="Traits\Player\ClassicProductionQueue.cs" />
<Compile Include="Traits\Player\PowerManager.cs" />
</ItemGroup>
<ItemGroup>
@@ -242,8 +226,11 @@
<Compile Include="ObjectCreator.cs" />
<Compile Include="Network\SyncReport.cs" />
<Compile Include="TraitDictionary.cs" />
<Compile Include="Traits\PrimaryBuilding.cs" />
<Compile Include="Traits\SharesCell.cs" />
<Compile Include="Traits\Valued.cs" />
<Compile Include="Traits\World\BibLayer.cs" />
<Compile Include="Widgets\Delegates\DeveloperModeDelegate.cs" />
<Compile Include="Widgets\ScrollingTextWidget.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">

View File

@@ -35,8 +35,11 @@ namespace OpenRA.Orders
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left && world.Map.IsInMap(xy))
yield return new Order(order, subject, xy);
if( mi.Button == MouseButton.Left && world.Map.IsInMap( xy ) )
{
world.CancelInputMode();
yield return new Order( order, subject, xy );
}
}
public virtual void Tick(World world) { }

View File

@@ -11,7 +11,8 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Orders
{
@@ -25,17 +26,17 @@ namespace OpenRA.Orders
.FirstOrDefault();
var orders = world.Selection.Actors
.Select(a => a.Order(xy, mi, underCursor))
.Select(a => OrderForUnit(a, xy, mi, underCursor))
.Where(o => o != null)
.ToArray();
var actorsInvolved = orders.Select(o => o.Subject).Distinct();
var actorsInvolved = orders.Select(o => o.self).Distinct();
if (actorsInvolved.Any())
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor,
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()));
foreach (var o in orders)
yield return o;
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()));
foreach( var o in orders )
yield return CheckSameOrder( o.iot, o.trait.IssueOrder( o.self, o.iot, o.target ) );
}
public void Tick( World world ) {}
@@ -45,39 +46,107 @@ namespace OpenRA.Orders
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
t.RenderBeforeWorld(a);
t.RenderBeforeWorld(a);
Game.Renderer.Flush();
}
public void RenderAfterWorld( World world )
{
foreach (var a in world.Selection.Actors)
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
t.RenderAfterWorld(a);
t.RenderAfterWorld(a);
Game.Renderer.Flush();
}
public string GetCursor( World world, int2 xy, MouseInput mi )
{
if (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.Info.Traits.Contains<SelectableInfo>())
.Any();
if (underCursor)
return "select";
}
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.FirstOrDefault();
var c = Order(world, xy, mi)
.Select(o => o.Subject.TraitsImplementing<IOrderCursor>()
.Select(pc => pc.CursorForOrder(o.Subject, o)).FirstOrDefault(a => a != null))
.FirstOrDefault(a => a != null);
return c ?? "default";
if( mi.Modifiers.HasModifier( Modifiers.Shift ) || !world.Selection.Actors.Any() )
if( underCursor != null )
return "select";
var orders = world.Selection.Actors
.Select(a => OrderForUnit(a, xy, mi, underCursor))
.Where(o => o != null)
.ToArray();
if( orders.Length == 0 ) return "default";
return orders[ 0 ].cursor ?? "default";
}
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
{
if (self.Owner != self.World.LocalPlayer)
return null;
if (!self.World.Map.IsInMap(xy.X, xy.Y))
return null;
if (self.Destroyed)
return null;
//var old = self.TraitsImplementing<IIssueOrder>()
// .OrderByDescending( x => x.OrderPriority( self, xy, mi, underCursor ) )
// .Select( x => x.IssueOrder( self, xy, mi, underCursor ) )
// .FirstOrDefault( x => x != null );
//if( old != null )
// return old;
if( mi.Button == MouseButton.Right )
{
var uim = self.World.WorldActor.Trait<UnitInfluence>();
foreach( var o in self.TraitsImplementing<IIssueOrder>()
.SelectMany( trait => trait.Orders
.Select( x => new { Trait = trait, Order = x } ) )
.OrderByDescending( x => x.Order.OrderPriority ) )
{
var actorsAt = uim.GetUnitsAt( xy ).ToList();
string cursor = null;
if( underCursor != null )
if( o.Order.CanTargetUnit( self, underCursor, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromActor( underCursor ) );
if( o.Order.CanTargetLocation( self, xy, actorsAt, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromCell( xy ) );
}
}
return null;
}
static Order CheckSameOrder( IOrderTargeter iot, Order order )
{
if( order == null && iot.OrderID != null )
Game.Debug( "BUG: in order targeter - decided on {0} but then didn't order", iot.OrderID );
else if( iot.OrderID != order.OrderString )
Game.Debug( "BUG: in order targeter - decided on {0} but ordered {1}", iot.OrderID, order.OrderString );
return order;
}
class UnitOrderResult
{
public readonly Actor self;
public readonly IOrderTargeter iot;
public readonly IIssueOrder trait;
public readonly string cursor;
public readonly Target target;
public UnitOrderResult( Actor self, IOrderTargeter iot, IIssueOrder trait, string cursor, Target target )
{
this.self = self;
this.iot = iot;
this.trait = trait;
this.cursor = cursor;
this.target = target;
}
}
}
}

View File

@@ -207,11 +207,11 @@ namespace OpenRA
public struct CellInfo
{
public float MinCost;
public int MinCost;
public int2 Path;
public bool Seen;
public CellInfo( float minCost, int2 path, bool seen )
public CellInfo( int minCost, int2 path, bool seen )
{
MinCost = minCost;
Path = path;
@@ -221,10 +221,10 @@ namespace OpenRA
public struct PathDistance : IComparable<PathDistance>
{
public float EstTotal;
public int EstTotal;
public int2 Location;
public PathDistance(float estTotal, int2 location)
public PathDistance(int estTotal, int2 location)
{
EstTotal = estTotal;
Location = location;

View File

@@ -20,7 +20,7 @@ namespace OpenRA
World world;
public CellInfo[ , ] cellInfo;
public PriorityQueue<PathDistance> queue;
public Func<int2, float> heuristic;
public Func<int2, int> heuristic;
Func<int2, bool> customBlock;
public bool checkForBlocked;
public Actor ignoreBuilding;
@@ -58,7 +58,7 @@ namespace OpenRA
return this;
}
public PathSearch WithHeuristic(Func<int2, float> h)
public PathSearch WithHeuristic(Func<int2, int> h)
{
heuristic = h;
return this;
@@ -66,7 +66,7 @@ namespace OpenRA
public PathSearch WithoutLaneBias()
{
LaneBias = 0f;
LaneBias = 0;
return this;
}
@@ -76,7 +76,7 @@ namespace OpenRA
return this;
}
float LaneBias = .5f;
int LaneBias = 1;
public int2 Expand( World world )
{
@@ -91,7 +91,7 @@ namespace OpenRA
var thisCost = Mobile.MovementCostForCell(mobileInfo, world, p.Location);
if (thisCost == float.PositiveInfinity)
if (thisCost == int.MaxValue)
return p.Location;
foreach( int2 d in directions )
@@ -104,7 +104,7 @@ namespace OpenRA
var costHere = Mobile.MovementCostForCell(mobileInfo, world, newHere);
if (costHere == float.PositiveInfinity)
if (costHere == int.MaxValue)
continue;
if (!Mobile.CanEnterCell(mobileInfo, world, uim, bim, newHere, ignoreBuilding, checkForBlocked))
@@ -114,10 +114,11 @@ namespace OpenRA
continue;
var est = heuristic( newHere );
if( est == float.PositiveInfinity )
if( est == int.MaxValue )
continue;
float cellCost = ((d.X * d.Y != 0) ? 1.414213563f : 1.0f) * costHere;
int cellCost = costHere;
if( d.X * d.Y != 0 ) cellCost = ( cellCost * 34 ) / 24;
// directional bonuses for smoother flow!
var ux = (newHere.X + (inReverse ? 1 : 0) & 1);
@@ -128,7 +129,7 @@ namespace OpenRA
if (uy == 0 && d.X < 0) cellCost += LaneBias;
else if (uy == 1 && d.X > 0) cellCost += LaneBias;
float newCost = cellInfo[ p.Location.X, p.Location.Y ].MinCost + cellCost;
int newCost = cellInfo[ p.Location.X, p.Location.Y ].MinCost + cellCost;
if( newCost >= cellInfo[ newHere.X, newHere.Y ].MinCost )
continue;
@@ -199,18 +200,18 @@ namespace OpenRA
var cellInfo = new CellInfo[ world.Map.MapSize.X, world.Map.MapSize.Y ];
for( int x = 0 ; x < world.Map.MapSize.X ; x++ )
for( int y = 0 ; y < world.Map.MapSize.Y ; y++ )
cellInfo[ x, y ] = new CellInfo( float.PositiveInfinity, new int2( x, y ), false );
cellInfo[ x, y ] = new CellInfo( int.MaxValue, new int2( x, y ), false );
return cellInfo;
}
public static Func<int2, float> DefaultEstimator( int2 destination )
public static Func<int2, int> DefaultEstimator( int2 destination )
{
return here =>
{
int2 d = ( here - destination ).Abs();
int diag = Math.Min( d.X, d.Y );
int straight = Math.Abs( d.X - d.Y );
return 1.5f * diag + straight;
return (3400 * diag / 24) + (100 * straight);
};
}
}

View File

@@ -49,6 +49,7 @@ namespace OpenRA
Index = index;
Palette = "player"+index;
Color = pr.Color;
Color2 = pr.Color2;
ClientIndex = 0; /* it's a map player, "owned" by host */

View File

@@ -42,7 +42,7 @@ namespace OpenRA
else
actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList();
var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasVoice());
var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoice());
if (voicedUnit != null)
Sound.PlayVoice("Select", voicedUnit, voicedUnit.Owner.Country.Race);
@@ -56,6 +56,10 @@ namespace OpenRA
public void Tick(World world)
{
actors.RemoveAll(a => !a.IsInWorld);
foreach (var cg in controlGroups.Values)
cg.RemoveAll(a => a.Destroyed); // note: NOT `!a.IsInWorld`, since that would remove things
// that are in transports.
}
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());

1
OpenRA.Game/Server/Exts.cs Normal file → Executable file
View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System;
namespace OpenRA.Server
{

60
OpenRA.Game/Server/MasterServerQuery.cs Normal file → Executable file
View File

@@ -14,15 +14,20 @@ using System.Net;
using System.Text;
using System.Threading;
using OpenRA.FileFormats;
using OpenRA.Widgets;
namespace OpenRA.Server
{
static class MasterServerQuery
{
public static event Action<GameServer[]> OnComplete = _ => { };
public static event Action<string> OnVersion = _ => { };
static GameServer[] Games = { };
public static string ClientVersion = "";
public static string ServerVersion = "";
static AutoResetEvent ev = new AutoResetEvent(false);
static AutoResetEvent ev2 = new AutoResetEvent(false);
public static void Refresh(string masterServerUrl)
{
@@ -30,9 +35,7 @@ namespace OpenRA.Server
{
try
{
var wc = new WebClient();
var data = wc.DownloadData(new Uri(masterServerUrl + "list.php"));
var str = Encoding.UTF8.GetString(data);
var str = GetData(new Uri(masterServerUrl + "list.php"));
var yaml = MiniYaml.FromString(str);
@@ -48,10 +51,61 @@ namespace OpenRA.Server
}).Start();
}
public static void GetMOTD(string masterServerUrl)
{
var motd = Widget.RootWidget.GetWidget<ScrollingTextWidget>("MOTD_SCROLLER");
// Runs in a separate thread to prevent dns lookup hitches
new Thread(() =>
{
if (motd != null)
{
try
{
motd.SetText(GetData(new Uri(masterServerUrl + "motd.php?v=" + ClientVersion)));
motd.ResetScroll();
}
catch
{
motd.SetText("Welcome to OpenRA. MOTD unable to be loaded from server.");
motd.ResetScroll();
}
}
ev.Set();
}).Start();
}
public static void Tick()
{
if (ev.WaitOne(TimeSpan.FromMilliseconds(0)))
OnComplete(Games);
if (ev2.WaitOne(TimeSpan.FromMilliseconds(0)))
OnVersion(ServerVersion);
}
static string GetData(Uri uri)
{
var wc = new WebClient();
var data = wc.DownloadData(uri);
return Encoding.UTF8.GetString(data);
}
public static void GetCurrentVersion(string masterServerUrl)
{
new Thread(() =>
{
try
{
ServerVersion = GetData(new Uri(masterServerUrl + "VERSION"));
}
catch
{
ServerVersion = "";
}
ev2.Set();
}).Start();
}
}

View File

@@ -164,7 +164,8 @@ namespace OpenRA.Server
static int ChooseFreeSlot()
{
return lobbyInfo.Slots.First(s => !s.Closed && s.Bot == null).Index;
return lobbyInfo.Slots.First(s => !s.Closed && s.Bot == null
&& !lobbyInfo.Clients.Any( c => c.Slot == s.Index )).Index;
}
static void AcceptConnection()
@@ -588,8 +589,9 @@ namespace OpenRA.Server
static void SyncLobbyInfo()
{
DispatchOrders(null, 0,
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
if (!GameStarted) /* don't do this while the game is running, it breaks things. */
DispatchOrders(null, 0,
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
PingMasterServer();
}

View File

@@ -151,65 +151,39 @@ namespace OpenRA
var minx = clipRect.Left;
var maxx = clipRect.Right;
var shroudPalette = "fog";
DrawShroud( minx, miny, maxx, maxy, fogSprites, "fog" );
DrawShroud( minx, miny, maxx, maxy, sprites, "shroud" );
}
void DrawShroud( int minx, int miny, int maxx, int maxy, Sprite[,] s, string pal )
{
var shroudPalette = Game.world.WorldRenderer.GetPaletteIndex(pal);
for (var j = miny; j < maxy; j++)
{
var starti = minx;
for (var i = minx; i < maxx; i++)
{
if (fogSprites[i, j] == shadowBits[0x0f])
if (s[i, j] == shadowBits[0x0f])
continue;
if (starti != i)
{
Game.Renderer.SpriteRenderer.DrawSprite(fogSprites[starti, j],
Game.CellSize * new float2(starti, j),
shroudPalette,
new float2(Game.CellSize * (i - starti), Game.CellSize));
starti = i+1;
}
Game.Renderer.SpriteRenderer.DrawSprite(fogSprites[i, j],
Game.CellSize * new float2(i, j),
shroudPalette);
starti = i+1;
}
if (starti < maxx)
Game.Renderer.SpriteRenderer.DrawSprite(fogSprites[starti, j],
Game.CellSize * new float2(starti, j),
shroudPalette,
new float2(Game.CellSize * (maxx - starti), Game.CellSize));
}
shroudPalette = "shroud";
for (var j = miny; j < maxy; j++)
{
var starti = minx;
for (var i = minx; i < maxx; i++)
{
if (sprites[i, j] == shadowBits[0x0f])
continue;
if (starti != i)
{
Game.Renderer.SpriteRenderer.DrawSprite(sprites[starti, j],
s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j),
shroudPalette,
new float2(Game.CellSize * (i - starti), Game.CellSize));
starti = i + 1;
}
Game.Renderer.SpriteRenderer.DrawSprite(sprites[i, j],
s[i, j].DrawAt(
Game.CellSize * new float2(i, j),
shroudPalette);
starti = i + 1;
}
if (starti < maxx)
Game.Renderer.SpriteRenderer.DrawSprite(sprites[starti, j],
s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j),
shroudPalette,
new float2(Game.CellSize * (maxx - starti), Game.CellSize));

View File

@@ -129,5 +129,34 @@ namespace OpenRA
return p.Index * 0x567;
return 0;
}
public static void CheckSyncUnchanged( World world, Action fn )
{
CheckSyncUnchanged( world, () => { fn(); return true; } );
}
static bool inUnsyncedCode = false;
public static T CheckSyncUnchanged<T>( World world, Func<T> fn )
{
int sync = world.SyncHash();
inUnsyncedCode = true;
try
{
return fn();
}
finally
{
inUnsyncedCode = false;
if( sync != world.SyncHash() )
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
}
}
public static void AssertUnsynced( string message )
{
if( !inUnsyncedCode )
throw new InvalidOperationException( message );
}
}
}

View File

@@ -8,19 +8,19 @@
*/
#endregion
using OpenRA.Traits;
using System.Collections.Generic;
namespace OpenRA.Traits.Activities
{
public class Drag : IActivity
{
public IActivity NextActivity { get; set; }
IActivity NextActivity { get; set; }
float2 endLocation;
float2 startLocation;
int2 endLocation;
int2 startLocation;
int length;
public Drag(float2 start, float2 end, int length)
public Drag(int2 start, int2 end, int length)
{
startLocation = start;
endLocation = end;
@@ -29,16 +29,32 @@ namespace OpenRA.Traits.Activities
int ticks = 0;
public IActivity Tick( Actor self )
{
self.CenterLocation = float2.Lerp(startLocation, endLocation, (float)ticks/(length-1));
Log.Write("debug", "drag #{0} {1} {2}", self.ActorID, ticks, self.CenterLocation);
{
var mobile = self.Trait<Mobile>();
mobile.PxPosition = int2.Lerp(startLocation, endLocation, ticks, length - 1);
if (++ticks >= length)
return NextActivity;
{
mobile.IsMoving = false;
return NextActivity;
}
mobile.IsMoving = true;
return this;
}
public void Cancel(Actor self) { }
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield return endLocation;
}
}
}

View File

@@ -10,11 +10,8 @@
namespace OpenRA.Traits.Activities
{
class Idle : IActivity
public class Idle : CancelableActivity
{
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self) { return NextActivity; }
public void Cancel(Actor self) {}
public override IActivity Tick(Actor self) { return NextActivity; }
}
}

View File

@@ -15,18 +15,14 @@ using System.Linq;
namespace OpenRA.Traits.Activities
{
public class Move : IActivity
public class Move : CancelableActivity
{
public IActivity NextActivity { get; set; }
int2? destination;
int nearEnough;
public List<int2> path;
Func<Actor, Mobile, List<int2>> getPath;
public Actor ignoreBuilding;
bool cancellable = true;
MovePart move;
int ticksBeforePathing;
const int avgTicksBeforePathing = 5;
@@ -49,7 +45,6 @@ namespace OpenRA.Traits.Activities
.WithoutLaneBias());
this.destination = destination;
this.nearEnough = 0;
this.cancellable = false;
}
public Move( int2 destination, int nearEnough )
@@ -102,16 +97,29 @@ namespace OpenRA.Traits.Activities
this.nearEnough = 0;
}
public IActivity Tick( Actor self )
static int HashList<T>(List<T> xs)
{
int hash = 0;
int n = 0;
foreach (var x in xs)
hash += n++ * x.GetHashCode();
return hash;
}
List<int2> EvalPath( Actor self, Mobile mobile )
{
var path = getPath(self, mobile).TakeWhile(a => a != mobile.toCell).ToList();
mobile.PathHash = HashList(path);
Log.Write("debug", "EvalPathHash #{0} {1}",
self.ActorID, mobile.PathHash);
return path;
}
public override IActivity Tick( Actor self )
{
var mobile = self.Trait<Mobile>();
if( move != null )
{
move.TickMove( self, mobile, this );
return this;
}
if (destination == mobile.toCell)
return NextActivity;
@@ -123,7 +131,7 @@ namespace OpenRA.Traits.Activities
return this;
}
path = getPath( self, mobile ).TakeWhile( a => a != mobile.toCell ).ToList();
path = EvalPath(self, mobile);
SanityCheckPath( mobile );
}
@@ -144,24 +152,20 @@ namespace OpenRA.Traits.Activities
if( firstFacing != mobile.Facing )
{
path.Add( nextCell.Value );
Log.Write("debug", "Turn: #{0} from {1} to {2}",
self.ActorID, mobile.Facing, firstFacing);
return new Turn( firstFacing ) { NextActivity = this };
return Util.SequenceActivities( new Turn( firstFacing ), this ).Tick( self );
}
else
{
mobile.toCell = nextCell.Value;
move = new MoveFirstHalf(
mobile.SetLocation( mobile.fromCell, nextCell.Value );
var move = new MoveFirstHalf(
this,
Util.CenterOfCell( mobile.fromCell ),
Util.BetweenCells( mobile.fromCell, mobile.toCell ),
mobile.Facing,
mobile.Facing,
0 );
move.TickMove( self, mobile, this );
return this;
return move.Tick( self );
}
}
@@ -221,7 +225,7 @@ namespace OpenRA.Traits.Activities
return null;
mobile.RemoveInfluence();
var newPath = getPath( self, mobile ).TakeWhile(a => a != mobile.toCell).ToList();
var newPath = EvalPath(self, mobile);
mobile.AddInfluence();
if (newPath.Count != 0)
@@ -235,64 +239,98 @@ namespace OpenRA.Traits.Activities
return nextCell;
}
public void Cancel( Actor self )
protected override bool OnCancel()
{
if (!cancellable) return;
path = new List<int2>();
NextActivity = null;
return true;
}
abstract class MovePart
public override IEnumerable<float2> GetCurrentPath()
{
public readonly float2 from, to;
if( path != null )
return Enumerable.Reverse(path).Select( c => (float2)Util.CenterOfCell(c) );
if( destination != null )
return new float2[] { destination.Value };
return new float2[ 0 ];
}
abstract class MovePart : IActivity
{
public readonly Move move;
public readonly int2 from, to;
public readonly int fromFacing, toFacing;
public int moveFraction;
public readonly int moveFractionTotal;
public MovePart( float2 from, float2 to, int fromFacing, int toFacing, int startingFraction )
public MovePart( Move move, int2 from, int2 to, int fromFacing, int toFacing, int startingFraction )
{
this.move = move;
this.from = from;
this.to = to;
this.fromFacing = fromFacing;
this.toFacing = toFacing;
this.moveFraction = startingFraction;
this.moveFractionTotal = (int)(( to - from ).Length*3);
this.moveFractionTotal = ( ( to - from ) * 3 ).Length;
}
public void TickMove( Actor self, Mobile mobile, Move parent )
public void Cancel( Actor self )
{
moveFraction += (int)mobile.MovementSpeedForCell(self, mobile.toCell);
if( moveFraction >= moveFractionTotal )
move.Cancel( self );
}
public void Queue( IActivity activity )
{
move.Queue( activity );
}
public IActivity Tick( Actor self )
{
var mobile = self.Trait<Mobile>();
var ret = InnerTick( self, mobile );
mobile.IsMoving = ( ret is MovePart );
if( moveFraction > moveFractionTotal )
moveFraction = moveFractionTotal;
UpdateCenterLocation( self, mobile );
if( moveFraction >= moveFractionTotal )
{
parent.move = OnComplete( self, mobile, parent );
if( parent.move == null )
UpdateCenterLocation( self, mobile );
}
return ret;
}
IActivity InnerTick( Actor self, Mobile mobile )
{
moveFraction += (int)mobile.MovementSpeedForCell(self, mobile.toCell);
if( moveFraction <= moveFractionTotal )
return this;
var next = OnComplete( self, mobile, move );
if( next != null )
return next;
return move;
}
void UpdateCenterLocation( Actor self, Mobile mobile )
{
var frac = (float)moveFraction / moveFractionTotal;
self.CenterLocation = float2.Lerp( from, to, frac );
mobile.PxPosition = int2.Lerp( from, to, moveFraction, moveFractionTotal );
if( moveFraction >= moveFractionTotal )
mobile.Facing = toFacing & 0xFF;
else
mobile.Facing = ( fromFacing + ( toFacing - fromFacing ) * moveFraction / moveFractionTotal ) & 0xFF;
mobile.Facing = int2.Lerp( fromFacing, toFacing, moveFraction, moveFractionTotal ) & 0xFF;
}
protected abstract MovePart OnComplete( Actor self, Mobile mobile, Move parent );
public IEnumerable<float2> GetCurrentPath()
{
return move.GetCurrentPath();
}
}
class MoveFirstHalf : MovePart
{
public MoveFirstHalf( float2 from, float2 to, int fromFacing, int toFacing, int startingFraction )
: base( from, to, fromFacing, toFacing, startingFraction )
public MoveFirstHalf( Move move, int2 from, int2 to, int fromFacing, int toFacing, int startingFraction )
: base( move, from, to, fromFacing, toFacing, startingFraction )
{
}
@@ -304,40 +342,41 @@ namespace OpenRA.Traits.Activities
if( ( nextCell - mobile.toCell ) != ( mobile.toCell - mobile.fromCell ) )
{
var ret = new MoveFirstHalf(
move,
Util.BetweenCells( mobile.fromCell, mobile.toCell ),
Util.BetweenCells( mobile.toCell, nextCell.Value ),
mobile.Facing,
Util.GetNearestFacing( mobile.Facing, Util.GetFacing( nextCell.Value - mobile.toCell, mobile.Facing ) ),
moveFraction - moveFractionTotal );
mobile.fromCell = mobile.toCell;
mobile.toCell = nextCell.Value;
mobile.SetLocation( mobile.toCell, nextCell.Value );
return ret;
}
else
parent.path.Add( nextCell.Value );
}
var ret2 = new MoveSecondHalf(
move,
Util.BetweenCells( mobile.fromCell, mobile.toCell ),
Util.CenterOfCell( mobile.toCell ),
mobile.Facing,
mobile.Facing,
moveFraction - moveFractionTotal );
mobile.fromCell = mobile.toCell;
mobile.SetLocation( mobile.toCell, mobile.toCell );
return ret2;
}
}
class MoveSecondHalf : MovePart
{
public MoveSecondHalf( float2 from, float2 to, int fromFacing, int toFacing, int startingFraction )
: base( from, to, fromFacing, toFacing, startingFraction )
public MoveSecondHalf( Move move, int2 from, int2 to, int fromFacing, int toFacing, int startingFraction )
: base( move, from, to, fromFacing, toFacing, startingFraction )
{
}
protected override MovePart OnComplete( Actor self, Mobile mobile, Move parent )
{
self.CenterLocation = Util.CenterOfCell( mobile.toCell );
mobile.fromCell = mobile.toCell;
mobile.PxPosition = Util.CenterOfCell( mobile.toCell );
mobile.SetLocation( mobile.toCell, mobile.toCell );
mobile.FinishedMoving(self);
return null;
}

View File

@@ -10,18 +10,13 @@
namespace OpenRA.Traits.Activities
{
public class RemoveSelf : IActivity
public class RemoveSelf : CancelableActivity
{
bool isCanceled;
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self)
public override IActivity Tick(Actor self)
{
if (isCanceled) return NextActivity;
if (IsCanceled) return NextActivity;
self.Destroy();
return null;
}
public void Cancel(Actor self) { isCanceled = true; NextActivity = null; }
}
}

View File

@@ -8,11 +8,13 @@
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Traits.Activities
{
class Sell : IActivity
{
public IActivity NextActivity { get; set; }
IActivity NextActivity { get; set; }
bool started;
@@ -55,5 +57,18 @@ namespace OpenRA.Traits.Activities
}
public void Cancel(Actor self) { /* never gonna give you up.. */ }
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}

View File

@@ -12,9 +12,8 @@ using System.Linq;
namespace OpenRA.Traits.Activities
{
public class Turn : IActivity
public class Turn : CancelableActivity
{
public IActivity NextActivity { get; set; }
int desiredFacing;
public Turn( int desiredFacing )
@@ -22,8 +21,9 @@ namespace OpenRA.Traits.Activities
this.desiredFacing = desiredFacing;
}
public IActivity Tick( Actor self )
public override IActivity Tick( Actor self )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if( desiredFacing == facing.Facing )
@@ -32,11 +32,5 @@ namespace OpenRA.Traits.Activities
return this;
}
public void Cancel( Actor self )
{
desiredFacing = self.Trait<IFacing>().Facing;
NextActivity = null;
}
}
}

View File

@@ -44,16 +44,16 @@ namespace OpenRA.Traits
public readonly BuildingInfo Info;
[Sync]
readonly int2 topLeft;
readonly PowerManager PlayerPower;
public int2 PxPosition { get { return ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; } }
public Building(ActorInitializer init)
{
this.self = init.self;
this.topLeft = init.Get<LocationInit,int2>();
Info = self.Info.Traits.Get<BuildingInfo>();
self.CenterLocation = Game.CellSize
* ((float2)topLeft + .5f * (float2)Info.Dimensions);
PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
}
@@ -64,19 +64,14 @@ namespace OpenRA.Traits
return Info.Power;
var health = self.TraitOrDefault<Health>();
var healthFraction = (health == null) ? 1f : health.HPFraction;
return (int)(healthFraction * Info.Power);
return health != null ? (Info.Power * health.HP / health.MaxHP) : Info.Power;
}
public void Damaged(Actor self, AttackInfo e)
{
// Power plants lose power with damage
if (Info.Power > 0)
{
var health = self.TraitOrDefault<Health>();
var healthFraction = (health == null) ? 1f : health.HPFraction;
PlayerPower.UpdateActor(self, (int)(healthFraction * Info.Power));
}
PlayerPower.UpdateActor(self, GetPowerUsage());
if (e.DamageState == DamageState.Dead)
{

View File

@@ -53,6 +53,9 @@ namespace OpenRA.Traits
if ((lifetime <= 0 || --lifetime <= 0) && !force)
return;
if (!target.IsValid)
return;
var p = target.CenterLocation;
Game.Renderer.LineRenderer.DrawLine(self.CenterLocation, p, c, c);

6
OpenRA.Game/Traits/Health.cs Normal file → Executable file
View File

@@ -140,6 +140,8 @@ namespace OpenRA.Traits
{
public static bool IsDead(this Actor self)
{
if (self.Destroyed) return true;
var health = self.TraitOrDefault<Health>();
return (health == null) ? true : health.IsDead;
}
@@ -161,7 +163,9 @@ namespace OpenRA.Traits
{
var health = self.TraitOrDefault<Health>();
if (health == null) return;
health.InflictDamage(self, attacker, health.HP, null);
/* hack. Fix for proper */
health.InflictDamage(self, attacker, int.MaxValue, null);
}
}
}

View File

@@ -15,6 +15,8 @@ using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits.Activities;
using OpenRA.FileFormats;
using System.Diagnostics;
using OpenRA.Orders;
namespace OpenRA.Traits
{
@@ -38,7 +40,7 @@ namespace OpenRA.Traits
foreach (var t in y.NodesDict["TerrainSpeeds"].Nodes)
{
var speed = (float)FieldLoader.GetValue("speed", typeof(float),t.Value.Value);
var cost = t.Value.NodesDict.ContainsKey("PathingCost") ? (float)FieldLoader.GetValue("cost", typeof(float), t.Value.NodesDict["PathingCost"].Value) : 1f/speed;
var cost = t.Value.NodesDict.ContainsKey("PathingCost") ? (int)FieldLoader.GetValue("cost", typeof(int), t.Value.NodesDict["PathingCost"].Value) : (int)(10000/speed);
ret.Add(t.Key, new TerrainInfo{Speed = speed, Cost = cost});
}
@@ -47,39 +49,51 @@ namespace OpenRA.Traits
public class TerrainInfo
{
public float Cost = float.PositiveInfinity;
public int Cost = int.MaxValue;
public float Speed = 0;
}
}
public class Mobile : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice, IOccupySpace, IMove, IFacing, INudge
public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IOccupySpace, IMove, IFacing, INudge
{
public readonly Actor self;
public readonly MobileInfo Info;
public bool IsMoving { get; internal set; }
int __facing;
int2 __fromCell, __toCell;
int __altitude;
[Sync]
public int Facing { get; set; }
public int Facing
{
get { return __facing; }
set { __facing = value; }
}
[Sync]
public int Altitude { get; set; }
public int Altitude
{
get { return __altitude; }
set { __altitude = value; }
}
public int ROT { get { return Info.ROT; } }
public int InitialFacing { get { return Info.InitialFacing; } }
int2 __fromCell, __toCell;
public int2 fromCell
{
get { return __fromCell; }
set { SetLocation( value, __toCell ); }
}
[Sync]
public int2 toCell
public int2 PxPosition { get; set; }
[Sync]
public int2 fromCell { get { return __fromCell; } }
[Sync]
public int2 toCell { get { return __toCell; } }
[Sync]
public int PathHash; // written by Move.EvalPath, to temporarily debug this crap.
public void SetLocation(int2 from, int2 to)
{
get { return __toCell; }
set { SetLocation( __fromCell, value ); }
}
void SetLocation( int2 from, int2 to )
{
if( fromCell == from && toCell == to ) return;
if (fromCell == from && toCell == to) return;
RemoveInfluence();
__fromCell = from;
__toCell = to;
@@ -98,6 +112,7 @@ namespace OpenRA.Traits
if (init.Contains<LocationInit>())
{
this.__fromCell = this.__toCell = init.Get<LocationInit,int2>();
this.PxPosition = Util.CenterOfCell( fromCell );
AddInfluence();
}
@@ -108,24 +123,27 @@ namespace OpenRA.Traits
public void SetPosition(Actor self, int2 cell)
{
SetLocation( cell, cell );
self.CenterLocation = Util.CenterOfCell(fromCell);
PxPosition = Util.CenterOfCell(fromCell);
}
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public void SetPxPosition( Actor self, int2 px )
{
// Force move takes precedence
return mi.Modifiers.HasModifier(Modifiers.Alt) ? int.MaxValue : 0;
var cell = Util.CellContaining( px );
SetLocation( cell, cell );
PxPosition = px;
}
public IEnumerable<IOrderTargeter> Orders { get { yield return new MoveOrderTargeter( Info ); } }
// Note: Returns a valid order even if the unit can't move to the target
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
{
if (Info.OnRails) return null;
if (mi.Button == MouseButton.Left) return null;
var type = (!self.World.LocalPlayer.Shroud.IsVisible(xy) || CanEnterCell(xy)) ? "Move" : "Move-Blocked";
return new Order(type, self, xy, mi.Modifiers.HasModifier(Modifiers.Shift));
if( order is MoveOrderTargeter )
{
if( Info.OnRails ) return null;
return new Order( "Move", self, Util.CellContaining( target.CenterLocation ), false );
}
return null;
}
public int2 NearestMoveableCell(int2 target)
@@ -150,7 +168,7 @@ namespace OpenRA.Traits
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Move" || order.OrderString == "Move-Blocked")
if (order.OrderString == "Move")
{
int2 currentLocation = NearestMoveableCell(order.TargetLocation);
if (!CanEnterCell(currentLocation))
@@ -170,20 +188,9 @@ namespace OpenRA.Traits
}
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString == "Move")
return "move";
if (order.OrderString == "Move-Blocked")
return "move-blocked";
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
if (order.OrderString == "Move" || order.OrderString == "Move-Blocked")
if (order.OrderString == "Move")
return "Move";
return null;
}
@@ -220,7 +227,7 @@ namespace OpenRA.Traits
public static bool CanEnterCell( MobileInfo mobileInfo, World world, UnitInfluence uim, BuildingInfluence bim, int2 cell, Actor ignoreActor, bool checkTransientActors )
{
if (MovementCostForCell(mobileInfo, world, cell) == float.PositiveInfinity)
if (MovementCostForCell(mobileInfo, world, cell) == int.MaxValue)
return false;
// Check for buildings
@@ -265,19 +272,14 @@ namespace OpenRA.Traits
}
}
public float MovementCostForCell( Actor self, int2 cell )
{
return MovementCostForCell( Info, self.World, cell );
}
public static float MovementCostForCell(MobileInfo info, World world, int2 cell)
public static int MovementCostForCell(MobileInfo info, World world, int2 cell)
{
if (!world.Map.IsInMap(cell.X,cell.Y))
return float.PositiveInfinity;
return int.MaxValue;
var type = world.GetTerrainType(cell);
if (!info.TerrainSpeeds.ContainsKey(type))
return float.PositiveInfinity;
return int.MaxValue;
return info.TerrainSpeeds[type].Cost;
}
@@ -293,15 +295,7 @@ namespace OpenRA.Traits
.TraitsImplementing<ISpeedModifier>()
.Select(t => t.GetSpeedModifier())
.Product();
return Info.Speed * Info.TerrainSpeeds[type].Speed * modifier;
}
public IEnumerable<float2> GetCurrentPath(Actor self)
{
var move = self.GetCurrentActivity() as Move;
if (move == null || move.path == null) return new float2[] { };
return Enumerable.Reverse(move.path).Select( c => Util.CenterOfCell(c) );
return Info.Speed * Info.TerrainSpeeds[type].Speed * modifier / 100f;
}
public void AddInfluence()
@@ -362,5 +356,31 @@ namespace OpenRA.Traits
Log.Write("debug", "OnNudge #{0} refuses at {1}",
self.ActorID, self.Location);
}
class MoveOrderTargeter : IOrderTargeter
{
readonly MobileInfo unitType;
public MoveOrderTargeter( MobileInfo unitType )
{
this.unitType = unitType;
}
public string OrderID { get { return "Move"; } }
public int OrderPriority { get { return 4; } }
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
return false;
}
public bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
{
cursor = "move";
if( self.World.LocalPlayer.Shroud.IsVisible( location ) && !self.Trait<Mobile>().CanEnterCell( location ) )
cursor = "move-blocked";
return true;
}
}
}
}

View File

@@ -68,17 +68,14 @@ namespace OpenRA.Traits
}
case "DevShroud":
{
DisableShroud ^= true;
if (self.World.LocalPlayer == self.Owner)
{
DisableShroud ^= true;
Game.world.LocalPlayer.Shroud.Disabled = DisableShroud;
}
self.World.LocalPlayer.Shroud.Disabled = DisableShroud;
break;
}
case "DevPathDebug":
{
if (self.World.LocalPlayer == self.Owner)
PathDebug ^= true;
PathDebug ^= true;
break;
}
case "DevUnitDebug":
@@ -86,17 +83,17 @@ namespace OpenRA.Traits
if (self.World.LocalPlayer == self.Owner)
Game.Settings.Debug.ShowCollisions ^= true;
break;
}
case "DevGiveExploration":
{
if (self.World.LocalPlayer == self.Owner)
self.World.WorldActor.Trait<Shroud>().ExploreAll(self.World);
break;
}
default:
case "DevGiveExploration":
{
if (self.World.LocalPlayer == self.Owner)
self.World.WorldActor.Trait<Shroud>().ExploreAll(self.World);
break;
}
default:
return;
}
}
Game.Debug("Cheat used: {0} by {1}"
.F(order.OrderString, self.Owner.PlayerName));
}

View File

@@ -13,7 +13,7 @@ using System.Linq;
namespace OpenRA.Traits
{
class PlayerResourcesInfo : ITraitInfo
public class PlayerResourcesInfo : ITraitInfo
{
public readonly int InitialCash = 10000;
public readonly int InitialOre = 0;

View File

@@ -61,9 +61,10 @@ namespace OpenRA.Traits
void DrawHealthBar(Actor self, float2 xy, float2 Xy)
{
if (!self.IsInWorld) return;
var health = self.TraitOrDefault<Health>();
if (self.IsDead() || health == null)
return;
if (health == null || health.IsDead) return;
var c = Color.Gray;
Game.Renderer.LineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
@@ -96,7 +97,7 @@ namespace OpenRA.Traits
var pipImages = new Animation("pips");
pipImages.PlayFetchIndex("groups", () => (int)group);
pipImages.Tick();
Game.Renderer.SpriteRenderer.DrawSprite(pipImages.Image, basePosition + new float2(-8, 1), "chrome");
pipImages.Image.DrawAt(basePosition + new float2(-8, 1), "chrome");
}
void DrawPips(Actor self, float2 basePosition)
@@ -122,7 +123,7 @@ namespace OpenRA.Traits
}
var pipImages = new Animation("pips");
pipImages.PlayRepeating(pipStrings[(int)pip]);
Game.Renderer.SpriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, "chrome");
pipImages.Image.DrawAt(pipxyBase + pipxyOffset, "chrome");
pipxyOffset += new float2(4, 0);
}
// Increment row
@@ -148,7 +149,7 @@ namespace OpenRA.Traits
var tagImages = new Animation("pips");
tagImages.PlayRepeating(tagStrings[(int)tag]);
Game.Renderer.SpriteRenderer.DrawSprite(tagImages.Image, tagxyBase + tagxyOffset, "chrome");
tagImages.Image.DrawAt(tagxyBase + tagxyOffset, "chrome");
// Increment row
tagxyOffset.Y += 8;
@@ -158,13 +159,14 @@ namespace OpenRA.Traits
void DrawUnitPath(Actor self)
{
if (!Game.world.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
if (!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
var activity = self.GetCurrentActivity();
var mobile = self.TraitOrDefault<IMove>();
if (mobile != null)
if (activity != null && mobile != null)
{
var alt = new float2(0, -mobile.Altitude);
var path = mobile.GetCurrentPath(self);
var path = activity.GetCurrentPath();
var start = self.CenterLocation + alt;
var c = Color.Green;

0
OpenRA.Game/Traits/SharesCell.cs Normal file → Executable file
View File

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Traits
public class TargetableInfo : ITraitInfo
{
public readonly string[] TargetTypes = {};
public object Create( ActorInitializer init ) { return new Targetable(this); }
public virtual object Create( ActorInitializer init ) { return new Targetable(this); }
}
public class Targetable : ITargetable

View File

@@ -35,8 +35,15 @@ namespace OpenRA.Traits
public interface IRender { IEnumerable<Renderable> Render(Actor self); }
public interface IIssueOrder
{
Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor );
int OrderPriority( Actor self, int2 xy, MouseInput mi, Actor underCursor );
IEnumerable<IOrderTargeter> Orders { get; }
Order IssueOrder( Actor self, IOrderTargeter order, Target target );
}
public interface IOrderTargeter
{
string OrderID { get; }
int OrderPriority { get; }
bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor );
bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor );
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
public interface IOrderCursor { string CursorForOrder(Actor self, Order order); }
@@ -49,7 +56,6 @@ namespace OpenRA.Traits
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, int2 exit); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); }
public interface INotifyEnterCell { void OnEnterCell(Actor self, int2 cell); }
public interface IStoreOre { int Capacity { get; }}
public interface IDisable { bool Disabled { get; } }
@@ -64,18 +70,17 @@ namespace OpenRA.Traits
public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IOccupySpace
public interface IHasLocation
{
int2 PxPosition { get; }
}
public interface IOccupySpace : IHasLocation
{
int2 TopLeft { get; }
IEnumerable<int2> OccupiedCells();
}
public interface IOccupyAir
{
int2 TopLeft { get; }
IEnumerable<int2> OccupiedAirCells();
}
public static class IOccupySpaceExts
{
public static int2 NearestCellTo( this IOccupySpace ios, int2 other )
@@ -104,17 +109,15 @@ namespace OpenRA.Traits
public interface IPips { IEnumerable<PipType> GetPips(Actor self); }
public interface ITags { IEnumerable<TagType> GetTags(); }
public interface ITeleportable /* crap name! */
public interface ITeleportable : IHasLocation /* crap name! */
{
bool CanEnterCell(int2 location);
void SetPosition(Actor self, int2 cell);
void SetPxPosition(Actor self, int2 px);
}
public interface IMove : ITeleportable
{
float MovementCostForCell(Actor self, int2 cell);
float MovementSpeedForCell(Actor self, int2 cell);
IEnumerable<float2> GetCurrentPath(Actor self);
int Altitude { get; set; }
}
@@ -171,9 +174,41 @@ namespace OpenRA.Traits
public interface IActivity
{
IActivity NextActivity { get; set; }
IActivity Tick(Actor self);
void Cancel(Actor self);
void Queue(IActivity activity);
IEnumerable<float2> GetCurrentPath();
}
public abstract class CancelableActivity : IActivity
{
protected IActivity NextActivity { get; private set; }
protected bool IsCanceled { get; private set; }
public abstract IActivity Tick( Actor self );
protected virtual bool OnCancel() { return true; }
public void Cancel( Actor self )
{
IsCanceled = OnCancel();
if( IsCanceled )
NextActivity = null;
else
NextActivity.Cancel( self );
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public virtual IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
public interface IRenderOverlay { void Render(); }
@@ -203,9 +238,10 @@ namespace OpenRA.Traits
public static readonly Target None = new Target();
public bool IsValid { get { return valid && (actor == null || actor.IsInWorld); } }
public float2 CenterLocation { get { return actor != null ? actor.CenterLocation : pos.ToInt2(); } }
public int2 PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos.ToInt2(); } }
public float2 CenterLocation { get { return PxPosition; } }
public Actor Actor { get { return actor; } }
public bool IsActor { get { return actor != null; } }
public Actor Actor { get { return IsActor ? actor : null; } }
public bool IsActor { get { return actor != null && !actor.Destroyed; } }
}
}

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Traits
public static int GetFacing( float2 d, int currentFacing )
{
if( float2.WithinEpsilon( d, float2.Zero, 0.001f ) )
if (float2.WithinEpsilon(d, float2.Zero, 0.001f))
return currentFacing;
int highest = -1;
@@ -82,14 +82,14 @@ namespace OpenRA.Traits
ecc * (cosAngle * v.Y - sinAngle * v.X));
}
public static float2 CenterOfCell(int2 loc)
public static int2 CenterOfCell(int2 loc)
{
return new float2(12, 12) + Game.CellSize * (float2)loc;
return new int2( Game.CellSize / 2, Game.CellSize / 2 ) + Game.CellSize * loc;
}
public static float2 BetweenCells(int2 from, int2 to)
public static int2 BetweenCells(int2 from, int2 to)
{
return 0.5f * (CenterOfCell(from) + CenterOfCell(to));
return int2.Lerp( CenterOfCell( from ), CenterOfCell( to ), 1, 2 );
}
public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); }
@@ -106,7 +106,7 @@ namespace OpenRA.Traits
public static IActivity SequenceActivities(params IActivity[] acts)
{
return acts.Reverse().Aggregate(
(next, a) => { a.NextActivity = next; return a; });
(next, a) => { a.Queue( next ); return a; });
}
public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); }

23
OpenRA.Game/Traits/Valued.cs Executable file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRA.Traits
{
public class ValuedInfo : TraitInfo<Valued>
{
public readonly int Cost = 0;
}
public class TooltipInfo : TraitInfo<Tooltip>
{
public readonly string Description = "";
public readonly string Name = "";
public readonly string Icon = null;
public readonly string[] AlternateName = { };
}
public class Valued { }
public class Tooltip { }
}

2
OpenRA.Game/Traits/World/BibLayer.cs Normal file → Executable file
View File

@@ -84,7 +84,7 @@ namespace OpenRA.Traits
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(kv.Key))
continue;
Game.Renderer.SpriteRenderer.DrawSprite(bibSprites[kv.Value.type - 1][kv.Value.image],
bibSprites[kv.Value.type - 1][kv.Value.image].DrawAt(
Game.CellSize * kv.Key, "terrain");
}
}

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Traits
public class ResourceLayerInfo : TraitInfo<ResourceLayer> { }
public class ResourceLayer: IRenderOverlay, IWorldLoaded
{
{
World world;
public ResourceType[] resourceTypes;
@@ -37,6 +37,9 @@ namespace OpenRA.Traits
var miny = cliprect.Top;
var maxy = cliprect.Bottom;
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
rt.info.PaletteIndex = world.WorldRenderer.GetPaletteIndex(rt.info.Palette);
for (int x = minx; x < maxx; x++)
for (int y = miny; y < maxy; y++)
{
@@ -46,9 +49,9 @@ namespace OpenRA.Traits
var c = content[x, y];
if (c.image != null)
Game.Renderer.SpriteRenderer.DrawSprite(c.image[c.density],
c.image[c.density].DrawAt(
Game.CellSize * new int2(x, y),
c.type.info.Palette);
c.type.info.PaletteIndex);
}
}
@@ -146,6 +149,7 @@ namespace OpenRA.Traits
content[p.X, p.Y].type = null;
content[p.X, p.Y].image = null;
content[p.X, p.Y].density = 0;
world.Map.CustomTerrain[p.X, p.Y] = null;
}
public ResourceType GetResource(int2 p) { return content[p.X, p.Y].type; }

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Traits
public readonly string TerrainType = "Ore";
public Sprite[][] Sprites;
public int PaletteIndex;
public object Create(ActorInitializer init) { return new ResourceType(this); }
}

View File

@@ -45,9 +45,9 @@ namespace OpenRA.Traits
for (var i = 0; i <= bins.GetUpperBound(0); i++)
bins[i, j].Clear();
foreach (var a in self.World.Actors)
foreach (var a in self.World.Queries.WithTrait<IHasLocation>())
{
var bounds = a.GetBounds(true);
var bounds = a.Actor.GetBounds(true);
if (bounds.Right <= Game.CellSize * self.World.Map.XOffset) continue;
if (bounds.Bottom <= Game.CellSize * self.World.Map.YOffset) continue;
@@ -61,7 +61,7 @@ namespace OpenRA.Traits
for (var j = j1; j <= j2; j++)
for (var i = i1; i <= i2; i++)
bins[i, j].Add(a);
bins[i, j].Add(a.Actor);
}
}

View File

@@ -18,7 +18,7 @@ using OpenRA.Widgets;
namespace OpenRA
{
class UiOverlay
public class UiOverlay
{
Sprite buildOk, buildBlocked, unitDebug;
@@ -49,7 +49,7 @@ namespace OpenRA
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())
Game.Renderer.SpriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), "terrain");
unitDebug.DrawAt(Game.CellSize * new float2(i, j), "terrain");
}
}
@@ -63,23 +63,21 @@ namespace OpenRA
if (Rules.Info[name].Traits.Contains<LineBuildInfo>())
{
foreach (var t in LineBuildUtils.GetLineBuildCells(world, topLeft, name, bi))
Game.Renderer.SpriteRenderer.DrawSprite(world.IsCloseEnoughToBase(world.LocalPlayer, name, bi, t)
? buildOk : buildBlocked, Game.CellSize * t, "terrain");
(world.IsCloseEnoughToBase(world.LocalPlayer, name, bi, t) ? buildOk : buildBlocked)
.DrawAt(Game.CellSize * t, "terrain");
}
else
{
var res = world.WorldActor.Trait<ResourceLayer>();
var isCloseEnough = world.IsCloseEnoughToBase(world.LocalPlayer, name, bi, topLeft);
foreach (var t in Footprint.Tiles(name, bi, topLeft))
Game.Renderer.SpriteRenderer.DrawSprite((isCloseEnough && world.IsCellBuildable(t, bi.WaterBound) && res.GetResource(t) == null)
? buildOk : buildBlocked, Game.CellSize * t, "terrain");
((isCloseEnough && world.IsCellBuildable(t, bi.WaterBound) && res.GetResource(t) == null) ? buildOk : buildBlocked)
.DrawAt(Game.CellSize * t, "terrain");
}
Game.Renderer.SpriteRenderer.Flush();
}
}
static class LineBuildUtils
public static class LineBuildUtils
{
public static IEnumerable<int2> GetLineBuildCells(World world, int2 location, string name, BuildingInfo bi)
{

View File

@@ -41,8 +41,7 @@ namespace OpenRA.Widgets
if (DrawBackground)
WidgetUtils.DrawPanel("dialog3", chatLogArea);
Game.Renderer.RgbaSpriteRenderer.Flush();
Game.Renderer.Device.EnableScissor(chatLogArea.Left, chatLogArea.Top, chatLogArea.Width, chatLogArea.Height);
Game.Renderer.EnableScissor(chatLogArea.Left, chatLogArea.Top, chatLogArea.Width, chatLogArea.Height);
foreach (var line in recentLines.AsEnumerable().Reverse())
{
chatpos.Y -= 20;
@@ -52,8 +51,7 @@ namespace OpenRA.Widgets
Game.Renderer.RegularFont.DrawText(line.Text, chatpos + new int2(inset, 0), Color.White);
}
Game.Renderer.RgbaSpriteRenderer.Flush();
Game.Renderer.Device.DisableScissor();
Game.Renderer.DisableScissor();
}
public void AddLine(Color c, string from, string text)

View File

@@ -33,8 +33,6 @@ namespace OpenRA.Widgets
Game.Renderer.BoldFont.DrawText(text, RenderOrigin + new float2(3, 7), Color.White);
Game.Renderer.RegularFont.DrawText(content, RenderOrigin + new float2(3 + w, 7), Color.White);
Game.Renderer.RgbaSpriteRenderer.Flush();
}
}

View File

@@ -37,7 +37,6 @@ namespace OpenRA.Widgets
public override void DrawInner(World world)
{
WidgetUtils.FillRectWithColor(RenderBounds, GetColor());
Game.Renderer.LineRenderer.Flush();
}
}
}

View File

@@ -14,56 +14,37 @@ namespace OpenRA.Widgets.Delegates
{
public class ConnectionDialogsDelegate : IWidgetDelegate
{
public ConnectionDialogsDelegate()
[ObjectCreator.UseCtor]
public ConnectionDialogsDelegate( [ObjectCreator.Param( "widget" )] Widget widget )
{
var r = Widget.RootWidget;
r.GetWidget("CONNECTION_BUTTON_ABORT").OnMouseUp = mi => {
r.GetWidget("CONNECTION_BUTTON_ABORT").Parent.Visible = false;
widget.GetWidget("CONNECTION_BUTTON_ABORT").OnMouseUp = mi => {
widget.GetWidget("CONNECTION_BUTTON_ABORT").Parent.Visible = false;
Game.Disconnect();
return true;
};
r.GetWidget("CONNECTION_BUTTON_CANCEL").OnMouseUp = mi => {
r.GetWidget("CONNECTION_BUTTON_CANCEL").Parent.Visible = false;
widget.GetWidget<LabelWidget>("CONNECTING_DESC").GetText = () =>
"Connecting to {0}:{1}...".F(Game.CurrentHost, Game.CurrentPort);
}
}
public class ConnectionFailedDelegate : IWidgetDelegate
{
[ObjectCreator.UseCtor]
public ConnectionFailedDelegate( [ObjectCreator.Param( "widget" )] Widget widget )
{
widget.GetWidget("CONNECTION_BUTTON_CANCEL").OnMouseUp = mi => {
widget.GetWidget("CONNECTION_BUTTON_CANCEL").Parent.Visible = false;
Game.Disconnect();
return true;
};
r.GetWidget("CONNECTION_BUTTON_RETRY").OnMouseUp = mi => {
widget.GetWidget("CONNECTION_BUTTON_RETRY").OnMouseUp = mi => {
Game.JoinServer(Game.CurrentHost, Game.CurrentPort);
return true;
};
r.GetWidget<LabelWidget>("CONNECTING_DESC").GetText = () =>
"Connecting to {0}:{1}...".F(Game.CurrentHost, Game.CurrentPort);
r.GetWidget<LabelWidget>("CONNECTION_FAILED_DESC").GetText = () =>
widget.GetWidget<LabelWidget>("CONNECTION_FAILED_DESC").GetText = () =>
"Could not connect to {0}:{1}".F(Game.CurrentHost, Game.CurrentPort);
Game.ConnectionStateChanged += () =>
{
r.CloseWindow();
switch( Game.orderManager.Connection.ConnectionState )
{
case ConnectionState.PreConnecting:
r.OpenWindow("MAINMENU_BG");
break;
case ConnectionState.Connecting:
r.OpenWindow("CONNECTING_BG");
break;
case ConnectionState.NotConnected:
r.OpenWindow("CONNECTION_FAILED_BG");
break;
case ConnectionState.Connected:
r.OpenWindow("SERVER_LOBBY");
var lobby = r.GetWidget("SERVER_LOBBY");
lobby.GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true;
lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true;
lobby.GetWidget("DISCONNECT_BUTTON").Visible = true;
r.GetWidget("INGAME_ROOT").GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
break;
}
};
}
}
}

View File

@@ -14,26 +14,18 @@ using System.Net;
namespace OpenRA.Widgets.Delegates
{
public class CreateServerMenuDelegate : IWidgetDelegate
{
public CreateServerMenuDelegate()
{
[ObjectCreator.UseCtor]
public CreateServerMenuDelegate( [ObjectCreator.Param( "widget" )] Widget cs )
{
var settings = Game.Settings;
var r = Widget.RootWidget;
var cs = r.GetWidget("CREATESERVER_BG");
r.GetWidget("MAINMENU_BUTTON_CREATE").OnMouseUp = mi => {
r.OpenWindow("CREATESERVER_BG");
return true;
};
cs.GetWidget("BUTTON_CANCEL").OnMouseUp = mi => {
r.CloseWindow();
Widget.CloseWindow();
return true;
};
cs.GetWidget("BUTTON_START").OnMouseUp = mi => {
r.OpenWindow("SERVER_LOBBY");
var map = Game.modData.AvailableMaps.FirstOrDefault(m => m.Value.Selectable).Key;
settings.Server.Name = cs.GetWidget<TextFieldWidget>("GAME_TITLE").Text;

212
OpenRA.Game/Widgets/Delegates/LobbyDelegate.cs Normal file → Executable file
View File

@@ -12,7 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Network;
using OpenRA.Network;
namespace OpenRA.Widgets.Delegates
{
@@ -22,12 +22,13 @@ namespace OpenRA.Widgets.Delegates
Dictionary<string, string> CountryNames;
string MapUid;
MapStub Map;
MapStub Map;
public static Color CurrentColorPreview1;
public static Color CurrentColorPreview2;
public LobbyDelegate()
[ObjectCreator.UseCtor]
public LobbyDelegate( [ObjectCreator.Param( "widget" )] Widget lobby )
{
Game.LobbyInfoChanged += UpdateCurrentMap;
UpdateCurrentMap();
@@ -35,9 +36,7 @@ namespace OpenRA.Widgets.Delegates
CurrentColorPreview1 = Game.Settings.Player.Color1;
CurrentColorPreview2 = Game.Settings.Player.Color2;
var r = Widget.RootWidget;
var lobby = r.GetWidget("SERVER_LOBBY");
Players = Widget.RootWidget.GetWidget("SERVER_LOBBY").GetWidget("PLAYERS");
Players = lobby.GetWidget("PLAYERS");
LocalPlayerTemplate = Players.GetWidget("TEMPLATE_LOCAL");
RemotePlayerTemplate = Players.GetWidget("TEMPLATE_REMOTE");
EmptySlotTemplate = Players.GetWidget("TEMPLATE_EMPTY");
@@ -74,8 +73,7 @@ namespace OpenRA.Widgets.Delegates
var mapButton = lobby.GetWidget("CHANGEMAP_BUTTON");
mapButton.OnMouseUp = mi =>
{
r.GetWidget("MAP_CHOOSER").SpecialOneArg(MapUid);
r.OpenWindow("MAP_CHOOSER");
Widget.OpenWindow("MAP_CHOOSER").SpecialOneArg(MapUid); // WTF
return true;
};
@@ -135,74 +133,74 @@ namespace OpenRA.Widgets.Delegates
teamChat ^= true;
chatLabel.Text = (teamChat) ? "Team:" : "Chat:";
return true;
};
var colorChooser = lobby.GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
hueSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
satSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
lumSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
rangeSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.GetWidget<ButtonWidget>("BUTTON_OK").OnMouseUp = mi =>
{
colorChooser.IsVisible = () => false;
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
UpdatePlayerColor(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
return true;
};
}
void UpdatePlayerColor(float hf, float sf, float lf, float r)
{
var c1 = ColorFromHSL(hf, sf, lf);
var c2 = ColorFromHSL(hf, sf, r*lf);
Game.Settings.Player.Color1 = c1;
Game.Settings.Player.Color2 = c2;
Game.Settings.Save();
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void UpdateColorPreview(float hf, float sf, float lf, float r)
{
CurrentColorPreview1 = ColorFromHSL(hf, sf, lf);
CurrentColorPreview2 = ColorFromHSL(hf, sf, r*lf);
Game.viewport.RefreshPalette();
}
var colorChooser = lobby.GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
hueSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
satSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
lumSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
rangeSlider.OnChange += _ => UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.GetWidget<ButtonWidget>("BUTTON_OK").OnMouseUp = mi =>
{
colorChooser.IsVisible = () => false;
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
UpdatePlayerColor(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
return true;
};
}
// hk is hue in the range [0,1] instead of [0,360]
Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; }
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
void UpdatePlayerColor(float hf, float sf, float lf, float r)
{
var c1 = ColorFromHSL(hf, sf, lf);
var c2 = ColorFromHSL(hf, sf, r*lf);
Game.Settings.Player.Color1 = c1;
Game.Settings.Player.Color2 = c2;
Game.Settings.Save();
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void UpdateColorPreview(float hf, float sf, float lf, float r)
{
CurrentColorPreview1 = ColorFromHSL(hf, sf, lf);
CurrentColorPreview2 = ColorFromHSL(hf, sf, r*lf);
Game.viewport.RefreshPalette();
}
// hk is hue in the range [0,1] instead of [0,360]
public static Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; }
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
void UpdateCurrentMap()
@@ -211,23 +209,23 @@ namespace OpenRA.Widgets.Delegates
MapUid = Game.LobbyInfo.GlobalSettings.Map;
Map = Game.modData.AvailableMaps[MapUid];
}
bool hasJoined = false;
void JoinedServer()
{
if (hasJoined)
return;
hasJoined = true;
if (Game.LocalClient.Name != Game.Settings.Player.Name)
Game.IssueOrder(Order.Command("name " + Game.Settings.Player.Name));
bool hasJoined = false;
void JoinedServer()
{
if (hasJoined)
return;
hasJoined = true;
if (Game.LocalClient.Name != Game.Settings.Player.Name)
Game.IssueOrder(Order.Command("name " + Game.Settings.Player.Name));
var c1 = Game.Settings.Player.Color1;
var c2 = Game.Settings.Player.Color2;
if (Game.LocalClient.Color1 != c1 || Game.LocalClient.Color2 != c2)
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
if (Game.LocalClient.Color1 != c1 || Game.LocalClient.Color2 != c2)
Game.IssueOrder(Order.Command("color {0},{1},{2},{3},{4},{5}".F(c1.R,c1.G,c1.B,c2.R,c2.G,c2.B)));
}
void ResetConnectionState()
@@ -315,24 +313,24 @@ namespace OpenRA.Widgets.Delegates
name.OnLoseFocus = () => name.OnEnterKey();
var color = template.GetWidget<ButtonWidget>("COLOR");
color.OnMouseUp = mi =>
{
var colorChooser = Widget.RootWidget.GetWidget("SERVER_LOBBY").GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
hueSlider.Offset = Game.LocalClient.Color1.GetHue()/360f;
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
satSlider.Offset = Game.LocalClient.Color1.GetSaturation();
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
lumSlider.Offset = Game.LocalClient.Color1.GetBrightness();
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
rangeSlider.Offset = Game.LocalClient.Color1.GetBrightness() == 0 ? 0 : Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness();
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.IsVisible = () => true;
return true;
color.OnMouseUp = mi =>
{
var colorChooser = Widget.RootWidget.GetWidget("SERVER_LOBBY").GetWidget("COLOR_CHOOSER");
var hueSlider = colorChooser.GetWidget<SliderWidget>("HUE_SLIDER");
hueSlider.SetOffset(Game.LocalClient.Color1.GetHue()/360f);
var satSlider = colorChooser.GetWidget<SliderWidget>("SAT_SLIDER");
satSlider.SetOffset(Game.LocalClient.Color1.GetSaturation());
var lumSlider = colorChooser.GetWidget<SliderWidget>("LUM_SLIDER");
lumSlider.SetOffset(Game.LocalClient.Color1.GetBrightness());
var rangeSlider = colorChooser.GetWidget<SliderWidget>("RANGE_SLIDER");
rangeSlider.SetOffset(Game.LocalClient.Color1.GetBrightness() == 0 ? 0 : Game.LocalClient.Color2.GetBrightness()/Game.LocalClient.Color1.GetBrightness());
UpdateColorPreview(hueSlider.GetOffset(), satSlider.GetOffset(), lumSlider.GetOffset(), rangeSlider.GetOffset());
colorChooser.IsVisible = () => true;
return true;
};
var colorBlock = color.GetWidget<ColorBlockWidget>("COLORBLOCK");
@@ -424,4 +422,4 @@ namespace OpenRA.Widgets.Delegates
return true;
}
}
}
}

View File

@@ -9,25 +9,41 @@
#endregion
using OpenRA.FileFormats;
using OpenRA.Server;
using System.Net;
using System.IO;
namespace OpenRA.Widgets.Delegates
{
public class MainMenuButtonsDelegate : IWidgetDelegate
{
public MainMenuButtonsDelegate()
[ObjectCreator.UseCtor]
public MainMenuButtonsDelegate( [ObjectCreator.Param( "widget" )] Widget widget )
{
// Main menu is the default window
Widget.WindowList.Push("MAINMENU_BG");
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_QUIT").OnMouseUp = mi => { Game.Exit(); return true; };
widget.GetWidget( "MAINMENU_BUTTON_JOIN" ).OnMouseUp = mi => { Widget.OpenWindow( "JOINSERVER_BG" ); return true; };
widget.GetWidget( "MAINMENU_BUTTON_CREATE" ).OnMouseUp = mi => { Widget.OpenWindow( "CREATESERVER_BG" ); return true; };
widget.GetWidget( "MAINMENU_BUTTON_SETTINGS" ).OnMouseUp = mi => { Widget.OpenWindow( "SETTINGS_MENU" ); return true; };
widget.GetWidget( "MAINMENU_BUTTON_MUSIC" ).OnMouseUp = mi => { Widget.OpenWindow( "MUSIC_MENU" ); return true; };
widget.GetWidget( "MAINMENU_BUTTON_QUIT" ).OnMouseUp = mi => { Game.Exit(); return true; };
var version = Widget.RootWidget.GetWidget("MAINMENU_BG").GetWidget<LabelWidget>("VERSION_STRING");
var version = widget.GetWidget<LabelWidget>("VERSION_STRING");
if (FileSystem.Exists("VERSION"))
{
var s = FileSystem.Open("VERSION");
version.Text = s.ReadAllText();
s.Close();
MasterServerQuery.OnVersion += v => { if (!string.IsNullOrEmpty(v)) version.Text += "\nLatest: " + v; };
MasterServerQuery.GetCurrentVersion(Game.Settings.Server.MasterServer);
}
else
{
version.Text = "Dev Build";
}
MasterServerQuery.ClientVersion = version.Text;
MasterServerQuery.GetMOTD(Game.Settings.Server.MasterServer);
}
}
}

View File

@@ -17,10 +17,10 @@ namespace OpenRA.Widgets.Delegates
public class MapChooserDelegate : IWidgetDelegate
{
MapStub Map = null;
public MapChooserDelegate()
[ObjectCreator.UseCtor]
public MapChooserDelegate( [ObjectCreator.Param( "widget" )] Widget bg )
{
var r = Widget.RootWidget;
var bg = r.GetWidget("MAP_CHOOSER");
bg.SpecialOneArg = (map) => RefreshMapList(map);
var ml = bg.GetWidget<ListBoxWidget>("MAP_LIST");
@@ -33,13 +33,13 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("BUTTON_OK").OnMouseUp = mi =>
{
Game.IssueOrder(Order.Command("map " + Map.Uid));
r.CloseWindow();
Widget.CloseWindow();
return true;
};
bg.GetWidget("BUTTON_CANCEL").OnMouseUp = mi =>
{
r.CloseWindow();
Widget.CloseWindow();
return true;
};

View File

@@ -24,15 +24,10 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
Game.Settings.Save();
Widget.RootWidget.CloseWindow();
Widget.CloseWindow();
return true;
};
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_MUSIC").OnMouseUp = mi => {
Widget.RootWidget.OpenWindow("MUSIC_MENU");
return true;
};
bg.GetWidget("BUTTON_PLAY").OnMouseUp = mi =>
{
if (CurrentSong == null)

View File

@@ -23,28 +23,20 @@ namespace OpenRA.Widgets.Delegates
GameServer currentServer = null;
Widget ServerTemplate;
public ServerBrowserDelegate()
[ObjectCreator.UseCtor]
public ServerBrowserDelegate( [ObjectCreator.Param( "widget" )] Widget widget )
{
var r = Widget.RootWidget;
var bg = r.GetWidget("JOINSERVER_BG");
var dc = r.GetWidget("DIRECTCONNECT_BG");
var bg = widget.GetWidget("JOINSERVER_BG");
MasterServerQuery.OnComplete += games => RefreshServerList(games);
r.GetWidget("MAINMENU_BUTTON_JOIN").OnMouseUp = mi =>
{
r.OpenWindow("JOINSERVER_BG");
bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true;
bg.GetWidget<LabelWidget>("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list...";
r.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true;
r.GetWidget<LabelWidget>("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list...";
bg.Children.RemoveAll(a => GameButtons.Contains(a));
GameButtons.Clear();
bg.Children.RemoveAll(a => GameButtons.Contains(a));
GameButtons.Clear();
MasterServerQuery.Refresh(Game.Settings.Server.MasterServer);
return true;
};
MasterServerQuery.Refresh(Game.Settings.Server.MasterServer);
bg.GetWidget("SERVER_INFO").IsVisible = () => currentServer != null;
var preview = bg.GetWidget<MapPreviewWidget>("MAP_PREVIEW");
@@ -52,7 +44,7 @@ namespace OpenRA.Widgets.Delegates
preview.IsVisible = () => CurrentMap() != null;
bg.GetWidget<LabelWidget>("SERVER_IP").GetText = () => currentServer.Address;
bg.GetWidget<LabelWidget>("SERVER_MODS").GetText = () => string.Join(",", currentServer.Mods);
bg.GetWidget<LabelWidget>("SERVER_MODS").GetText = () => GenerateModsLabel();
bg.GetWidget<LabelWidget>("MAP_TITLE").GetText = () => (CurrentMap() != null) ? CurrentMap().Title : "Unknown";
bg.GetWidget<LabelWidget>("MAP_PLAYERS").GetText = () =>
{
@@ -70,8 +62,8 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("REFRESH_BUTTON").OnMouseUp = mi =>
{
r.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true;
r.GetWidget<LabelWidget>("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list...";
bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true;
bg.GetWidget<LabelWidget>("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list...";
bg.Children.RemoveAll(a => GameButtons.Contains(a));
GameButtons.Clear();
@@ -83,16 +75,14 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("CANCEL_BUTTON").OnMouseUp = mi =>
{
r.CloseWindow();
Widget.CloseWindow();
return true;
};
bg.GetWidget("DIRECTCONNECT_BUTTON").OnMouseUp = mi =>
{
r.CloseWindow();
dc.GetWidget<TextFieldWidget>("SERVER_ADDRESS").Text = Game.Settings.Player.LastServer;
r.OpenWindow("DIRECTCONNECT_BG");
Widget.CloseWindow();
Widget.OpenWindow("DIRECTCONNECT_BG");
return true;
};
@@ -119,33 +109,10 @@ namespace OpenRA.Widgets.Delegates
return false;
}
r.CloseWindow();
Widget.CloseWindow();
Game.JoinServer(currentServer.Address.Split(':')[0], int.Parse(currentServer.Address.Split(':')[1]));
return true;
};
// Direct Connect
dc.GetWidget("JOIN_BUTTON").OnMouseUp = mi =>
{
var address = dc.GetWidget<TextFieldWidget>("SERVER_ADDRESS").Text;
var cpts = address.Split(':').ToArray();
if (cpts.Length != 2)
return true;
Game.Settings.Player.LastServer = address;
Game.Settings.Save();
r.CloseWindow();
Game.JoinServer(cpts[0], int.Parse(cpts[1]));
return true;
};
dc.GetWidget("CANCEL_BUTTON").OnMouseUp = mi =>
{
r.CloseWindow();
return r.GetWidget("MAINMENU_BUTTON_JOIN").OnMouseUp(mi);
};
}
MapStub CurrentMap()
@@ -153,11 +120,22 @@ namespace OpenRA.Widgets.Delegates
return (currentServer == null || !Game.modData.AvailableMaps.ContainsKey(currentServer.Map))
? null : Game.modData.AvailableMaps[currentServer.Map];
}
string GenerateModsLabel()
{
return string.Join("\n", currentServer.Mods.Select(m =>
ModData.AllMods.ContainsKey(m) ? string.Format("{0} ({1})", ModData.AllMods[m].Title, ModData.AllMods[m].Version)
: string.Format("Unknown Mod: {0}",m)).ToArray());
}
void RefreshServerList(IEnumerable<GameServer> games)
{
var r = Widget.RootWidget;
var bg = r.GetWidget("JOINSERVER_BG");
if (bg == null) // We got a MasterServer reply AFTER the browser is gone, just return to prevent crash - Gecko
return;
var sl = bg.GetWidget<ListBoxWidget>("SERVER_LIST");
sl.Children.Clear();
@@ -205,4 +183,37 @@ namespace OpenRA.Widgets.Delegates
}
}
}
public class DirectConnectDelegate : IWidgetDelegate
{
[ObjectCreator.UseCtor]
public DirectConnectDelegate( [ObjectCreator.Param( "widget" )] Widget widget )
{
var dc = widget.GetWidget("DIRECTCONNECT_BG");
dc.GetWidget<TextFieldWidget>("SERVER_ADDRESS").Text = Game.Settings.Player.LastServer;
dc.GetWidget("JOIN_BUTTON").OnMouseUp = mi =>
{
var address = dc.GetWidget<TextFieldWidget>("SERVER_ADDRESS").Text;
var cpts = address.Split(':').ToArray();
if (cpts.Length != 2)
return true;
Game.Settings.Player.LastServer = address;
Game.Settings.Save();
Widget.CloseWindow();
Game.JoinServer(cpts[0], int.Parse(cpts[1]));
return true;
};
dc.GetWidget("CANCEL_BUTTON").OnMouseUp = mi =>
{
Widget.CloseWindow();
Widget.OpenWindow("MAINMENU_BG");
return true;
};
}
}
}

View File

@@ -53,6 +53,15 @@ namespace OpenRA.Widgets.Delegates
Game.Settings.Game.ViewportEdgeScroll ^= true;
return true;
};
// Added scroll sensitivity - Gecko
var edgeScrollSlider = general.GetWidget<SliderWidget>("EDGE_SCROLL_AMOUNT");
if (edgeScrollSlider != null) // Backwards compatible - Gecko
{
edgeScrollSlider.SetOffset(Game.Settings.Game.ViewportEdgeScrollStep);
edgeScrollSlider.OnChange += _ => { Game.Settings.Game.ViewportEdgeScrollStep = edgeScrollSlider.GetOffset(); };
Game.Settings.Game.ViewportEdgeScrollStep = edgeScrollSlider.GetOffset();
}
var inverseScroll = general.GetWidget<CheckboxWidget>("INVERSE_SCROLL");
inverseScroll.Checked = () => Game.Settings.Game.InverseDragScroll;
@@ -68,10 +77,12 @@ namespace OpenRA.Widgets.Delegates
var soundslider = audio.GetWidget<SliderWidget>("SOUND_VOLUME");
soundslider.OnChange += x => { Sound.SoundVolume = x; };
soundslider.GetOffset = () => { return Sound.SoundVolume; };
soundslider.SetOffset(Sound.SoundVolume);
var musicslider = audio.GetWidget<SliderWidget>("MUSIC_VOLUME");
musicslider.OnChange += x => { Sound.MusicVolume = x; };
musicslider.GetOffset = () => { return Sound.MusicVolume; };
musicslider.SetOffset(Sound.MusicVolume);
// Display
@@ -150,17 +161,9 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
Game.Settings.Save();
Widget.RootWidget.CloseWindow();
Widget.CloseWindow();
return true;
};
// Menu Buttons
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_SETTINGS").OnMouseUp = mi => {
Widget.RootWidget.OpenWindow("SETTINGS_MENU");
return true;
};
}
string open = null;

View File

@@ -44,13 +44,13 @@ namespace OpenRA.Widgets.Delegates
bg.GetWidget("BUTTON_CLOSE").OnMouseUp = mi => {
player.Stop();
Widget.RootWidget.CloseWindow();
Widget.CloseWindow();
return true;
};
// Menu Buttons
Widget.RootWidget.GetWidget("MAINMENU_BUTTON_VIDEOPLAYER").OnMouseUp = mi => {
Widget.RootWidget.OpenWindow("VIDEOPLAYER_MENU");
Widget.OpenWindow("VIDEOPLAYER_MENU");
return true;
};

View File

@@ -16,10 +16,12 @@ namespace OpenRA.Widgets
public class LabelWidget : Widget
{
public enum TextAlign { Left, Center, Right }
public enum TextVAlign { Top, Middle, Bottom }
public string Text = null;
public string Background = null;
public TextAlign Align = TextAlign.Left;
public TextVAlign VAlign = TextVAlign.Middle;
public bool Bold = false;
public Func<string> GetText;
public Func<string> GetBackground;
@@ -54,8 +56,14 @@ namespace OpenRA.Widgets
return;
int2 textSize = font.Measure(text);
int2 position = RenderOrigin + new int2(0, (Bounds.Height - textSize.Y)/2);
int2 position = RenderOrigin;
if (VAlign == TextVAlign.Middle)
position += new int2(0, (Bounds.Height - textSize.Y)/2);
if (VAlign == TextVAlign.Bottom)
position += new int2(0, Bounds.Height - textSize.Y);
if (Align == TextAlign.Center)
position += new int2((Bounds.Width - textSize.X)/2, 0);

View File

@@ -71,15 +71,12 @@ namespace OpenRA.Widgets
WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", "down_arrow"),
new float2(downButtonRect.Left + downOffset, downButtonRect.Top + downOffset));
Game.Renderer.RgbaSpriteRenderer.Flush();
Game.Renderer.Device.EnableScissor(backgroundRect.X, backgroundRect.Y + HeaderHeight, backgroundRect.Width, backgroundRect.Height - HeaderHeight);
Game.Renderer.EnableScissor(backgroundRect.X, backgroundRect.Y + HeaderHeight, backgroundRect.Width, backgroundRect.Height - HeaderHeight);
foreach (var child in Children)
child.Draw(world);
Game.Renderer.RgbaSpriteRenderer.Flush();
Game.Renderer.Device.DisableScissor();
Game.Renderer.DisableScissor();
}
public override int2 ChildOrigin { get { return RenderOrigin + new int2(0, (int)ListOffset); } }

View File

@@ -105,8 +105,6 @@ namespace OpenRA.Widgets
new float2(MapRect.Location),
new float2( MapRect.Size ) );
Game.Renderer.RgbaSpriteRenderer.Flush();
// Overlay spawnpoints
var colors = SpawnColors();
foreach (var p in map.SpawnPoints)
@@ -120,12 +118,9 @@ namespace OpenRA.Widgets
sprite = OwnedSpawn;
offset = new int2(-OwnedSpawn.bounds.Width/2, -OwnedSpawn.bounds.Height/2);
WidgetUtils.FillRectWithColor(new Rectangle(pos.X + offset.X + 2, pos.Y + offset.Y + 2, 12, 12), colors[p]);
Game.Renderer.LineRenderer.Flush();
}
Game.Renderer.RgbaSpriteRenderer.DrawSprite(sprite, pos + offset);
}
Game.Renderer.Flush();
}
}
}

View File

@@ -40,8 +40,6 @@ namespace OpenRA.Widgets
return b;
});
}
Game.Renderer.LineRenderer.Flush();
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace OpenRA.Widgets
{
class ScrollingTextWidget : Widget
{
public string Text = "";
private string ScrollingText = "";
public string Background = null;
public bool Bold = false;
public int ScrollLength = 200;
// ticks per single letter scroll
public int ScrollRate = 4;
private string ScrollBuffer = "";
private int ScrollLocation = 0;
private int ScrollTick = 0;
public Func<string> GetText;
public Func<string> GetBackground;
public ScrollingTextWidget()
: base()
{
GetText = () => Text;
GetBackground = () => Background;
}
protected ScrollingTextWidget(ScrollingTextWidget other)
: base(other)
{
Text = other.Text;
GetText = other.GetText;
Bold = other.Bold;
GetBackground = other.GetBackground;
}
public override void Tick(World world)
{
if (Text != "")
{
ScrollingText = Text;
Text = "";
}
UpdateScrollBuffer();
}
public void ResetScroll()
{
ScrollLocation = 0;
ScrollTick = 0;
}
private void UpdateScrollBuffer()
{
ScrollTick++;
if (ScrollTick < ScrollRate)
{
return;
}
ScrollTick = 0;
ScrollBuffer = "";
if (ScrollingText.Substring(ScrollingText.Length - 4, 3) != " ")
{
ScrollingText += " ";
}
int tempScrollLocation = ScrollLocation;
for (int i = 0; i < ScrollLength; ++i)
{
ScrollBuffer += ScrollingText.Substring(tempScrollLocation, 1);
tempScrollLocation = (tempScrollLocation + 1) % ScrollingText.Length;
}
ScrollLocation = (ScrollLocation + 1) % ScrollingText.Length;
}
public void SetText(string newText)
{
Text = newText.Replace("\n", " ");
Text = Text.Replace("\r", "");
}
public override void DrawInner(World world)
{
var bg = GetBackground();
if (bg != null)
WidgetUtils.DrawPanel(bg, RenderBounds);
var font = (Bold) ? Game.Renderer.BoldFont : Game.Renderer.RegularFont;
var text = GetText();
if (text == null)
return;
int2 textSize = font.Measure(text);
int2 position = RenderOrigin + new int2(0, (Bounds.Height - textSize.Y) / 2);
Game.Renderer.EnableScissor(position.X, position.Y, Bounds.Width, Bounds.Height);
font.DrawText(ScrollBuffer, position, Color.White);
Game.Renderer.DisableScissor();
}
public override Widget Clone() { return new ScrollingTextWidget(this); }
}
}

45
OpenRA.Game/Widgets/SliderWidget.cs Normal file → Executable file
View File

@@ -6,9 +6,9 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
#endregion
using System;
using System.Drawing;
namespace OpenRA.Widgets
@@ -17,9 +17,11 @@ namespace OpenRA.Widgets
{
public event Action<float> OnChange;
public Func<float> GetOffset;
public float Offset = 0;
public int Ticks = 0;
public int TrackHeight = 5;
public float2 Range = new float2(0f, 1f);
private float Offset = 0;
int2 lastMouseLocation;
bool isMoving = false;
@@ -27,8 +29,15 @@ namespace OpenRA.Widgets
public SliderWidget()
: base()
{
GetOffset = () => Offset;
OnChange = x => Offset = x;
GetOffset = () =>
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
return Spread * Offset + Little;
};
OnChange = x => Offset = x.Clamp(0f, 1f);
}
public SliderWidget(SliderWidget other)
@@ -36,13 +45,23 @@ namespace OpenRA.Widgets
{
OnChange = other.OnChange;
GetOffset = other.GetOffset;
Offset = other.Offset;
Ticks = other.Ticks;
Range = other.Range;
Offset = GetOffset();
TrackHeight = other.TrackHeight;
lastMouseLocation = other.lastMouseLocation;
isMoving = other.isMoving;
}
public void SetOffset(float newOffset)
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
Offset = ((newOffset - Little) / Spread).Clamp(0f, 1f);
}
public override bool HandleInputInner(MouseInput mi)
{
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
@@ -72,7 +91,7 @@ namespace OpenRA.Widgets
}
else if (Ticks != 0)
{
var pos = GetOffset();
var pos = Offset;
// Offset slightly the direction we want to move so we don't get stuck on a tick
var delta = 0.001;
@@ -92,7 +111,7 @@ namespace OpenRA.Widgets
var thumb = thumbRect;
var center = thumb.X + thumb.Width / 2;
var newOffset = OffsetBy((mi.Location.X - center) * 1f / (RenderBounds.Width - thumb.Width));
if (newOffset != GetOffset())
if (newOffset != Offset)
{
OnChange(newOffset);
@@ -127,7 +146,7 @@ namespace OpenRA.Widgets
float OffsetBy(float amount)
{
var centerPos = GetOffset() + amount;
var centerPos = Offset + amount;
if (centerPos < 0) centerPos = 0;
if (centerPos > 1) centerPos = 1;
return centerPos;
@@ -141,7 +160,7 @@ namespace OpenRA.Widgets
{
var width = RenderBounds.Height;
var height = RenderBounds.Height;
var origin = (int)((RenderBounds.X + width / 2) + GetOffset() * (RenderBounds.Width - width) - width / 2f);
var origin = (int)((RenderBounds.X + width / 2) + Offset * (RenderBounds.Width - width) - width / 2f);
return new Rectangle(origin, RenderBounds.Y, width, height);
}
}
@@ -169,5 +188,5 @@ namespace OpenRA.Widgets
WidgetUtils.DrawPanel("dialog2", thumbRect);
}
}
}
}

View File

@@ -127,16 +127,13 @@ namespace OpenRA.Widgets
if (Focused)
textPos += new int2(Bounds.Width - 2 * margin - textSize.X, 0);
Game.Renderer.Device.EnableScissor(pos.X + margin, pos.Y, Bounds.Width - 2 * margin, Bounds.Bottom);
Game.Renderer.EnableScissor(pos.X + margin, pos.Y, Bounds.Width - 2 * margin, Bounds.Bottom);
}
font.DrawText(Text + cursor, textPos, Color.White);
if (textSize.X > Bounds.Width - 2 * margin)
{
Game.Renderer.RgbaSpriteRenderer.Flush();
Game.Renderer.Device.DisableScissor();
}
Game.Renderer.DisableScissor();
}
public override Widget Clone() { return new TextFieldWidget(this); }

View File

@@ -1,172 +1,178 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using OpenRA.Graphics;
namespace OpenRA.Widgets
{
[Flags]
public enum ScrollDirection
{
None = 0,
Up = 1,
Left = 2,
Down = 4,
Right = 8
}
class ViewportScrollControllerWidget : Widget
{
public int EdgeScrollThreshold = 15;
ScrollDirection Keyboard;
namespace OpenRA.Widgets
{
[Flags]
public enum ScrollDirection
{
None = 0,
Up = 1,
Left = 2,
Down = 4,
Right = 8
}
class ViewportScrollControllerWidget : Widget
{
public int EdgeScrollThreshold = 15;
ScrollDirection Keyboard;
ScrollDirection Edge;
public ViewportScrollControllerWidget() : base() { }
protected ViewportScrollControllerWidget(ViewportScrollControllerWidget widget) : base(widget) {}
public override void DrawInner( World world ) {}
public override bool HandleInputInner(MouseInput mi)
{
if (mi.Event == MouseInputEvent.Move &&
(mi.Button == MouseButton.Middle || mi.Button == (MouseButton.Left | MouseButton.Right)))
public ViewportScrollControllerWidget() : base() { }
protected ViewportScrollControllerWidget(ViewportScrollControllerWidget widget) : base(widget) {}
public override void DrawInner( World world ) {}
public override bool HandleInputInner(MouseInput mi)
{
if (mi.Event == MouseInputEvent.Move &&
(mi.Button == MouseButton.Middle || mi.Button == (MouseButton.Left | MouseButton.Right)))
{
int InverseScroll = Game.Settings.Game.InverseDragScroll ? -1 : 1;
Game.viewport.Scroll((Viewport.LastMousePos - mi.Location) * InverseScroll);
return true;
}
return false;
}
public override string GetCursor(int2 pos)
{
if (!Game.Settings.Game.ViewportEdgeScroll)
return null;
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if(BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-tl-blocked";
else
return "scroll-tl";
}
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-tr-blocked";
else
return "scroll-tr";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-bl-blocked";
else
return "scroll-bl";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-br-blocked";
else
return "scroll-br";
}
if (Edge.Includes(ScrollDirection.Up))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Up))
return "scroll-t-blocked";
else
return "scroll-t";
if (Edge.Includes(ScrollDirection.Down))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Down))
return "scroll-b-blocked";
else
return "scroll-b";
if (Edge.Includes(ScrollDirection.Left))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Left))
return "scroll-l-blocked";
else
return "scroll-l";
if (Edge.Includes(ScrollDirection.Right))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Right))
return "scroll-r-blocked";
else
return "scroll-r";
return null;
}
public override bool LoseFocus (MouseInput mi)
{
Keyboard = ScrollDirection.None;
return base.LoseFocus(mi);
}
public override bool HandleKeyPressInner(KeyInput e)
{
switch (e.KeyName)
{
case "up": Keyboard = Keyboard.Set(ScrollDirection.Up, (e.Event == KeyInputEvent.Down)); return true;
case "down": Keyboard = Keyboard.Set(ScrollDirection.Down, (e.Event == KeyInputEvent.Down)); return true;
case "left": Keyboard = Keyboard.Set(ScrollDirection.Left, (e.Event == KeyInputEvent.Down)); return true;
case "right": Keyboard = Keyboard.Set(ScrollDirection.Right, (e.Event == KeyInputEvent.Down)); return true;
}
return false;
}
public override void Tick(World world)
{
Edge = ScrollDirection.None;
if (Game.Settings.Game.ViewportEdgeScroll && Game.HasInputFocus)
{
// Check for edge-scroll
if (Viewport.LastMousePos.X < EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Left, true);
if (Viewport.LastMousePos.Y < EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Up, true);
if (Viewport.LastMousePos.X >= Game.viewport.Width - EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Right, true);
if (Viewport.LastMousePos.Y >= Game.viewport.Height - EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Down, true);
}
if(Keyboard != ScrollDirection.None || Edge != ScrollDirection.None)
{
var scroll = new float2(0,0);
if (Keyboard.Includes(ScrollDirection.Up) || Edge.Includes(ScrollDirection.Up))
scroll += new float2(0, -10);
if (Keyboard.Includes(ScrollDirection.Right) || Edge.Includes(ScrollDirection.Right))
scroll += new float2(10, 0);
if (Keyboard.Includes(ScrollDirection.Down) || Edge.Includes(ScrollDirection.Down))
scroll += new float2(0, 10);
if (Keyboard.Includes(ScrollDirection.Left) || Edge.Includes(ScrollDirection.Left))
scroll += new float2(-10, 0);
Game.viewport.Scroll(scroll);
}
}
public override Widget Clone() { return new ViewportScrollControllerWidget(this); }
}
public static class ViewportExts
{
public static bool Includes(this ScrollDirection d, ScrollDirection s)
{
return (d & s) == s;
}
public static ScrollDirection Set(this ScrollDirection d, ScrollDirection s, bool val)
{
return (d.Includes(s) != val) ? d ^ s : d;
}
}
}
Game.viewport.Scroll((Viewport.LastMousePos - mi.Location) * InverseScroll);
return true;
}
return false;
}
public override string GetCursor(int2 pos)
{
if (!Game.Settings.Game.ViewportEdgeScroll)
return null;
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if(BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-tl-blocked";
else
return "scroll-tl";
}
if (Edge.Includes(ScrollDirection.Up) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Up) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-tr-blocked";
else
return "scroll-tr";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Left)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Left))
return "scroll-bl-blocked";
else
return "scroll-bl";
}
if (Edge.Includes(ScrollDirection.Down) && Edge.Includes(ScrollDirection.Right)){
ScrollDirection BlockedDirections = Game.viewport.GetBlockedDirections();
if (BlockedDirections.Includes(ScrollDirection.Down) && BlockedDirections.Includes(ScrollDirection.Right))
return "scroll-br-blocked";
else
return "scroll-br";
}
if (Edge.Includes(ScrollDirection.Up))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Up))
return "scroll-t-blocked";
else
return "scroll-t";
if (Edge.Includes(ScrollDirection.Down))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Down))
return "scroll-b-blocked";
else
return "scroll-b";
if (Edge.Includes(ScrollDirection.Left))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Left))
return "scroll-l-blocked";
else
return "scroll-l";
if (Edge.Includes(ScrollDirection.Right))
if (Game.viewport.GetBlockedDirections().Includes(ScrollDirection.Right))
return "scroll-r-blocked";
else
return "scroll-r";
return null;
}
public override bool LoseFocus (MouseInput mi)
{
Keyboard = ScrollDirection.None;
return base.LoseFocus(mi);
}
public override bool HandleKeyPressInner(KeyInput e)
{
switch (e.KeyName)
{
case "up": Keyboard = Keyboard.Set(ScrollDirection.Up, (e.Event == KeyInputEvent.Down)); return true;
case "down": Keyboard = Keyboard.Set(ScrollDirection.Down, (e.Event == KeyInputEvent.Down)); return true;
case "left": Keyboard = Keyboard.Set(ScrollDirection.Left, (e.Event == KeyInputEvent.Down)); return true;
case "right": Keyboard = Keyboard.Set(ScrollDirection.Right, (e.Event == KeyInputEvent.Down)); return true;
}
return false;
}
public override void Tick(World world)
{
Edge = ScrollDirection.None;
if (Game.Settings.Game.ViewportEdgeScroll && Game.HasInputFocus)
{
// Check for edge-scroll
if (Viewport.LastMousePos.X < EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Left, true);
if (Viewport.LastMousePos.Y < EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Up, true);
if (Viewport.LastMousePos.X >= Game.viewport.Width - EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Right, true);
if (Viewport.LastMousePos.Y >= Game.viewport.Height - EdgeScrollThreshold)
Edge = Edge.Set(ScrollDirection.Down, true);
}
if(Keyboard != ScrollDirection.None || Edge != ScrollDirection.None)
{
var scroll = new float2(0, 0);
// Modified to use the ViewportEdgeScrollStep setting - Gecko
if (Keyboard.Includes(ScrollDirection.Up) || Edge.Includes(ScrollDirection.Up))
scroll += new float2(0, -1);
if (Keyboard.Includes(ScrollDirection.Right) || Edge.Includes(ScrollDirection.Right))
scroll += new float2(1, 0);
if (Keyboard.Includes(ScrollDirection.Down) || Edge.Includes(ScrollDirection.Down))
scroll += new float2(0, 1);
if (Keyboard.Includes(ScrollDirection.Left) || Edge.Includes(ScrollDirection.Left))
scroll += new float2(-1, 0);
float length = scroll.Length;
scroll.X = (scroll.X / length) * Game.Settings.Game.ViewportEdgeScrollStep;
scroll.Y = (scroll.Y / length) * Game.Settings.Game.ViewportEdgeScrollStep;
Game.viewport.Scroll(scroll);
}
}
public override Widget Clone() { return new ViewportScrollControllerWidget(this); }
}
public static class ViewportExts
{
public static bool Includes(this ScrollDirection d, ScrollDirection s)
{
return (d & s) == s;
}
public static ScrollDirection Set(this ScrollDirection d, ScrollDirection s, bool val)
{
return (d.Includes(s) != val) ? d ^ s : d;
}
}
}

View File

@@ -26,6 +26,7 @@ namespace OpenRA.Widgets
public string Width = "0";
public string Height = "0";
public string Delegate = null;
public string EventHandler = null;
public bool ClickThrough = true;
public bool Visible = true;
public readonly List<Widget> Children = new List<Widget>();
@@ -35,7 +36,7 @@ namespace OpenRA.Widgets
public Widget Parent = null;
static List<string> Delegates = new List<string>();
public static Stack<string> WindowList = new Stack<string>();
public static Stack<Widget> WindowList = new Stack<Widget>();
// Common Funcs that most widgets will want
public Action<object> SpecialOneArg = (arg) => {};
@@ -47,24 +48,13 @@ namespace OpenRA.Widgets
public Func<bool> IsVisible;
public Widget() { IsVisible = () => Visible; }
public static Widget RootWidget {
get
{
if (rootWidget == null)
{
rootWidget = new ContainerWidget();
foreach( var file in Game.modData.Manifest.ChromeLayout.Select( a => MiniYaml.FromFile( a ) ) )
foreach( var w in file )
rootWidget.AddChild( WidgetLoader.LoadWidget( w ) );
rootWidget.Initialize();
rootWidget.InitDelegates();
}
return rootWidget;
}
public static Widget RootWidget
{
get { return rootWidget; }
set { rootWidget = value; }
}
private static Widget rootWidget = null;
private static Widget rootWidget = new ContainerWidget();
public Widget(Widget widget)
{
@@ -132,14 +122,15 @@ namespace OpenRA.Widgets
Evaluator.Evaluate(Y, substitutions),
width,
height);
}
// Non-static func definitions
if (Delegate != null && !Delegates.Contains(Delegate))
Delegates.Add(Delegate);
foreach (var child in Children)
child.Initialize();
public void PostInit()
{
if( Delegate != null )
{
var createDict = new Dictionary<string, object> { { "widget", this } };
Game.modData.ObjectCreator.CreateObject<IWidgetDelegate>( Delegate, createDict );
}
}
public void InitDelegates()
@@ -322,20 +313,19 @@ namespace OpenRA.Widgets
return (widget != null)? (T) widget : null;
}
public void CloseWindow()
public static void CloseWindow()
{
RootWidget.GetWidget(WindowList.Pop()).Visible = false;
if (WindowList.Count > 0)
RootWidget.GetWidget(WindowList.Peek()).Visible = true;
RootWidget.Children.Remove( WindowList.Pop() );
if( WindowList.Count > 0 )
rootWidget.Children.Add( WindowList.Peek() );
}
public Widget OpenWindow(string id)
public static Widget OpenWindow(string id)
{
if (WindowList.Count > 0)
RootWidget.GetWidget(WindowList.Peek()).Visible = false;
WindowList.Push(id);
var window = RootWidget.GetWidget(id);
window.Visible = true;
var window = Game.modData.WidgetLoader.LoadWidget( rootWidget, id );
if( WindowList.Count > 0 )
rootWidget.Children.Remove( WindowList.Peek() );
WindowList.Push( window );
return window;
}

View File

@@ -8,29 +8,57 @@
*/
#endregion
using System.Linq;
using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Widgets;
namespace OpenRA
{
class WidgetLoader
public class WidgetLoader
{
public static Widget LoadWidget(MiniYamlNode node)
// foreach( var file in Game.modData.Manifest.ChromeLayout.Select( a => MiniYaml.FromFile( a ) ) )
// foreach( var w in file )
// rootWidget.AddChild( WidgetLoader.LoadWidget( w ) );
// rootWidget.Initialize();
// rootWidget.InitDelegates();
Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
public WidgetLoader( ModData modData )
{
foreach( var file in modData.Manifest.ChromeLayout.Select( a => MiniYaml.FromFile( a ) ) )
foreach( var w in file )
widgets.Add( w.Key.Substring( w.Key.IndexOf( '@' ) + 1 ), w );
}
public Widget LoadWidget( Widget parent, string w )
{
return LoadWidget( parent, widgets[ w ] );
}
public Widget LoadWidget( Widget parent, MiniYamlNode node)
{
var widget = NewWidget(node.Key);
parent.AddChild( widget );
foreach (var child in node.Value.Nodes)
if (child.Key != "Children")
FieldLoader.LoadField(widget, child.Key, child.Value.Value);
widget.Initialize();
foreach (var child in node.Value.Nodes)
{
if (child.Key == "Children")
foreach (var c in child.Value.Nodes)
widget.AddChild(LoadWidget(c));
else
FieldLoader.LoadField(widget, child.Key, child.Value.Value);
}
LoadWidget( widget, c);
widget.PostInit();
return widget;
}
static Widget NewWidget(string widgetType)
Widget NewWidget(string widgetType)
{
widgetType = widgetType.Split('@')[0];
return Game.CreateObject<Widget>(widgetType + "Widget");

View File

@@ -127,8 +127,6 @@ namespace OpenRA.Widgets
DrawRGBA(ss[6], new float2(Bounds.Left, Bounds.Bottom - ss[6].size.Y));
if (ps.HasFlags(PanelSides.Right | PanelSides.Bottom))
DrawRGBA(ss[7], new float2(Bounds.Right - ss[7].size.X, Bounds.Bottom - ss[7].size.Y));
Game.Renderer.RgbaSpriteRenderer.Flush();
}
}

View File

@@ -6,14 +6,14 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Orders;
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Orders;
using OpenRA.Traits;
namespace OpenRA.Widgets
@@ -39,8 +39,6 @@ namespace OpenRA.Widgets
foreach (var u in SelectActorsInBox(world, selbox.Value.First, selbox.Value.Second))
world.WorldRenderer.DrawSelectionBox(u, Color.Yellow);
Game.Renderer.LineRenderer.Flush();
}
float2 dragStart, dragEnd;
@@ -111,9 +109,8 @@ namespace OpenRA.Widgets
public override string GetCursor(int2 pos)
{
var world = Game.world;
int sync = world.SyncHash();
try
{
return Sync.CheckSyncUnchanged( world, () =>
{
if (!world.GameHasStarted)
return "default";
@@ -124,29 +121,24 @@ namespace OpenRA.Widgets
Modifiers = Game.GetModifierKeys()
};
return Game.world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi).ToInt2(), mi );
}
finally
{
if( sync != world.SyncHash() )
throw new InvalidOperationException( "Desync in InputControllerWidget.GetCursor" );
}
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi).ToInt2(), mi );
} );
}
public override bool HandleKeyPressInner(KeyInput e)
{
if (e.Event == KeyInputEvent.Down)
{
if (e.KeyName.Length == 1 && char.IsDigit(e.KeyName[0]))
{
Game.world.Selection.DoControlGroup(Game.world, e.KeyName[0] - '0', e.Modifiers);
return true;
}
if (e.KeyChar == '\b')
{
GotoNextBase();
return true;
{
if (e.KeyName.Length == 1 && char.IsDigit(e.KeyName[0]))
{
Game.world.Selection.DoControlGroup(Game.world, e.KeyName[0] - '0', e.Modifiers);
return true;
}
if (e.KeyChar == '\b')
{
GotoNextBase();
return true;
}
}
return false;

View File

@@ -85,7 +85,6 @@ namespace OpenRA.Widgets
ChromeProvider.GetImage("flags", actor.Owner.Country.Race),
new float2(Viewport.LastMousePos.X + 30, Viewport.LastMousePos.Y + 50));
}
Game.Renderer.RgbaSpriteRenderer.Flush();
}
}
}

View File

@@ -54,8 +54,18 @@ namespace OpenRA
public readonly TileSet TileSet;
public readonly WorldRenderer WorldRenderer;
public IOrderGenerator OrderGenerator = new UnitOrderGenerator();
IOrderGenerator orderGenerator_;
public IOrderGenerator OrderGenerator
{
get { return orderGenerator_; }
set
{
Sync.AssertUnsynced( "The current order generator may not be changed from synced code" );
orderGenerator_ = value;
}
}
public Selection Selection = new Selection();
public void CancelInputMode() { OrderGenerator = new UnitOrderGenerator(); }
@@ -76,6 +86,7 @@ namespace OpenRA
public World(Manifest manifest, Map map)
{
orderGenerator_ = new UnitOrderGenerator();
Map = map;
TileSet = Rules.TileSets[Map.Tileset];
@@ -194,7 +205,6 @@ namespace OpenRA
readonly World world;
public readonly Cache<Player, OwnedByCachedView> OwnedBy;
readonly TypeDictionary hasTrait = new TypeDictionary();
public AllQueries( World world )
{

View File

@@ -22,13 +22,21 @@ namespace OpenRA.GlRenderer
{
Gl.glGenBuffers(1, out buffer);
GraphicsDevice.CheckGlError();
}
public void SetData(ushort[] data)
{
Bind();
Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER,
new IntPtr(2 * data.Length), data, Gl.GL_DYNAMIC_DRAW);
new IntPtr(2 * size),
new ushort[ size ],
Gl.GL_DYNAMIC_DRAW);
GraphicsDevice.CheckGlError();
}
public void SetData(ushort[] data, int length)
{
Bind();
Gl.glBufferSubData(Gl.GL_ELEMENT_ARRAY_BUFFER,
IntPtr.Zero,
new IntPtr(2 * length),
data);
GraphicsDevice.CheckGlError();
}

View File

@@ -24,13 +24,21 @@ namespace OpenRA.GlRenderer
{
Gl.glGenBuffers(1, out buffer);
GraphicsDevice.CheckGlError();
}
public void SetData(T[] data)
{
Bind();
Gl.glBufferData(Gl.GL_ARRAY_BUFFER,
new IntPtr(Marshal.SizeOf(typeof(T)) * data.Length), data, Gl.GL_DYNAMIC_DRAW);
new IntPtr(Marshal.SizeOf(typeof(T)) * size),
new T[ size ],
Gl.GL_DYNAMIC_DRAW);
GraphicsDevice.CheckGlError();
}
public void SetData(T[] data, int length)
{
Bind();
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER,
IntPtr.Zero,
new IntPtr(Marshal.SizeOf(typeof(T)) * length),
data);
GraphicsDevice.CheckGlError();
}

View File

@@ -65,7 +65,6 @@ namespace OpenRA.Mods.Cnc
WidgetUtils.FillRectWithSprite(StripeRect, Stripe);
r.RgbaSpriteRenderer.DrawSprite(Logo, LogoPos);
Font.DrawText(text, new float2(Renderer.Resolution.Width - textSize.X - 20, Renderer.Resolution.Height - textSize.Y - 20), Color.White);
r.RgbaSpriteRenderer.Flush();
r.EndFrame();
}
}

View File

@@ -9,6 +9,7 @@
#endregion
using OpenRA.Mods.Cnc.Effects;
using OpenRA.Mods.RA;
using OpenRA.Orders;
using OpenRA.Traits;
@@ -33,9 +34,6 @@ namespace OpenRA.Mods.Cnc
w.Add(new IonCannon(self, w, order.TargetLocation));
});
if (Owner == Owner.World.LocalPlayer)
self.World.CancelInputMode();
FinishActivate();
}
}

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA
public static void PlayFullscreenFMVThen(World w, string movie, Action then)
{
var playerRoot = Widget.RootWidget.OpenWindow("FMVPLAYER");
var playerRoot = Widget.OpenWindow("FMVPLAYER");
var player = playerRoot.GetWidget<VqaPlayerWidget>("PLAYER");
w.DisableTick = true;
player.Load(movie);
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA
if (music)
Sound.PlayMusic();
Widget.RootWidget.CloseWindow();
Widget.CloseWindow();
w.DisableTick = false;
then();
});
@@ -126,7 +126,7 @@ namespace OpenRA.Mods.RA
}
// GoodGuy win conditions
// BadGuy is dead
int badcount = self.World.Queries.OwnedBy[Players["BadGuy"]].Count(a => a.IsInWorld && !a.IsDead());
int badcount = self.World.Queries.OwnedBy[Players["BadGuy"]].Count(a => !a.IsDead());
if (badcount != lastBadCount)
{
Game.Debug("{0} badguys remain".F(badcount));
@@ -137,7 +137,7 @@ namespace OpenRA.Mods.RA
}
//GoodGuy lose conditions
if (self.World.Queries.OwnedBy[Players["GoodGuy"]].Count( a => a.IsInWorld && !a.IsDead()) == 0)
if (self.World.Queries.OwnedBy[Players["GoodGuy"]].Count( a => !a.IsDead()) == 0)
OnLose(self.World);
// GoodGuy reinforcements

View File

@@ -12,9 +12,9 @@ using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Render;
namespace OpenRA.Mods.Cnc
{
@@ -33,8 +33,7 @@ namespace OpenRA.Mods.Cnc
// Start and end beyond the edge of the map, to give a finite delay, and ability to land when AFLD is on map edge
var startPos = new int2(owner.World.Map.XOffset + owner.World.Map.Width+5, self.Location.Y);
var endPos = new int2(owner.World.Map.XOffset-5, self.Location.Y);
var endPos = new int2(owner.World.Map.XOffset-5, self.Location.Y);
// Assume a single exit point for simplicity
var exit = self.Info.Traits.WithInterface<ExitInfo>().First();
@@ -51,16 +50,17 @@ namespace OpenRA.Mods.Cnc
new AltitudeInit( Rules.Info["c17"].Traits.Get<PlaneInfo>().CruiseAltitude ),
});
a.QueueActivity(new Fly(self.Location + new int2(6,0)));
a.QueueActivity(Fly.ToCell(self.Location + new int2(6,0)));
a.QueueActivity(new Land(Target.FromActor(self)));
a.QueueActivity(new CallFunc(() =>
{
if (self.IsDead())
if (!self.IsInWorld || self.IsDead())
return;
rb.PlayCustomAnimRepeating(self, "idle");
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
}));
a.QueueActivity(new Fly(endPos));
a.QueueActivity(Fly.ToCell(endPos));
a.QueueActivity(new RemoveSelf());
});

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Cnc
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
foreach (var c in cargo.Passengers)
c.CenterLocation = self.CenterLocation;
c.Trait<ITeleportable>().SetPxPosition( c, self.Trait<IHasLocation>().PxPosition );
return r.Concat(cargo.Passengers.SelectMany(a => a.Render()));
}

View File

@@ -25,8 +25,8 @@ namespace OpenRA.Mods.Cnc
bool preventDock = false;
public void OnDock(Actor self, Actor harv, DeliverResources dockOrder)
{
float2 startDock = harv.CenterLocation;
float2 endDock = self.CenterLocation + new float2(-15,8);
int2 startDock = harv.Trait<IHasLocation>().PxPosition;
int2 endDock = self.Trait<IHasLocation>().PxPosition + new int2(-15,8);
var harvester = harv.Trait<Harvester>();
harv.QueueActivity( new Turn(112) );

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Activities
{
/* non-turreted attack */
public class Attack : IActivity
public class Attack : CancelableActivity
{
Target Target;
int Range;
@@ -26,10 +26,17 @@ namespace OpenRA.Mods.RA.Activities
Range = range;
}
public IActivity NextActivity { get; set; }
public IActivity Tick( Actor self )
public override IActivity Tick( Actor self )
{
var attack = self.Trait<AttackBase>();
var ret = InnerTick( self, attack );
attack.IsAttacking = ( ret == this );
return ret;
}
IActivity InnerTick( Actor self, AttackBase attack )
{
if (IsCanceled) return NextActivity;
var facing = self.Trait<IFacing>();
if (!Target.IsValid)
return NextActivity;
@@ -37,7 +44,7 @@ namespace OpenRA.Mods.RA.Activities
var targetCell = Util.CellContaining(Target.CenterLocation);
if ((targetCell - self.Location).LengthSquared >= Range * Range)
return new Move( Target, Range ) { NextActivity = this };
return Util.SequenceActivities( new Move( Target, Range ), this );
var desiredFacing = Util.GetFacing((targetCell - self.Location).ToFloat2(), 0);
var renderUnit = self.TraitOrDefault<RenderUnit>();
@@ -47,15 +54,12 @@ namespace OpenRA.Mods.RA.Activities
if (Util.QuantizeFacing(facing.Facing, numDirs)
!= Util.QuantizeFacing(desiredFacing, numDirs))
{
return new Turn( desiredFacing ) { NextActivity = this };
return Util.SequenceActivities( new Turn( desiredFacing ), this );
}
var attack = self.Trait<AttackBase>();
attack.target = Target;
attack.DoAttack(self);
return this;
}
public void Cancel(Actor self) { Target = Target.None; }
}
}

Some files were not shown because too many files have changed in this diff Show More