Basic chronosphere behavior

This commit is contained in:
Paul Chote
2010-01-03 21:51:54 +13:00
parent 67cda2162b
commit 8d761abb4f
12 changed files with 254 additions and 35 deletions

View File

@@ -245,6 +245,22 @@ namespace OpenRa.Game
void DrawButtons()
{
// Chronoshift
Rectangle chronoshiftRect = new Rectangle(6, 14, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
var chronoshiftDrawPos = Game.viewport.Location + new float2(chronoshiftRect.Location);
var hasChronosphere = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<Chronosphere>());
if (!hasChronosphere)
repairButton.ReplaceAnim("disabled");
else
{
//repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
AddButton(chronoshiftRect, isLmb => Game.controller.ToggleInputMode<ChronosphereSelectOrderGenerator>());
}
buildPaletteRenderer.DrawSprite(repairButton.Image, chronoshiftDrawPos, PaletteType.Chrome);
// Repair
Rectangle repairRect = new Rectangle(Game.viewport.Width - 100, 5, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
var repairDrawPos = Game.viewport.Location + new float2(repairRect.Location);

View File

@@ -22,7 +22,8 @@ namespace OpenRa.Game
public static Cursor Deploy { get { return new Cursor("deploy"); } }
public static Cursor Enter { get { return new Cursor("enter"); } }
public static Cursor DeployBlocked { get { return new Cursor("deploy-blocked"); } }
public static Cursor Chronoshift { get { return new Cursor("chrono"); } }
public static Cursor Chronoshift { get { return new Cursor("chrono-target"); } }
public static Cursor ChronoshiftSelect { get { return new Cursor("chrono-select"); } }
public static Cursor C4 { get { return new Cursor("c4"); } }
public static Cursor Capture { get { return new Cursor("capture"); } }
public static Cursor Heal { get { return new Cursor("heal"); } }

View File

@@ -95,6 +95,7 @@
<Compile Include="GameRules\UserSettings.cs" />
<Compile Include="GameRules\VoiceInfo.cs" />
<Compile Include="Effects\IEffect.cs" />
<Compile Include="Orders\ChronosphereSelectOrderGenerator.cs" />
<Compile Include="Orders\IOrderSource.cs" />
<Compile Include="Orders\LocalOrderSource.cs" />
<Compile Include="Effects\Missile.cs" />
@@ -103,7 +104,7 @@
<Compile Include="Orders\OrderManager.cs" />
<Compile Include="Orders\RepairOrderGenerator.cs" />
<Compile Include="Orders\SellOrderGenerator.cs" />
<Compile Include="Orders\TeleportOrderGenerator.cs" />
<Compile Include="Orders\ChronoshiftDestinationOrderGenerator.cs" />
<Compile Include="Ore.cs" />
<Compile Include="PathSearch.cs" />
<Compile Include="ProductionItem.cs" />
@@ -196,6 +197,8 @@
<Compile Include="Traits\BelowUnits.cs" />
<Compile Include="Traits\Building.cs" />
<Compile Include="Traits\C4Demolition.cs" />
<Compile Include="Traits\Chronoshiftable.cs" />
<Compile Include="Traits\Chronosphere.cs" />
<Compile Include="Traits\EngineerCapture.cs" />
<Compile Include="Traits\Explodes.cs" />
<Compile Include="Traits\ChronoshiftDeploy.cs" />

View File

@@ -7,11 +7,11 @@ using OpenRa.Game.Traits;
namespace OpenRa.Game.Orders
{
class TeleportOrderGenerator : IOrderGenerator
class ChronoshiftDestinationOrderGenerator : IOrderGenerator
{
public readonly Actor self;
public TeleportOrderGenerator(Actor self)
public ChronoshiftDestinationOrderGenerator(Actor self)
{
this.self = self;
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Game.GameRules;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Orders
{
class ChronosphereSelectOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
Game.controller.CancelInputMode();
return OrderInner(xy, mi);
}
IEnumerable<Order> OrderInner(int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left)
{
var loc = mi.Location + Game.viewport.Location;
var underCursor = Game.FindUnits(loc, loc)
.Where(a => a.Owner == Game.LocalPlayer
&& a.traits.Contains<Unit>()
&& a.Info.Selectable).FirstOrDefault();
var unit = underCursor != null ? underCursor.Info as UnitInfo : null;
if (unit != null)
{
yield return new Order("ChronosphereSelect", underCursor, null, int2.Zero, null);
}
}
}
public void Tick()
{
var hasChronosphere = Game.world.Actors
.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<Chronosphere>());
if (!hasChronosphere)
Game.controller.CancelInputMode();
}
public void Render() { }
public Cursor GetCursor(int2 xy, MouseInput mi)
{
mi.Button = MouseButton.Left;
return OrderInner(xy, mi).Any()
? Cursor.ChronoshiftSelect : Cursor.MoveBlocked;
}
}
}

View File

@@ -49,7 +49,7 @@ namespace OpenRa.Game.Traits
{
if (order.OrderString == "Deploy")
{
Game.controller.orderGenerator = new TeleportOrderGenerator(self);
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
return;
}
@@ -68,7 +68,7 @@ namespace OpenRa.Game.Traits
public float GetSpeedModifier()
{
// ARGH! You must not do this, it will desync!
return (Game.controller.orderGenerator is TeleportOrderGenerator) ? 0f : 1f;
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
}
// Display 5 pips indicating the current charge status

View File

@@ -0,0 +1,127 @@
using OpenRa.Game.Traits;
using OpenRa.Game.Orders;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
namespace OpenRa.Game.Traits
{
class Chronoshiftable : IOrder, ISpeedModifier, ITick, IPaletteModifier
{
// Return-to-sender logic
int2 chronoshiftOrigin;
int chronoshiftReturnTicks = 0;
// Screen fade logic
int animationTick = 0;
int animationLength = 10;
bool animationStarted = false;
public Chronoshiftable(Actor self) { }
public void Tick(Actor self)
{
if (animationStarted)
{
if (animationTick < animationLength)
animationTick++;
else
animationStarted = false;
}
else if (animationTick > 0)
animationTick--;
if (chronoshiftReturnTicks <= 0)
return;
if (chronoshiftReturnTicks > 0)
chronoshiftReturnTicks--;
// Return to original location
if (chronoshiftReturnTicks == 0)
{
self.CancelActivity();
// Todo: need a new Teleport method that will move to the closest available cell
self.QueueActivity(new Activities.Teleport(chronoshiftOrigin));
}
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
return null; // Chronoshift order is issued through Chrome.
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "ChronosphereSelect")
{
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
}
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault();
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
{
chronoshiftOrigin = self.Location;
chronoshiftReturnTicks = (int)(Rules.General.ChronoDuration * 60 * 25);
// TODO: Kill cargo if Rules.General.ChronoKillCargo says so
Game.controller.CancelInputMode();
self.CancelActivity();
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
Sound.Play("chrono2.aud");
animationStarted = true;
}
}
public float GetSpeedModifier()
{
// ARGH! You must not do this, it will desync!
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
}
public void AdjustPalette(Bitmap bmp)
{
if (!animationStarted && animationTick == 0)
return;
// saturation modifier
var f = 1 - (animationTick * 1.0f / animationLength);
using (var bitmapCopy = new Bitmap(bmp))
for (int j = 0; j < 8; j++)
for (int i = 0; i < bmp.Width; i++)
{
var h = bitmapCopy.GetPixel(i, j).GetHue(); // 0-360
var s = f * bitmapCopy.GetPixel(i, j).GetSaturation(); // 0-1.0
var l = bitmapCopy.GetPixel(i, j).GetBrightness(); // 0-1.0
var alpha = bitmapCopy.GetPixel(i, j).A;
// Convert from HSL to RGB
// Refactor me!
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
var hk = h / 360.0f;
double[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
double[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
// mod doesn't seem to work right... do it manually
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; }
}
bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255)));
}
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.Traits
{
class Chronosphere
{
public Chronosphere(Actor self) { }
}
}

View File

@@ -7,28 +7,28 @@ QTNK
[STNK]
Description=Stealth Tank
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, Cloak
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, Cloak, Chronoshiftable
Recoil=2
Voice=VehicleVoice
[TTNK]
Description=Tesla Tank
Traits=Unit, Mobile, AttackBase, RenderUnitSpinner
Traits=Unit, Mobile, AttackBase, RenderUnitSpinner, Chronoshiftable
Voice=VehicleVoice
[CTNK]
Description=Chrono Tank
Traits=Unit, Mobile, AttackBase, RenderUnit, ChronoshiftDeploy
Traits=Unit, Mobile, AttackBase, RenderUnit, ChronoshiftDeploy, Chronoshiftable
Voice=VehicleVoice
[DTRK]
Description=Demo Truck
Traits=Unit, Mobile, AttackBase, RenderUnit
Traits=Unit, Mobile, AttackBase, RenderUnit, Chronoshiftable
Voice=VehicleVoice
[QTNK]
Description=M.A.D. Tank
Traits=Unit, Mobile, RenderUnit
Traits=Unit, Mobile, RenderUnit, Chronoshiftable
Voice=VehicleVoice
@@ -42,7 +42,7 @@ MSUB
Description=Missile Submarine
WaterBound=yes
BuiltAt=spen
Traits=Unit, Mobile, AttackBase, RenderUnit, Submarine
Traits=Unit, Mobile, AttackBase, RenderUnit, Submarine, Chronoshiftable
FireDelay=2

View File

@@ -376,7 +376,8 @@
<sequence name="default-minimap" start="80" length="1" />
<sequence name="ability" start="82" length="8" />
<sequence name="nuke" start="90" length="7" x="12" y="12" />
<sequence name="chrono" start="105" length="8" x="12" y="12" />
<sequence name="chrono-select" start="97" length="8" x="12" y="12" />
<sequence name="chrono-target" start="105" length="8" x="12" y="12" />
<sequence name="enter" start="113" length="3" x="12" y="12" />
<sequence name="c4" start="116" length="3" x="12" y="12" />
<sequence name="sell-blocked" start="119" length="1" x="12" y="12" />

View File

@@ -9,3 +9,5 @@ s1=Multi2,mcv,600,12445,0,Guard,None
s2=Multi1,mcv,600,12505,0,Guard,None
;s2=Multi1,e3,600,12505,0,Guard,None
s3=Multi3,mcv,600,2910,0,Guard,None
;s4=Multi1,ctnk,600,12506,Gaurd,None
s5=Multi1,pdox,600,12510,Gaurd,None

View File

@@ -16,47 +16,47 @@ MNLY.AT
[V2RL]
Description=V2 Rocket
Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget, Repairable
Traits=Unit, Mobile, AttackBase, RenderUnitReload, AutoTarget, Repairable, Chronoshiftable
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, AutoTarget, Repairable
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable
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, AutoTarget, Repairable
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable
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, AutoTarget, Repairable
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable
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, AutoTarget, Repairable
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable
Voice=VehicleVoice
LongDesc=Big and slow tank, with anti-air capability.\n Strong vs Tanks, Aircraft\n Weak vs Infantry
[ARTY]
Description=Artillery
Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable
Traits=Unit, Mobile, AttackBase, RenderUnit, Explodes, AutoTarget, Repairable, Chronoshiftable
Voice=VehicleVoice
LongDesc=Long-range artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft
[JEEP]
Description=Ranger
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Repairable, Chronoshiftable
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, AutoTarget, Repairable
Traits=Unit, Mobile, AttackBase, RenderUnitMuzzleFlash, AutoTarget, Repairable, Chronoshiftable
PrimaryOffset=0,0,0,-4
MuzzleFlash=yes
Voice=VehicleVoice
@@ -65,40 +65,40 @@ LongDesc=Tough infantry transport.\n Strong vs Infantry, Light Vehicles\n Weak
;; non-combat vehicles
[MRJ]
Description=Radar Jammer
Traits=Unit, Mobile, RenderUnitSpinner, Repairable
Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable
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, Repairable
Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable
PrimaryOffset=0,6,0,-3
SelectionPriority=3
Voice=VehicleVoice
LongDesc=Regenerates Fog of War in a small area \naround the unit.\n Unarmed
[HARV]
Description=Ore Truck
Traits=Harvester, Unit, Mobile, RenderUnit, Repairable
Traits=Harvester, Unit, Mobile, RenderUnit, Repairable, Chronoshiftable
SelectionPriority=7
Voice=VehicleVoice
LongDesc=Collects Ore and Gems for processing.\n Unarmed
[MCV]
Description=Mobile Construction Vehicle
Traits=Unit, Mobile, McvDeploy, RenderUnit, Repairable
Traits=Unit, Mobile, McvDeploy, RenderUnit, Repairable, Chronoshiftable
SelectionPriority=3
Voice=VehicleVoice
LongDesc=Deploys into another Construction Yard.\n Unarmed
[MNLY.AP]
Description=Minelayer (Anti-Personnel)
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo, Chronoshiftable
Voice=VehicleVoice
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
Primary=MINP ;; temporary hack
[MNLY.AT]
Description=Minelayer (Anti-Tank)
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo
Traits=Unit, Mobile, RenderUnit, Minelayer, MineImmune, Repairable, LimitedAmmo, Chronoshiftable
Voice=VehicleVoice
LongDesc=Lays mines to destroy unwary enemy units.\n Unarmed
Primary=MINV ;; temporary hack
@@ -116,21 +116,21 @@ PT
Description=Submarine
WaterBound=yes
BuiltAt=spen
Traits=Unit, Mobile, RenderUnit, Submarine, AttackBase
Traits=Unit, Mobile, RenderUnit, Submarine, AttackBase, Chronoshiftable
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, AutoTarget
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
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
BuiltAt=syrd
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
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
@@ -138,13 +138,13 @@ Recoil=3
[LST]
Description=Transport
WaterBound=yes
Traits=Unit, Mobile, RenderUnit
Traits=Unit, Mobile, RenderUnit, Chronoshiftable
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, AutoTarget
Traits=Unit, Mobile, Turreted, AttackTurreted, RenderUnitTurreted, AutoTarget, Chronoshiftable
PrimaryOffset=0,-6,0,-1
LongDesc=Light scout & support ship. \n Strong vs Ships, Submarines\n Weak vs Aircraft
@@ -289,7 +289,7 @@ SelectionPriority=3
LongDesc=Makes a group of units invulnerable for a \nshort time.\n Special Ability: Invulnerability
[PDOX]
Description=Chronosphere
Traits=Building, RenderBuilding
Traits=Building, RenderBuilding, Chronosphere
Dimensions=2,2
Footprint=xx xx
SelectionPriority=3