Merge branch 'master' into minelayer
This commit is contained in:
@@ -50,7 +50,6 @@ namespace OpenRa.Game
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
@@ -93,11 +92,8 @@ namespace OpenRa.Game
|
||||
if (!Rules.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
// HACK: Get the first unit in the cell
|
||||
// This will need to be updated for multiple-infantry-in-a-cell
|
||||
// HACK: this doesn't work for targeting air units either
|
||||
var underCursor = Game.UnitInfluence.GetUnitsAt( xy ).FirstOrDefault()
|
||||
?? Game.BuildingInfluence.GetBuildingAt( xy );
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc).FirstOrDefault();
|
||||
|
||||
if (underCursor != null && !underCursor.Info.Selectable)
|
||||
underCursor = null;
|
||||
@@ -107,19 +103,18 @@ namespace OpenRa.Game
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
|
||||
public RectangleF Bounds
|
||||
public RectangleF GetBounds(bool useAltitude)
|
||||
{
|
||||
get
|
||||
var size = SelectedSize;
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var size = SelectedSize;
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
var unit = traits.GetOrDefault<Unit>();
|
||||
|
||||
if (unit != null)
|
||||
loc -= new float2(0, unit.Altitude);
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
if (unit != null) loc -= new float2(0, unit.Altitude);
|
||||
}
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsDead { get { return Health <= 0; } }
|
||||
@@ -150,6 +145,8 @@ namespace OpenRa.Game
|
||||
|
||||
Game.world.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
if (Health > Info.Strength)
|
||||
Health = Info.Strength;
|
||||
|
||||
var newState = GetDamageState();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenRa.Game
|
||||
|
||||
static float GetMaximumSpread(WeaponInfo weapon, WarheadInfo warhead)
|
||||
{
|
||||
return (int)(warhead.Spread * Math.Log(weapon.Damage, 2));
|
||||
return (int)(warhead.Spread * Math.Log(Math.Abs(weapon.Damage), 2));
|
||||
}
|
||||
|
||||
static float GetDamageToInflict(Actor target, int2 loc, WeaponInfo weapon, WarheadInfo warhead)
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace OpenRa.Game
|
||||
{
|
||||
var mods = GetModifierKeys();
|
||||
var c = (orderGenerator is UnitOrderGenerator) ? orderGenerator.Order(dragEnd.ToInt2(),
|
||||
new MouseInput { Button = MouseButton.Right, Modifiers = mods })
|
||||
new MouseInput { Location = (Game.CellSize * dragEnd - Game.viewport.Location).ToInt2(), Button = MouseButton.Right, Modifiers = mods })
|
||||
.Where(o => o.Validate())
|
||||
.Select(o => CursorForOrderString(o.OrderString, o.Subject, o.TargetLocation))
|
||||
.FirstOrDefault(a => a != null) : null;
|
||||
|
||||
@@ -269,13 +269,19 @@ namespace OpenRa.Game
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
return world.Actors
|
||||
.Where(x => x.Bounds.IntersectsWith(rect));
|
||||
.Where(x => x.GetBounds(true).IntersectsWith(rect));
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnitsInCircle(float2 a, float r)
|
||||
{
|
||||
return FindUnits(a - new float2(r, r), a + new float2(r, r))
|
||||
.Where(x => (x.CenterLocation - a).LengthSquared < r * r);
|
||||
var min = a - new float2(r, r);
|
||||
var max = a + new float2(r, r);
|
||||
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
var inBox = world.Actors.Where(x => x.GetBounds(false).IntersectsWith(rect));
|
||||
|
||||
return inBox.Where(x => (x.CenterLocation - a).LengthSquared < r * r);
|
||||
}
|
||||
|
||||
public static IEnumerable<int2> FindTilesInCircle(int2 a, int r)
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace OpenRa.Game.Graphics
|
||||
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
|
||||
{
|
||||
var bounds = selectedUnit.Bounds;
|
||||
var bounds = selectedUnit.GetBounds(true);
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
|
||||
@@ -172,6 +172,7 @@
|
||||
<Compile Include="Traits\AttackBase.cs" />
|
||||
<Compile Include="Traits\AttackInfo.cs" />
|
||||
<Compile Include="Traits\AttackTurreted.cs" />
|
||||
<Compile Include="Traits\AutoHeal.cs" />
|
||||
<Compile Include="Traits\AutoTarget.cs" />
|
||||
<Compile Include="Traits\BelowUnits.cs" />
|
||||
<Compile Include="Traits\Building.cs" />
|
||||
|
||||
64
OpenRa.Game/Traits/AutoHeal.cs
Normal file
64
OpenRa.Game/Traits/AutoHeal.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRa.Game.Traits
|
||||
{
|
||||
class AutoHeal : ITick
|
||||
{
|
||||
public AutoHeal(Actor self) { }
|
||||
|
||||
void AttackTarget(Actor self, Actor target)
|
||||
{
|
||||
var attack = self.traits.WithInterface<AttackBase>().First();
|
||||
if (target != null)
|
||||
attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null));
|
||||
else
|
||||
self.CancelActivity();
|
||||
}
|
||||
|
||||
float GetMaximumRange(Actor self)
|
||||
{
|
||||
return new[] { self.Info.Primary, self.Info.Secondary }
|
||||
.Where(w => w != null)
|
||||
.Max(w => Rules.WeaponInfo[w].Range);
|
||||
}
|
||||
|
||||
bool NeedsNewTarget(Actor self)
|
||||
{
|
||||
var attack = self.traits.WithInterface<AttackBase>().First();
|
||||
var range = GetMaximumRange(self);
|
||||
|
||||
if (attack.target == null)
|
||||
return true; // he's dead.
|
||||
if ((attack.target.Location - self.Location).LengthSquared > range * range + 2)
|
||||
return true; // wandered off faster than we could follow
|
||||
if (attack.target.Health == attack.target.Info.Strength)
|
||||
return true; // fully healed
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
var attack = self.traits.WithInterface<AttackBase>().First();
|
||||
var range = GetMaximumRange(self);
|
||||
|
||||
if (NeedsNewTarget(self))
|
||||
AttackTarget(self, ChooseTarget(self, range));
|
||||
}
|
||||
|
||||
Actor ChooseTarget(Actor self, float range)
|
||||
{
|
||||
var inRange = Game.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
|
||||
return inRange
|
||||
.Where(a => a.Owner == self.Owner) /* todo: one day deal with friendly players */
|
||||
.Where(a => Combat.HasAnyValidWeapons(self, a))
|
||||
.Where(a => a.Health < a.Info.Strength)
|
||||
.OrderBy(a => (a.Location - self.Location).LengthSquared)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,23 @@ namespace OpenRa.Game.Traits
|
||||
attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null));
|
||||
}
|
||||
|
||||
float GetMaximumRange(Actor self)
|
||||
{
|
||||
return new[] { self.Info.Primary, self.Info.Secondary }
|
||||
.Where(w => w != null)
|
||||
.Max(w => Rules.WeaponInfo[w].Range);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (!self.IsIdle) return;
|
||||
|
||||
var attack = self.traits.WithInterface<AttackBase>().First();
|
||||
var range = Rules.WeaponInfo[self.Info.Primary].Range;
|
||||
var range = GetMaximumRange(self);
|
||||
|
||||
if (attack.target == null ||
|
||||
(attack.target.Location - self.Location).LengthSquared > range * range + 2)
|
||||
attack.target = ChooseTarget(self, range);
|
||||
AttackTarget(self, ChooseTarget(self, range));
|
||||
}
|
||||
|
||||
Actor ChooseTarget(Actor self, float range)
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRa.Game.Traits
|
||||
{
|
||||
if (doneBuilding) roof.Tick();
|
||||
|
||||
var b = self.Bounds;
|
||||
var b = self.GetBounds(false);
|
||||
if (isOpen && !Game.UnitInfluence.GetUnitsAt(((1/24f) * self.CenterLocation).ToInt2()).Any())
|
||||
{
|
||||
isOpen = false;
|
||||
|
||||
Reference in New Issue
Block a user