diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 2199061a77..9b7f1e63bd 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -7,6 +7,7 @@ using IjwFramework.Collections; using IjwFramework.Types; using OpenRa.Game.Graphics; using OpenRa.Game.Support; +using OpenRa.Game.GameRules; namespace OpenRa.Game { @@ -17,6 +18,7 @@ namespace OpenRa.Game readonly SpriteRenderer chromeRenderer; readonly Sprite specialBinSprite; readonly Sprite moneyBinSprite; + readonly Sprite tooltipSprite; readonly SpriteRenderer buildPaletteRenderer; readonly Animation cantBuild; readonly Animation ready; @@ -37,6 +39,7 @@ namespace OpenRa.Game specialBinSprite = new Sprite(specialBin, new Rectangle(0, 0, 32, 192), TextureChannel.Alpha); moneyBinSprite = new Sprite(specialBin, new Rectangle(512 - 320, 0, 320, 32), TextureChannel.Alpha); + tooltipSprite = new Sprite(specialBin, new Rectangle(0, 288, 272, 136), TextureChannel.Alpha); blank = SheetBuilder.Add(new Size(64, 48), 16); @@ -90,8 +93,8 @@ namespace OpenRa.Game Game.orderManager.FrameNumber, PerfHistory.items["render"].LastValue, PerfHistory.items["tick_time"].LastValue, - Game.LocalPlayer.powerDrained, - Game.LocalPlayer.powerProvided, + Game.LocalPlayer.PowerDrained, + Game.LocalPlayer.PowerProvided, Game.LocalPlayer.IsReady ? "Yes" : "No" ), new int2(140, 5), Color.White); @@ -214,6 +217,9 @@ namespace OpenRa.Game var overlayBits = new List>(); + string tooltipItem = null; + int2 tooltipPos = int2.Zero; + foreach (var item in allItems) { var rect = new Rectangle(Game.viewport.Width - (3 - x) * 64, 40 + 48 * y, 64, 48); @@ -223,6 +229,12 @@ namespace OpenRa.Game buildPaletteRenderer.DrawSprite(sprites[item], drawPos, 0); + if (rect.Contains(lastMousePos.ToPoint())) + { + tooltipItem = item; + tooltipPos = new int2(rect.Location); + } + if (!buildableItems.Contains(item) || isBuildingSomethingElse) overlayBits.Add(Pair.New(cantBuild.Image, drawPos)); @@ -271,6 +283,9 @@ namespace OpenRa.Game chromeRenderer.DrawSprite(shimSprites[0], new float2(Game.viewport.Width - 192 - 9, 40 - 9), 0); chromeRenderer.DrawSprite(shimSprites[1], new float2(Game.viewport.Width - 192 - 9, 40 - 1 + 48 * y), 0); chromeRenderer.Flush(); + + if (tooltipItem != null) + DrawProductionTooltip(tooltipItem, tooltipPos); } void HandleBuildPalette(string item, bool isLmb) @@ -322,8 +337,12 @@ namespace OpenRa.Game } } + int2 lastMousePos; public bool HandleInput(MouseInput mi) { + if (mi.Event == MouseInputEvent.Move) + lastMousePos = mi.Location; + var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint())) .Select(a => a.Second).FirstOrDefault(); @@ -340,5 +359,46 @@ namespace OpenRa.Game { return buttons.Any(a => a.First.Contains(mousePos.ToPoint())); } + + void DrawRightAligned(string text, int2 pos, Color c) + { + renderer.DrawText2(text, pos - new int2(renderer.MeasureText2(text).X, 0), c); + } + + void DrawProductionTooltip(string unit, int2 pos) + { + var p = pos.ToFloat2() - new float2(tooltipSprite.size.X, 0); + chromeRenderer.DrawSprite(tooltipSprite, p, 0); + chromeRenderer.Flush(); + + var info = Rules.UnitInfo[unit]; + + renderer.DrawText2(info.Description, p.ToInt2() + new int2(5,5), Color.White); + + DrawRightAligned( "${0}".F(info.Cost), pos + new int2(-5,5), + Game.LocalPlayer.Cash + Game.LocalPlayer.Ore >= info.Cost ? Color.White : Color.Red); + + var bi = info as BuildingInfo; + if (bi != null) + DrawRightAligned("ϟ{0}".F(bi.Power), pos + new int2(-5, 20), + Game.LocalPlayer.PowerProvided - Game.LocalPlayer.PowerDrained + bi.Power >= 0 + ? Color.White : Color.Red); + + var buildings = Rules.TechTree.GatherBuildings( Game.LocalPlayer ); + p += new int2(5, 5); + p += new int2(0, 15); + if (!Rules.TechTree.CanBuild(info, Game.LocalPlayer, buildings)) + { + var prereqs = info.Prerequisite.Select(a => Rules.UnitInfo[a.ToLowerInvariant()].Description); + renderer.DrawText("Requires {0}".F( string.Join( ", ", prereqs.ToArray() ) ), p.ToInt2(), + Color.White); + } + + if (info.LongDesc != null) + { + p += new int2(0, 15); + renderer.DrawText(info.LongDesc.Replace( "\\n", "\n" ), p.ToInt2(), Color.White); + } + } } } diff --git a/OpenRa.Game/GameRules/UnitInfo.cs b/OpenRa.Game/GameRules/UnitInfo.cs index b464020e45..0bb6b3a78d 100755 --- a/OpenRa.Game/GameRules/UnitInfo.cs +++ b/OpenRa.Game/GameRules/UnitInfo.cs @@ -50,6 +50,7 @@ namespace OpenRa.Game.GameRules public readonly int InitialFacing = 128; public readonly bool Selectable = true; public readonly int FireDelay = 0; + public readonly string LongDesc = null; public UnitInfo(string name) { Name = name; } } diff --git a/OpenRa.Game/Graphics/Renderer.cs b/OpenRa.Game/Graphics/Renderer.cs index 7476de583d..e516a06acb 100644 --- a/OpenRa.Game/Graphics/Renderer.cs +++ b/OpenRa.Game/Graphics/Renderer.cs @@ -17,7 +17,7 @@ namespace OpenRa.Game.Graphics public Shader RgbaSpriteShader { get; private set; } readonly SpriteHelper sh; - readonly FontHelper fhDebug; + readonly FontHelper fhDebug, fhTitle; public void BuildPalette(Map map) { @@ -44,6 +44,7 @@ namespace OpenRa.Game.Graphics sh = new SpriteHelper(device); fhDebug = new FontHelper(device, "Tahoma", 10, false); + fhTitle = new FontHelper(device, "Tahoma", 10, true); } public GraphicsDevice Device { get { return device; } } @@ -107,9 +108,21 @@ namespace OpenRa.Game.Graphics sh.End(); } + public void DrawText2(string text, int2 pos, Color c) + { + sh.Begin(); + fhTitle.Draw(sh, text, pos.X, pos.Y, c.ToArgb()); + sh.End(); + } + public int2 MeasureText(string text) { return new int2(fhDebug.MeasureText(sh, text)); } + + public int2 MeasureText2(string text) + { + return new int2(fhTitle.MeasureText(sh, text)); + } } } diff --git a/OpenRa.Game/Player.cs b/OpenRa.Game/Player.cs index 8d3a560cff..abd3e1400e 100644 --- a/OpenRa.Game/Player.cs +++ b/OpenRa.Game/Player.cs @@ -19,8 +19,8 @@ namespace OpenRa.Game public int Cash; public int Ore; public int DisplayCash; - public int powerProvided; - public int powerDrained; + public int PowerProvided; + public int PowerDrained; public bool IsReady; @@ -34,15 +34,15 @@ namespace OpenRa.Game this.Cash = 10000; this.Ore = 0; this.DisplayCash = 0; - this.powerProvided = this.powerDrained = 0; + this.PowerProvided = this.PowerDrained = 0; } void UpdatePower() { - var oldBalance = powerProvided - powerDrained; + var oldBalance = PowerProvided - PowerDrained; - powerProvided = 0; - powerDrained = 0; + PowerProvided = 0; + PowerDrained = 0; var myBuildings = Game.world.Actors .Where(a => a.Owner == this && a.traits.Contains()); @@ -51,13 +51,13 @@ namespace OpenRa.Game { var bi = a.Info as BuildingInfo; if (bi.Power > 0) /* todo: is this how real-ra scales it? */ - powerProvided += (a.Health * bi.Power) / bi.Strength; + PowerProvided += (a.Health * bi.Power) / bi.Strength; else - powerDrained -= bi.Power; + PowerDrained -= bi.Power; } - if (powerProvided - powerDrained < 0) - if (powerProvided - powerDrained != oldBalance) + if (PowerProvided - PowerDrained < 0) + if (PowerProvided - PowerDrained != oldBalance) GiveAdvice("lopower1.aud"); } @@ -68,8 +68,8 @@ namespace OpenRa.Game public PowerState GetPowerState() { - if (powerProvided >= powerDrained) return PowerState.Normal; - if (powerProvided > powerDrained / 2) return PowerState.Low; + if (PowerProvided >= PowerDrained) return PowerState.Normal; + if (PowerProvided > PowerDrained / 2) return PowerState.Low; return PowerState.Critical; } diff --git a/artsrc/bits.psd b/artsrc/bits.psd index e9b91efd0f..157a1ff1db 100644 Binary files a/artsrc/bits.psd and b/artsrc/bits.psd differ diff --git a/specialbin.png b/specialbin.png index b58be310c6..9985343d8c 100644 Binary files a/specialbin.png and b/specialbin.png differ diff --git a/units.ini b/units.ini index 3b3af5c587..b5ec8f50af 100755 --- a/units.ini +++ b/units.ini @@ -17,68 +17,80 @@ MNLY Description=V2 Rocket Traits=Unit, Mobile, AttackBase, RenderUnitReload Voice=VehicleVoice +LongDesc=Long-range rocket artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft [1TNK] Description=Light Tank Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted Recoil=2 Voice=VehicleVoice +LongDesc=Light Tank, good for scouting.\n Strong vs Light Vehicles\n Weak vs Tanks, Aircraft [2TNK] Description=Medium Tank Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted Recoil=3 Voice=VehicleVoice +LongDesc=Allied Main Battle Tank.\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft [3TNK] Description=Heavy Tank Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted Recoil=3 Voice=VehicleVoice +LongDesc=Soviet Main Battle Tank, with dual cannons\n Strong vs Tanks, Light Vehicles\n Weak vs Infantry, Aircraft [4TNK] Description=Mammoth Tank Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted Voice=VehicleVoice +LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry [MRJ] Description=Radar Jammer Traits=Unit, Mobile, RenderUnitSpinner PrimaryOffset=0,4,0,-6 SelectionPriority=3 Voice=VehicleVoice +LongDesc=Hides nearby units on the enemy's minimap.\n Unarmed [MGG] Description=Mobile Gap Generator Traits=Unit, Mobile, RenderUnitSpinner PrimaryOffset=0,6,0,-3 SelectionPriority=3 Voice=VehicleVoice +LongDesc=Regenerates Fog of War in a small area \naround the unit.\n Unarmed [ARTY] Description=Artillery Traits=Unit, Mobile, AttackBase, RenderUnit Voice=VehicleVoice +LongDesc=Long-range artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft [HARV] Description=Ore Truck Traits=Harvester, Unit, Mobile, RenderUnit SelectionPriority=7 Voice=VehicleVoice +LongDesc=Collects Ore and Gems for processing.\n Unarmed [MCV] Description=Mobile Construction Vehicle Traits=Unit, Mobile, McvDeploy, RenderUnit SelectionPriority=3 Voice=VehicleVoice +LongDesc=Deploys into another Construction Yard.\n Unarmed [JEEP] Description=Ranger Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted PrimaryOffset=0,0,0,-2 MuzzleFlash=yes Voice=VehicleVoice +LongDesc=Fast scout & anti-infantry vehicle.\n Strong vs Infantry\n Weak vs Tanks, Aircraft [APC] Description=Armored Personnel Carrier Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash PrimaryOffset=0,0,0,-4 MuzzleFlash=yes Voice=VehicleVoice +LongDesc=Tough infantry transport.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft [MNLY] Description=Minelayer Traits=Unit, Mobile, RenderUnit Voice=VehicleVoice - +LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed @@ -96,12 +108,14 @@ WaterBound=yes BuiltAt=spen Traits=Unit, Mobile, RenderUnit, Cloak, AttackBase FireDelay=2 +LongDesc=Submerged anti-ship unit armed with \ntorpedoes.\n Strong vs Ships\n Weak vs Everything\n Special Ability: Submerge [DD] Description=Destroyer WaterBound=yes BuiltAt=syrd Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted PrimaryOffset=0,-8,0,-3 +LongDesc=Fast multi-role ship. \n Strong vs Submarines, Aircraft\n Weak vs Infantry, Tanks [CA] Description=Cruiser WaterBound=yes @@ -109,17 +123,20 @@ BuiltAt=syrd Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted PrimaryOffset=0,17,0,-2 SecondaryOffset=0,-17,0,-2 +LongDesc=Very slow long-range ship. \n Strong vs Buildings\n Weak vs Ships, Submarines Recoil=3 [LST] Description=Transport WaterBound=yes Traits=Unit, Mobile, RenderUnit +LongDesc=General-purpose naval transport.\nCan carry infantry and tanks.\n Unarmed [PT] Description=Gunboat WaterBound=yes BuiltAt=syrd Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted PrimaryOffset=0,-6,0,-1 +LongDesc=Light scout & support ship. \n Strong vs Ships, Submarines\n Weak vs Aircraft @@ -140,11 +157,13 @@ Description=Mig Attack Plane BuiltAt=afld Traits=Unit, Mobile, RenderUnit InitialFacing=192 +LongDesc=Fast Ground-Attack Plane.\n Strong vs Buildings\n Weak vs Infantry, Light Vehicles [YAK] Description=Yak Attack Plane BuiltAt=afld Traits=Unit, Mobile, RenderUnit InitialFacing=192 +LongDesc=Anti-Tanks & Anti-Infantry Plane.\n Strong vs Infantry, Tanks\n Weak vs Buildings [TRAN] Description=Transport Helicopter PrimaryOffset=0,14,0,-4 @@ -153,18 +172,20 @@ BuiltAt=hpad Traits=Unit, Helicopter, RenderUnitRotor SecondaryAnim=rotor2 InitialFacing=20 +LongDesc=Fast Infantry Transport Helicopter.\n Unarmed [HELI] Description=Longbow BuiltAt=hpad Traits=Unit, Helicopter, RenderUnitRotor PrimaryOffset=0,0,0,-2 InitialFacing=20 +LongDesc=Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry [HIND] Description=Hind BuiltAt=hpad Traits=Unit, Helicopter, RenderUnitRotor InitialFacing=20 - +LongDesc=Helicopter Gunship with Chainguns.\n Strong vs Infantry, Light Vehicles.\n Weak vs Tanks @@ -192,12 +213,14 @@ Traits=Building, Turreted, RenderBuilding, AttackTurreted, AutoTarget Dimensions=1,1 Footprint=x SelectionPriority=3 +LongDesc=Basic defensive structure.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft [HBOX] Description=Camo Pillbox Traits=Building, Turreted, RenderBuilding, AttackTurreted, AutoTarget Dimensions=1,1 Footprint=x SelectionPriority=3 +LongDesc=Hidden defensive structure.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft [TSLA] Description=Tesla Coil Traits=Building, Turreted, RenderBuildingCharge, AttackTurreted, AutoTarget @@ -205,6 +228,7 @@ Dimensions=1,2 Footprint=_ x SelectionPriority=3 FireDelay=8 +LongDesc=Advanced base defense. Requires power\nto operate.\n Strong vs Tanks, Infantry\n Weak vs Aircraft [GUN] Description=Turret Traits=Building, Turreted, RenderBuildingTurreted, AttackTurreted, AutoTarget @@ -212,6 +236,7 @@ Dimensions=1,1 Footprint=x SelectionPriority=3 InitialFacing=50 +LongDesc=Anti-Armor base defense.\n Strong vs Tanks\n Weak vs Infantry, Aircraft [AGUN] Description=AA Gun Traits=Building, Turreted, RenderBuildingTurreted @@ -219,30 +244,49 @@ Dimensions=1,2 Footprint=_ x SelectionPriority=3 InitialFacing=224 +LongDesc=Anti-Air base defense.\n Strong vs Aircraft\n Weak vs Infantry, Tanks [FTUR] Description=Flame Turret Traits=Building, RenderBuilding Dimensions=1,1 Footprint=x SelectionPriority=3 +LongDesc=Anti-Infantry base defense.\n Strong vs Infantry\n Weak vs Aircraft [GAP] Description=Gap Generator Traits=Building, RenderBuilding Dimensions=1,2 Footprint=_ x SelectionPriority=3 +LongDesc=Regenerates the Fog of War nearby, \nobscuring the area.\n Unarmed [SAM] Description=SAM Site Traits=Building, Turreted, RenderBuildingTurreted Dimensions=2,1 Footprint=xx SelectionPriority=3 +LongDesc=Anti-Air base defense.\n Strong vs Aircraft\n Weak vs Infantry, Tanks [MSLO] Description=Missile Silo Traits=Building, RenderBuilding Dimensions=2,1 Footprint=xx SelectionPriority=3 +LongDesc=Launches a devastating nuclear strike.\n Strong vs Infantry, Buildings\n Weak vs Tanks\n Special Ability: Nuclear Missile +[IRON] +Description=Iron Curtain +Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx +SelectionPriority=3 +LongDesc=Makes a group of units invulnerable for a \nshort time.\n Special Ability: Invulnerability +[PDOX] +Description=Chronosphere +Traits=Building, RenderBuilding +Dimensions=2,2 +Footprint=xx xx +SelectionPriority=3 +LongDesc=Teleports a group of units from one place \nto another, for a limited time.\n Special Ability: Chronoshift @@ -279,24 +323,13 @@ DOMF ; x : Solid. cannot be walked on or built on. ; = : Occupied by a building, but can be walked on normally. (e.g: the drop-off point on the refinery) ; `Produces` is a category of objects that this building can produce. -[IRON] -Description=Iron Curtain -Traits=Building, RenderBuilding -Dimensions=2,2 -Footprint=xx xx -SelectionPriority=3 [ATEK] Description=Allied Tech Center Traits=Building, RenderBuilding Dimensions=2,2 Footprint=xx xx SelectionPriority=3 -[PDOX] -Description=Chronosphere -Traits=Building, RenderBuilding -Dimensions=2,2 -Footprint=xx xx -SelectionPriority=3 +LongDesc=Provides Allied advanced technologies.\n Special Ability: GPS Satellite [WEAP] Description=War Factory Traits=Building, RenderWarFactory, RallyPoint, Production @@ -305,6 +338,7 @@ Footprint=xxx xxx Produces=Vehicle RallyPoint=1,3 SelectionPriority=3 +LongDesc=Produces tanks & light vehicles. [SYRD] Description=Shipyard Traits=Building, RenderBuilding, ProductionSurround @@ -312,6 +346,7 @@ Dimensions=3,3 Footprint=xxx xxx xxx Produces=Ship SelectionPriority=3 +LongDesc=Produces and repairs ships [SPEN] Description=Sub Pen Traits=Building, RenderBuilding, ProductionSurround @@ -319,6 +354,7 @@ Dimensions=3,3 Footprint=xxx xxx xxx Produces=Ship SelectionPriority=3 +LongDesc=Produces and repairs submarines and \ntransports [FACT] Description=Construction Yard Traits=Building, RenderBuilding @@ -326,18 +362,21 @@ Dimensions=3,3 Footprint=xxx xxx xxx Produces=Building,Defense SelectionPriority=3 +LongDesc=Produces other structures [PROC] Description=Ore Refinery Traits=Building, RenderBuilding, AcceptsOre Dimensions=3,3 Footprint=_x_ xxx x== SelectionPriority=3 +LongDesc=Converts Ore and Gems into money [SILO] Description=Silo Traits=Building, RenderBuildingOre Dimensions=1,1 Footprint=x SelectionPriority=3 +LongDesc=Stores excess harvested Ore [HPAD] Description=Helipad Traits=Building, RenderBuilding, Production @@ -346,12 +385,14 @@ Footprint=xx xx Produces=Plane SelectionPriority=3 SpawnOffset=0,0 ; todo: push this up a bit, but we've got a z-order issue first. +LongDesc=Produces and reloads helicopters [DOME] Description=Radar Dome Traits=Building, RenderBuilding Dimensions=2,2 Footprint=xx xx SelectionPriority=3 +LongDesc=Provides an overview of the battlefield.\n Requires power to operate. [AFLD] Description=Airstrip Traits=Building, RenderBuilding, Production @@ -359,24 +400,28 @@ Dimensions=3,2 Footprint=xxx xxx Produces=Plane SelectionPriority=3 +LongDesc=Produces and reloads planes\n Special Ability: Paratroopers\n Special Ability: Spy Plane [POWR] Description=Power Plant Traits=Building, RenderBuilding Dimensions=2,2 Footprint=xx xx SelectionPriority=3 +LongDesc=Provides power for other structures [APWR] Description=Advanced Power Plant Traits=Building, RenderBuilding Dimensions=3,3 Footprint=___ xxx xxx SelectionPriority=3 +LongDesc=Provides more power, cheaper than the \nstandard Power Plant [STEK] Description=Soviet Tech Center Traits=Building, RenderBuilding Dimensions=3,2 Footprint=xxx xxx SelectionPriority=3 +LongDesc=Provides Soviet advanced technologies [BARR] Description=Soviet Barracks Traits=Building, RenderBuilding, RallyPoint, Production @@ -385,6 +430,7 @@ Footprint=xx xx Produces=Infantry RallyPoint=1,3 SelectionPriority=3 +LongDesc=Produces infantry [TENT] Description=Allied Barracks Traits=Building, RenderBuilding, RallyPoint, Production @@ -393,6 +439,7 @@ Footprint=xx xx Produces=Infantry RallyPoint=1,3 SelectionPriority=3 +LongDesc=Produces infantry [KENN] Description=Kennel Traits=Building, RenderBuilding, RallyPoint, Production @@ -400,42 +447,49 @@ Dimensions=1,1 Footprint=x RallyPoint=1,2 SelectionPriority=3 +LongDesc=Produces attack dogs [FIX] Description=Service Depot Traits=Building, RenderBuilding Dimensions=3,3 Footprint=_x_ xxx _x_ SelectionPriority=3 +LongDesc=Repairs vehicles, reloads minelayers, and \nallows the construction of additional bases. [FACF] Description=Fake Construction Yard Traits=Building, RenderBuilding Dimensions=3,3 Footprint=xxx xxx xxx SelectionPriority=3 +LongDesc=Looks like a Construction Yard. [WEAF] Description=Fake War Factory Traits=Building, RenderWarFactory Dimensions=3,2 Footprint=xxx xxx SelectionPriority=3 +LongDesc=Looks like a War Factory. [SYRF] Description=Fake Shipyard Traits=Building, RenderBuilding Dimensions=3,3 Footprint=xxx xxx xxx SelectionPriority=3 +LongDesc=Looks like a Shipyard [SPEF] Description=Fake Sub Pen Traits=Building, RenderBuilding Dimensions=3,3 Footprint=xxx xxx xxx SelectionPriority=3 +LongDesc=Looks like a Sub Pen [DOMF] Description=Fake Radar Dome Traits=Building, RenderBuilding Dimensions=2,2 Footprint=xx xx SelectionPriority=3 +LongDesc=Looks like a Radar Dome ;[SBAG] ;Description=Sandbags ;SelectionPriority=3 @@ -467,29 +521,36 @@ Description=Attack Dog BuiltAt=KENN Voice=DogVoice Traits=Unit, Mobile, RenderInfantry +LongDesc=Anti-infantry unit. Not fooled by the \nSpy's disguise.\n Strong vs Infantry\n Weak vs Vehicles [E1] Description=Rifle Infantry Traits=Unit, Mobile, RenderInfantry, AttackBase +LongDesc=General-purpose infantry. Strong vs Infantry\n Weak vs Vehicles [E2] Description=Grenadier Traits=Unit, Mobile, RenderInfantry, AttackBase FireDelay=15 +LongDesc=Infantry armed with grenades. \n Strong vs Buildings, Infantry\n Weak vs Vehicles [E3] Description=Rocket Soldier Traits=Unit, Mobile, RenderInfantry, AttackBase PrimaryOffset=0,0,0,-13 +LongDesc=Anti-tank/Anti-aircraft infantry.\n Strong vs Tanks, Aircraft\n Weak vs Infantry [E4] Description=Flamethrower Traits=Unit, Mobile, RenderInfantry, AttackBase FireDelay=8 +LongDesc=Advanced Anti-infantry unit.\n Strong vs Infantry, Buildings\n Weak vs Vehicles [E6] Description=Engineer Traits=Unit, Mobile, RenderInfantry Voice=EngineerVoice +LongDesc=Infiltrates and captures enemy structures.\n Strong vs Nothing\n Weak vs Everything [SPY] Description=Spy Voice=SpyVoice Traits=Unit, Mobile, RenderInfantry +LongDesc=Infiltrates enemy structures to gather \nintelligence. Exact effect depends on the \nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised [THF] Description=Thief Voice=MedicVoice @@ -497,10 +558,12 @@ Voice=MedicVoice Description=Tanya Voice=TanyaVoice Traits=Unit, Mobile, RenderInfantry, AttackBase +LongDesc=Elite commando infantry, armed with \ndual pistols and C4.\n Strong vs Infantry, Buildings\n Weak vs Vehicles\n Special Ability: Destroy Building with C4 [MEDI] Description=Medic Voice=MedicVoice Traits=Unit, Mobile, RenderInfantry, AttackBase +LongDesc=Heals nearby infantry.\n Strong vs Nothing\n Weak vs Everything